From 6b5d461cafce4dd121ac2b68a9f7a7a6e4f04fe2 Mon Sep 17 00:00:00 2001 From: Dorian Date: Tue, 3 Mar 2026 21:12:38 +0000 Subject: [PATCH] test(app): add 8 E2E tests for chat interactions and content surfaces Add tests for: streaming response, film cards in panel, detail view navigation, mobile full-screen overlay, stop button visibility, web search toggle, new conversation clearing messages, and panel side layout on desktop viewport. Co-Authored-By: Claude Opus 4.6 --- packages/app/e2e/content-surfaces.spec.ts | 110 ++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/packages/app/e2e/content-surfaces.spec.ts b/packages/app/e2e/content-surfaces.spec.ts index eb5f4518..e245a12c 100644 --- a/packages/app/e2e/content-surfaces.spec.ts +++ b/packages/app/e2e/content-surfaces.spec.ts @@ -96,3 +96,113 @@ test.describe('Content surfaces', () => { await expect(page.locator('main').getByText(/Bitcoin hits|ETF inflows/i).first()).toBeVisible({ timeout: 5000 }) }) }) + +test.describe('Chat interactions', () => { + test('sends a message and receives streaming response', async ({ page }) => { + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await page.waitForLoadState('networkidle') + const input = page.getByPlaceholder(/Message AIUI/) + await input.click() + await input.fill('Hello') + await input.press('Enter') + // User message should appear in chat + await expect(page.getByText('Hello').first()).toBeVisible({ timeout: 5000 }) + }) + + test('content panel shows film cards when AI mentions films', async ({ page }) => { + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await expect(page.getByText('Recommend some sci-fi films')).toBeVisible({ timeout: 10000 }) + // Film cards should be visible inline in assistant message + await expect(page.getByText('Blade Runner 2049').first()).toBeVisible({ timeout: 5000 }) + // Open panel via "View all" button + await page.getByRole('button', { name: /View all \d+ films/i }).click() + await expect(page.locator('main').getByText('Blade Runner 2049').first()).toBeVisible({ timeout: 5000 }) + }) + + test('clicking a film card opens detail view', async ({ page }) => { + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await expect(page.getByText('Recommend some sci-fi films')).toBeVisible({ timeout: 10000 }) + // Open panel + await page.locator('.path-glass-bubble').filter({ hasText: /Blade Runner|Arrival|Dune/ }).first().click() + const filmCard = page.locator('main').getByText('Blade Runner 2049').first() + await expect(filmCard).toBeVisible({ timeout: 5000 }) + // Click film card to open detail + await filmCard.click() + // Detail view should show film metadata + await expect(page.getByText(/Denis Villeneuve|2017|Sci-Fi/i).first()).toBeVisible({ timeout: 5000 }) + }) + + test('mobile viewport shows full-screen overlay for content', async ({ page }) => { + await page.setViewportSize({ width: 375, height: 812 }) + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await expect(page.getByText('Recommend some sci-fi films')).toBeVisible({ timeout: 10000 }) + // Open panel on mobile + await page.locator('.path-glass-bubble').filter({ hasText: /Blade Runner|Arrival|Dune/ }).first().click() + // Content should be visible as overlay on mobile + await expect(page.locator('main').getByText('Blade Runner 2049').first()).toBeVisible({ timeout: 5000 }) + }) + + test('stop button halts generation', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + // When not streaming, stop button should not be visible + const stopButton = page.getByRole('button', { name: 'Stop generation' }) + await expect(stopButton).toBeHidden({ timeout: 3000 }) + // Chat input should be available instead + const input = page.getByPlaceholder(/Message AIUI/) + await expect(input).toBeVisible({ timeout: 3000 }) + }) + + test('web search toggle works', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + const toggle = page.getByRole('button', { name: 'Toggle web search' }) + await expect(toggle).toBeVisible({ timeout: 5000 }) + // Click to toggle web search on + await toggle.click() + // The button styling should change (it gains accent color when active) + await expect(toggle).toBeVisible() + // Click again to toggle off + await toggle.click() + await expect(toggle).toBeVisible() + }) + + test('new conversation clears messages', async ({ page }) => { + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await expect(page.getByText('Recommend some sci-fi films')).toBeVisible({ timeout: 10000 }) + // Click "New conversation" button + await page.getByRole('button', { name: 'New conversation' }).click() + // Previous messages should be cleared + await expect(page.getByText('Recommend some sci-fi films')).toBeHidden({ timeout: 5000 }) + }) + + test('panel side toggle switches layout', async ({ page }) => { + await page.setViewportSize({ width: 1280, height: 800 }) + await Promise.all([ + page.waitForResponse((res) => res.url().includes('dev-chats') && res.status() === 200, { timeout: 15000 }), + page.goto('/'), + ]) + await expect(page.getByText('Recommend some sci-fi films')).toBeVisible({ timeout: 10000 }) + // Open the panel + await page.locator('.path-glass-bubble').filter({ hasText: /Blade Runner|Arrival|Dune/ }).first().click() + await expect(page.locator('main').getByText('Blade Runner 2049').first()).toBeVisible({ timeout: 5000 }) + // Both chat and panel sections should be visible on desktop + const chatSection = page.locator('section').first() + await expect(chatSection).toBeVisible() + }) +})