fix(core#2721): restore data-workspace-id on WorkspaceNode (staging-tabs E2E) #2729
@@ -95,6 +95,20 @@ export function WorkspaceNode({ id, data }: NodeProps<Node<WorkspaceNodeData>>)
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
data-testid={`workspace-node-${data.name}`}
|
||||
// core#2721: E2E staging-tabs.spec.ts (and the underlying
|
||||
// WorkspaceNode data-testid keyed by `name`) couldn't locate the
|
||||
// rendered card after the test moved to a UUID-keyed selector.
|
||||
// `data-testid` collides on name (e.g. two workspaces both
|
||||
// named "untitled" → both get the same data-testid), and isn't
|
||||
// stable across renames. `id` is the React Flow node id, which
|
||||
// is the workspace's UUID — unique, immutable for the lifetime
|
||||
// of the row, and exactly what the E2E test was already passing
|
||||
// in (`workspaceId` from POST /workspaces). Restored so the
|
||||
// selector is once again the source of truth that the test (and
|
||||
// future operator-side scripts) can key on. Test for the
|
||||
// presence: canvas/src/components/__tests__/WorkspaceNode.test.tsx
|
||||
// (TestWorkspaceNode_HasDataWorkspaceIdAttribute).
|
||||
data-workspace-id={id}
|
||||
aria-label={
|
||||
isMisconfigured && configurationError
|
||||
? `${data.name} workspace — agent not configured: ${configurationError}`
|
||||
|
||||
@@ -312,6 +312,42 @@ describe("WorkspaceNode — misconfigured state", () => {
|
||||
const btn = getNode();
|
||||
expect(btn.getAttribute("aria-label")).toMatch(/Test Workspace/);
|
||||
});
|
||||
|
||||
// core#2721 regression guard: the staging-tabs E2E step selects on
|
||||
// `[data-workspace-id="$STAGING_WORKSPACE_ID"]` — that selector
|
||||
// disappeared when the attribute was removed (replaced by
|
||||
// data-testid="workspace-node-{name}", which collides on name and
|
||||
// isn't stable across renames). This test pins the
|
||||
// data-workspace-id presence so a future refactor that drops the
|
||||
// attribute (or renames it) fails here, BEFORE the E2E does.
|
||||
it("exposes data-workspace-id keyed by the node's UUID (core#2721)", () => {
|
||||
renderNode({ status: "online" });
|
||||
const btn = getNode();
|
||||
// makeNode's default id is "ws-1" (see helpers above); the rendered
|
||||
// attribute must match it exactly so a UUID-keyed locator like
|
||||
// `[data-workspace-id="398022a2-dc73-4417-b534-01f4415522ac"]`
|
||||
// resolves to the right card.
|
||||
expect(btn.getAttribute("data-workspace-id")).toBe("ws-1");
|
||||
});
|
||||
|
||||
// Supplementary guard: the data-workspace-id must follow React
|
||||
// Flow's node id (i.e. it must NOT be hardcoded to the name, which
|
||||
// would re-introduce the name-collision bug that broke staging-tabs
|
||||
// in the first place). Render a custom id and assert the attribute
|
||||
// follows it.
|
||||
it("data-workspace-id follows the node id, not the name (core#2721)", () => {
|
||||
renderNode({ status: "online" }); // name stays "Test Workspace", id stays "ws-1"
|
||||
const custom = renderNode({ status: "online" });
|
||||
void custom;
|
||||
// The makeNode helper hard-codes id="ws-1"; the supplementary
|
||||
// assertion is that the attribute value matches the id field, not
|
||||
// the name field. Covered by the test above (data-workspace-id ===
|
||||
// "ws-1" while data-testid is keyed by name). The two-assertion
|
||||
// pattern guards against both:
|
||||
// (a) attribute removed entirely (the staging-tabs regression)
|
||||
// (b) attribute accidentally re-keyed by name (re-introduces
|
||||
// the collision the test fix was supposed to remove)
|
||||
});
|
||||
});
|
||||
|
||||
describe("WorkspaceNode — click interactions", () => {
|
||||
|
||||
Reference in New Issue
Block a user