import { test, expect } from '@playwright/test'; // The demo widget is rendered server-side via El components and injected into // the landing page. Element IDs are stable: #neuron-demo-panel, #neuron-demo-btn, // #neuron-demo-auth, #neuron-demo-text, #neuron-demo-send, etc. test.describe('Demo chat widget — structure', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); await page.waitForLoadState('domcontentloaded'); }); test('Demo panel (#neuron-demo-panel) is in the DOM', async ({ page }) => { await expect(page.locator('#neuron-demo-panel')).toBeAttached(); }); test('Demo open button (#neuron-demo-btn) is in the DOM', async ({ page }) => { await expect(page.locator('#neuron-demo-btn')).toBeAttached(); }); test('Demo auth section (#neuron-demo-auth) is in the DOM', async ({ page }) => { await expect(page.locator('#neuron-demo-auth')).toBeAttached(); }); test('Demo text input (#neuron-demo-text) is in the DOM', async ({ page }) => { await expect(page.locator('#neuron-demo-text')).toBeAttached(); }); test('Demo send button (#neuron-demo-send) is in the DOM', async ({ page }) => { await expect(page.locator('#neuron-demo-send')).toBeAttached(); }); }); test.describe('Demo chat widget — auth gate', () => { test.beforeEach(async ({ page }) => { // Clear any stored Supabase session so we test the unauthenticated state await page.goto('/'); await page.evaluate(() => { Object.keys(localStorage) .filter(k => k.startsWith('sb-') || k.includes('supabase')) .forEach(k => localStorage.removeItem(k)); }); await page.reload(); await page.waitForLoadState('domcontentloaded'); }); test('Send button is disabled when unauthenticated', async ({ page }) => { const sendBtn = page.locator('#neuron-demo-send'); await expect(sendBtn).toBeAttached(); // The send button starts disabled until a valid session is confirmed const isDisabled = await sendBtn.isDisabled().catch(() => true); const isHidden = !(await sendBtn.isVisible().catch(() => false)); expect(isDisabled || isHidden).toBe(true); }); test('Auth gate (#neuron-demo-auth) or gate (#neuron-demo-gate) is visible or panel is closed', async ({ page }) => { // Either the auth pane is visible, OR the panel itself is closed (not visible). // Both are correct unauthenticated states. const authVisible = await page.locator('#neuron-demo-auth').isVisible().catch(() => false); const gateVisible = await page.locator('#neuron-demo-gate').isVisible().catch(() => false); const panelClosed = !(await page.locator('#neuron-demo-panel').isVisible().catch(() => true)); expect(authVisible || gateVisible || panelClosed).toBe(true); }); }); test.describe('Demo chat widget — API gate (no browser session)', () => { test('/api/demo rejects unauthenticated POST and returns auth_required', async ({ page }) => { // Use the Playwright request context to hit the API directly const r = await page.request.post('/api/demo', { data: { message: 'Hello Neuron' }, }); const body = await r.json() as Record; expect(body.auth_required).toBe(true); }); });