From 4e3bb3795a19f61c1f28edc6f21f786dab8cefd8 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Fri, 24 Apr 2026 18:38:28 -0700 Subject: [PATCH] fix(e2e): canvas-hydration wait used a selector that never appears pre-click MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourth E2E bug in the staging→main chain. The previous three (#2066 setup-phase fixes) let the harness reach the actual Playwright spec. This one is in staging-tabs.spec.ts itself. The spec at L78 waits 45s for one of: [role="tablist"], [data-testid="hydration-error"] Both targets are wrong: 1. [role="tablist"] only appears AFTER the workspace node is clicked (which happens 25 lines later at L100). Waiting for it BEFORE the click can never resolve, so the wait always times out at 45s regardless of whether the canvas actually loaded. 2. [data-testid="hydration-error"] doesn't exist anywhere in the canvas. The error banner at app/page.tsx:62 only had role="alert" — which collides with toast notifications and other alert-type elements, so a more-specific selector was never wired. Two-part fix: - Test waits on `[aria-label="Molecule AI workspace canvas"]` instead — that's the React Flow wrapper (Canvas.tsx:150), always present once hydrated regardless of workspace count or selection state. Hydration-error banner remains the secondary OR target for the failure path. - app/page.tsx hydration-error banner gets the missing `data-testid="hydration-error"` attribute. role="alert" stays for accessibility; the testid is for programmatic detection without conflict. After this lands, the staging-tabs spec should advance past the initial wait, click the workspace node, and exercise each tab. If a tab fails, we get a proper test failure rather than a 45s timeout that obscures everything. Co-Authored-By: Claude Opus 4.7 (1M context) --- canvas/e2e/staging-tabs.spec.ts | 11 ++++++++--- canvas/src/app/page.tsx | 5 +++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/canvas/e2e/staging-tabs.spec.ts b/canvas/e2e/staging-tabs.spec.ts index 412953a5..fa99fa5e 100644 --- a/canvas/e2e/staging-tabs.spec.ts +++ b/canvas/e2e/staging-tabs.spec.ts @@ -73,10 +73,15 @@ test.describe("staging canvas tabs", () => { await page.goto(tenantURL, { waitUntil: "networkidle" }); // Canvas hydration races WebSocket connect + /workspaces fetch. - // Wait for the tablist element (appears after a workspace is - // selected) or the hydration-error banner — whichever wins first. + // Wait for the React Flow canvas wrapper (always present once + // hydrated, even with zero workspaces) or the hydration-error + // banner — whichever wins first. Previous version of this wait + // used `[role="tablist"]`, but that selector only appears AFTER + // a workspace node is clicked (which happens below at L100), so + // the wait would always time out at 45s before any meaningful + // failure surfaced. await page.waitForSelector( - '[role="tablist"], [data-testid="hydration-error"]', + '[aria-label="Molecule AI workspace canvas"], [data-testid="hydration-error"]', { timeout: 45_000 }, ); diff --git a/canvas/src/app/page.tsx b/canvas/src/app/page.tsx index 74291409..8b79ef83 100644 --- a/canvas/src/app/page.tsx +++ b/canvas/src/app/page.tsx @@ -61,6 +61,11 @@ export default function Home() { {hydrationError && (

{hydrationError}