From 6dbb1db5a1a172d169cf9b9fd2c87401453a3e32 Mon Sep 17 00:00:00 2001 From: core-devops Date: Thu, 11 Jun 2026 04:48:08 -0700 Subject: [PATCH] fix(canvas): namespace WorkspacePanelTabs ids per instance (duplicate #tab-chat broke chat E2E) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The concierge Settings pane embeds a SECOND WorkspacePanelTabs (ConciergeShell.tsx:598) and the component hardcodes id={`tab-${id}`} / id={`panel-${id}`} — two mounted instances produce duplicate DOM ids: invalid HTML, aria-controls pointing at the wrong element, and the chat E2E failing on every main commit since the embed landed: Error: strict mode violation: locator('#tab-chat') resolved to 2 elements 1) ... aka getByRole('tab', { name: 'Chat' }) <- SidePanel 2) ... aka getByTestId('settings-pane-platform')... <- concierge embed (run 348090 on 79550255: all 7 chat-desktop tests; the mobile suite passes because the embed isn't mounted there.) Fix: add an idPrefix prop (default "" so the primary map SidePanel keeps its stable #tab-chat hooks); the concierge embed passes "concierge-". The roving-focus getElementById and the tabpanel ids/labels use the prefix too. staging-concierge.spec.ts updated to the namespaced ids. canvas unit suite: 185 files / 2649 tests green. Co-Authored-By: Claude Opus 4.8 (1M context) --- canvas/e2e/staging-concierge.spec.ts | 11 ++++++---- canvas/src/components/WorkspacePanelTabs.tsx | 22 ++++++++++++++----- .../components/concierge/ConciergeShell.tsx | 6 ++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/canvas/e2e/staging-concierge.spec.ts b/canvas/e2e/staging-concierge.spec.ts index 79d047b0..a3d316bc 100644 --- a/canvas/e2e/staging-concierge.spec.ts +++ b/canvas/e2e/staging-concierge.spec.ts @@ -418,7 +418,10 @@ test.describe("concierge Settings — two tabs", () => { wsTablist, "platform-agent Settings tab did not embed WorkspacePanelTabs", ).toBeVisible({ timeout: 15_000 }); - await expect(page.locator("#tab-config")).toHaveAttribute( + // concierge-embedded WorkspacePanelTabs namespaces its ids with + // "concierge-" (duplicate-id fix); the bare #tab-* ids belong to the + // map SidePanel instance only. + await expect(page.locator("#concierge-tab-config")).toHaveAttribute( "aria-selected", "true", ); @@ -434,8 +437,8 @@ test.describe("concierge Settings — two tabs", () => { "schedule", ]) { await expect( - page.locator(`#tab-${id}`), - `WorkspacePanelTabs is missing #tab-${id}`, + page.locator(`#concierge-tab-${id}`), + `WorkspacePanelTabs is missing #concierge-tab-${id}`, ).toHaveCount(1); } @@ -469,7 +472,7 @@ test.describe("concierge Settings — Config tab dropdowns", () => { ).toBeVisible({ timeout: 15_000 }); // The runtime