test(e2e): stable workspace-node selector for chat-desktop specs #2648

Merged
devops-engineer merged 1 commits from fix/2506-chat-desktop-workspace-selector into main 2026-06-12 17:04:37 +00:00
4 changed files with 9 additions and 21 deletions
+3 -15
View File
@@ -48,11 +48,7 @@ test.describe("Desktop ChatTab", () => {
// view and renders a matching wsName div, so an unscoped getByText
// .first() can resolve to the invisible concierge node (DOM-order
// dependent → alternating green/red on main).
await page
.locator(".react-flow__node")
.getByText(workspaceName, { exact: true })
.first()
.click();
await page.getByTestId(`workspace-node-${workspaceName}`).click();
// Wait for the side panel chat tab to be clickable, then click it.
await page.locator('#tab-chat').click();
// All chat selectors are scoped to #panel-chat (the map SidePanel
@@ -90,11 +86,7 @@ test.describe("Desktop ChatTab", () => {
await page.reload();
await enterMapView(page);
await page.waitForSelector(".react-flow__node", { timeout: 10_000 });
await page
.locator(".react-flow__node")
.getByText(workspaceName, { exact: true })
.first()
.click();
await page.getByTestId(`workspace-node-${workspaceName}`).click();
await page.locator('#tab-chat').click();
await page.waitForSelector("#panel-chat [data-testid='chat-panel']", { timeout: 5_000 });
// Wait for the workspace status to flip to online and the textarea to be enabled.
@@ -175,11 +167,7 @@ test.describe("Desktop ChatTab — Markdown rendering", () => {
if (await skipGuide2.isVisible().catch(() => false)) {
await skipGuide2.click();
}
await page
.locator(".react-flow__node")
.getByText(workspaceName, { exact: true })
.first()
.click();
await page.getByTestId(`workspace-node-${workspaceName}`).click();
await page.locator('#tab-chat').click();
await page.waitForSelector("#panel-chat [data-testid='chat-panel']", { timeout: 5_000 });
// Wait for the workspace status to flip to online and the textarea to be enabled.
+3 -3
View File
@@ -381,10 +381,10 @@ test.describe("concierge Org map", () => {
});
// Normal workspaces render as map node cards (WorkspaceNode →
// data-testid="workspace-node"). The provisioned hermes workspace must
// data-testid="workspace-node-{name}"). The provisioned hermes workspace must
// appear. expect.poll lets React Flow finish its layout pass.
await expect
.poll(async () => page.locator('[data-testid="workspace-node"]').count(), {
.poll(async () => page.locator('[data-testid^="workspace-node-"]').count(), {
message: "no workspace nodes rendered on the org map",
timeout: 15_000,
})
@@ -397,7 +397,7 @@ test.describe("concierge Org map", () => {
// canvas-topology.ts). Only meaningful when we actually installed one.
if (platformInstalled) {
const platformNode = page.locator(
`[data-testid="workspace-node"][aria-label^="${PLATFORM_AGENT_NAME} workspace"]`,
`[data-testid^="workspace-node-"][aria-label^="${PLATFORM_AGENT_NAME} workspace"]`,
);
await expect(
platformNode,
+1 -1
View File
@@ -94,7 +94,7 @@ export function WorkspaceNode({ id, data }: NodeProps<Node<WorkspaceNodeData>>)
<div
role="button"
tabIndex={0}
data-testid="workspace-node"
data-testid={`workspace-node-${data.name}`}
aria-label={
isMisconfigured && configurationError
? `${data.name} workspace — agent not configured: ${configurationError}`
@@ -179,7 +179,7 @@ import { WorkspaceNode } from "../WorkspaceNode";
// ── Helpers ──────────────────────────────────────────────────────────────────
// Main node card uses data-testid to distinguish from handle anchors (also role=button)
const getNode = () => screen.getByTestId("workspace-node");
const getNode = (name = "Test Workspace") => screen.getByTestId(`workspace-node-${name}`);
// Typed access to the shared mock state (set by the vi.mock factory)
const mocks = () => globalThis.__workspaceNodeMocks!;
@@ -566,7 +566,7 @@ describe("WorkspaceNode — selection aria", () => {
describe("WorkspaceNode — aria-label", () => {
it("includes name and status in aria-label", () => {
renderNode({ name: "MyAgent", status: "online" });
const label = getNode().getAttribute("aria-label");
const label = getNode("MyAgent").getAttribute("aria-label");
expect(label).toContain("MyAgent");
expect(label).toContain("online");
});