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 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-22 06:10:18 +07:00
co-authored by Claude Opus 4.8
parent 678a878855
commit fdf5c4ea90
3 changed files with 10 additions and 2 deletions
@@ -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']) {
@@ -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();
+6 -2
View File
@@ -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([]);
});
});