test(canvas): gating test for in-flight turn status preservation on hydrate (issue #2391) #2426

Merged
devops-engineer merged 2 commits from test/2391-hydrate-inflight-turn-status into main 2026-06-09 02:14:03 +00:00
2 changed files with 26 additions and 0 deletions
@@ -162,6 +162,11 @@ describe("DisplayTab", () => {
controller: "user",
ttl_seconds: 300,
});
// Defensive: the noVNC constructor is async (dynamic import), so wait
// for it to be called before asserting arguments (prevents flake in CI).
await waitFor(() => {
expect(mockRFBConstructor).toHaveBeenCalled();
});
expect(mockRFBConstructor).toHaveBeenCalledWith(
expect.any(HTMLElement),
expect.stringContaining("/workspaces/ws-display/display/session/websockify"),
+21
View File
@@ -162,6 +162,27 @@ describe("hydrate", () => {
useCanvasStore.getState().hydrate([ws]);
expect(useCanvasStore.getState().nodes[0].data.currentTask).toBe("");
});
it("preserves in-flight turn status after refresh (issue #2391)", () => {
// Simulates a page refresh: the canvas re-hydrates from GET /workspaces
// while the agent has an active in-flight turn. The store must reflect
// "working" immediately — no dependence on a subsequent TASK_UPDATED
// socket event. This prevents the "stuck idle" UX after reload.
const ws = makeWS({
id: "ws-1",
status: "online",
current_task: "Analyzing data",
active_tasks: 2,
});
useCanvasStore.getState().hydrate([ws]);
const node = useCanvasStore.getState().nodes[0];
expect(node.data.currentTask).toBe("Analyzing data");
expect(node.data.activeTasks).toBe(2);
expect(node.data.status).toBe("online");
// Defensive: the node must be considered "working" for any UI that
// gates on currentTask (e.g. ChatTab thinking indicator).
expect(!!node.data.currentTask).toBe(true);
});
});
describe("summarizeWorkspaceCapabilities", () => {