From ecb94b25e7591f6274b65ebd27fab57dcd887603 Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Wed, 22 Jul 2026 14:06:09 +0700 Subject: [PATCH] test(e2e): assert stand routes on data, not only on client-side state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every assertion was client-side — the URL, a route-derived breadcrumb and pageerror, which a production React build does not emit for a failed query — so all five passed against a backend erroring on every request. Verified against the live stand: healthy, 5/5 pass; with GraphQL forced to error, the URL and breadcrumb assertions still pass and only the new one fails. Each route now proves its query resolved, accepting the empty state as well since a stand may hold no rows. Co-Authored-By: Claude Opus 4.8 --- frontend/e2e/specs/real/stand-smoke.spec.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/frontend/e2e/specs/real/stand-smoke.spec.ts b/frontend/e2e/specs/real/stand-smoke.spec.ts index f112d4a7..b0a01114 100644 --- a/frontend/e2e/specs/real/stand-smoke.spec.ts +++ b/frontend/e2e/specs/real/stand-smoke.spec.ts @@ -4,15 +4,15 @@ import { expect, test } from '@playwright/test'; // stand): the authenticated shell renders and each core route loads without an // uncaught error. No seeded data and no agent run — safe against a shared stand. const ROUTES = [ - { path: '/flows', title: 'Flows' }, - { path: '/templates', title: 'Templates' }, - { path: '/knowledges', title: 'Knowledges' }, - { path: '/settings/prompts', title: 'Prompts' }, - { path: '/settings/api-tokens', title: 'API Tokens' }, + { emptyTitle: 'No flows found', path: '/flows', title: 'Flows' }, + { emptyTitle: 'No templates yet', path: '/templates', title: 'Templates' }, + { emptyTitle: 'No knowledge documents yet', path: '/knowledges', title: 'Knowledges' }, + { emptyTitle: 'No prompts available', path: '/settings/prompts', title: 'Prompts' }, + { emptyTitle: 'No API tokens configured', path: '/settings/api-tokens', title: 'API Tokens' }, ]; test.describe('stand smoke', { tag: '@stand' }, () => { - for (const { path, title } of ROUTES) { + for (const { emptyTitle, path, title } of ROUTES) { test(`renders ${path} without a page error`, async ({ page }) => { const pageErrors: string[] = []; @@ -28,6 +28,10 @@ test.describe('stand smoke', { tag: '@stand' }, () => { // span tag matters: NavLink puts aria-current="page" on the active // settings-sidebar at runtime, the breadcrumb title is a span. await expect(page.locator('span[aria-current="page"]')).toHaveText(title); + // The only assertion here a backend erroring on every request fails: each page + // returns early into its ErrorState, rendering neither branch. Both branches are + // accepted because a stand may legitimately hold no rows. + await expect(page.locator('[data-slot="table"]').first().or(page.getByText(emptyTitle))).toBeVisible(); expect(pageErrors, `uncaught errors on ${path}`).toEqual([]); }); }