From fdf5c4ea905f89a489467d9ad8a71ceca21d5f52 Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Wed, 22 Jul 2026 06:10:18 +0700 Subject: [PATCH] test(e2e): close three latent assertion gaps - Watch for uncaught errors on the two auth-path smoke tests (they destructured no error log before); the rejected-login path asserts no uncaught JS exception while tolerating the 401's expected browser console line. - Assert the thinking body is collapsed before the toggle, so an always-expanded regression fails. - Assert the dashboard overview metrics are absent until the tab is selected, so the "loads lazily" title is actually covered. Co-Authored-By: Claude Opus 4.8 --- frontend/e2e/specs/dashboard/dashboard.spec.ts | 2 ++ frontend/e2e/specs/flows/messages.spec.ts | 2 ++ frontend/e2e/specs/smoke.spec.ts | 8 ++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/e2e/specs/dashboard/dashboard.spec.ts b/frontend/e2e/specs/dashboard/dashboard.spec.ts index 5f5a2ba3..4f7f1e08 100644 --- a/frontend/e2e/specs/dashboard/dashboard.spec.ts +++ b/frontend/e2e/specs/dashboard/dashboard.spec.ts @@ -26,6 +26,8 @@ test.describe('dashboard', { tag: '@coverage' }, () => { test('overview tab loads lazily and renders metrics and usage tables', async ({ page, pageErrorLog }) => { await page.goto('/dashboard'); + // Lazy: the overview metrics are not mounted while the Analytics tab is active. + await expect(page.getByRole('heading', { exact: true, name: 'Total Flows' })).toBeHidden(); await page.getByRole('tab', { name: 'Overview' }).click(); for (const title of ['Total Flows', 'Tool Calls', 'Total Tokens', 'Total Cost']) { diff --git a/frontend/e2e/specs/flows/messages.spec.ts b/frontend/e2e/specs/flows/messages.spec.ts index 4609da8d..18d8e0af 100644 --- a/frontend/e2e/specs/flows/messages.spec.ts +++ b/frontend/e2e/specs/flows/messages.spec.ts @@ -41,6 +41,8 @@ test.describe('flow message rendering', { tag: '@flows' }, () => { const thinkingToggle = page.getByText('Show thinking'); await expect(thinkingToggle).toBeVisible(); + // Collapsed first, so an always-expanded regression fails instead of passing. + await expect(page.getByText('internal reasoning about the plan')).toBeHidden(); await thinkingToggle.click(); await expect(page.getByText('Hide thinking')).toBeVisible(); await expect(page.getByText('internal reasoning about the plan')).toBeVisible(); diff --git a/frontend/e2e/specs/smoke.spec.ts b/frontend/e2e/specs/smoke.spec.ts index 9d5520d1..fba878c0 100644 --- a/frontend/e2e/specs/smoke.spec.ts +++ b/frontend/e2e/specs/smoke.spec.ts @@ -7,13 +7,14 @@ test.describe('smoke', { tag: '@smoke' }, () => { test.describe('unauthenticated', () => { test.use({ cassette: loginJourneyCassette, isAuthSeeded: false }); - test('redirects a protected route to /login with returnUrl', async ({ page }) => { + test('redirects a protected route to /login with returnUrl', async ({ page, pageErrorLog }) => { await page.goto('/flows'); await expect(page).toHaveURL(/\/login\?returnUrl=%2Fflows/); await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible(); // The guest /info carries OAuth providers, so the login page renders its OAuth buttons. await expect(page.getByRole('button', { name: 'Continue with Google' })).toBeVisible(); + expectCleanPage(pageErrorLog); }); test('logs in through the form and lands on the flows list', async ({ page, pageErrorLog }) => { @@ -31,7 +32,7 @@ test.describe('smoke', { tag: '@smoke' }, () => { test.describe('rejected login', () => { test.use({ cassette: loginFailCassette, isAuthSeeded: false }); - test('surfaces the error and re-disables Sign in until a field changes', async ({ page }) => { + test('surfaces the error and re-disables Sign in until a field changes', async ({ page, pageErrorLog }) => { await page.goto('/login'); await page.getByLabel('Login').fill(SEEDED_USER.mail); await page.getByRole('textbox', { name: 'Password' }).fill('wrong-password'); @@ -42,6 +43,9 @@ test.describe('smoke', { tag: '@smoke' }, () => { // react-hook-form leaves Submit disabled after a failed submit until // an input changes. await expect(page.getByRole('button', { name: 'Sign in' })).toBeDisabled(); + // The 401 logs an expected browser console error, but the path must raise no + // uncaught JS exception / unhandled rejection. + expect(pageErrorLog.pageErrors).toEqual([]); }); });