From 4bae441e45cb4b59a5e0753dc77fde29ef0fe7f5 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 8 Nov 2026 12:53:10 +0100 Subject: [PATCH] test(app): prove late archive errors against a real daemon refusal The test answered the held archive request with a response it built itself, so no daemon ever failed. It now releases the held request naming a workspace the daemon has no record of, which is the one archive refusal a test can trigger without patching the daemon. --- .../browser/workspace-archive-undo.spec.ts | 6 ++- .../support/helpers/workspace-archive-undo.ts | 37 +++++++------------ 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/packages/app/e2e/browser/workspace-archive-undo.spec.ts b/packages/app/e2e/browser/workspace-archive-undo.spec.ts index c6c6fcad56..9f9567b75a 100644 --- a/packages/app/e2e/browser/workspace-archive-undo.spec.ts +++ b/packages/app/e2e/browser/workspace-archive-undo.spec.ts @@ -131,9 +131,11 @@ test.describe("Workspace archive undo", () => { await page.setViewportSize({ width: 400, height: 720 }); await expect(undoButton(page)).toHaveCount(0); - archive.fail("Injected archive failure."); + archive.releaseForUnknownWorkspace("workspace-the-daemon-never-had"); - await expect(page.getByTestId("app-toast-message")).toHaveText("Injected archive failure."); + await expect(page.getByTestId("app-toast-message")).toHaveText( + "Workspace not found: workspace-the-daemon-never-had", + ); }); test("the archived toast keeps Undo inside the card at the narrowest sidebar", async ({ diff --git a/packages/app/e2e/support/helpers/workspace-archive-undo.ts b/packages/app/e2e/support/helpers/workspace-archive-undo.ts index ae4a802edd..7f6846b252 100644 --- a/packages/app/e2e/support/helpers/workspace-archive-undo.ts +++ b/packages/app/e2e/support/helpers/workspace-archive-undo.ts @@ -100,23 +100,19 @@ export async function expectDirectoryPresence(directory: string, present: boolea export interface HeldArchiveRequest { waitForHeld(): Promise; - fail(error: string): void; + /** Sends the held request to the daemon naming a workspace it has no record of, so it refuses. */ + releaseForUnknownWorkspace(workspaceId: string): void; } -/** Keeps the next archive request from the host and lets the test answer it with a failure. */ +/** Keeps the next archive request from reaching the daemon until the test releases it. */ export async function holdNextArchiveRequest(page: Page): Promise { - let held: { requestId: string; workspaceId: string; respond: (raw: string) => void } | null = - null; + let held: { request: SessionRequest; forward: (raw: string) => void } | null = null; await page.routeWebSocket(daemonWsRoutePattern(), (browser) => { const server = browser.connectToServer(); browser.onMessage((message) => { const request = parseSessionRequest(message); if (!held && request?.type === "archive_workspace_request") { - held = { - requestId: request.requestId, - workspaceId: request.workspaceId, - respond: (raw) => browser.send(raw), - }; + held = { request, forward: (raw) => server.send(raw) }; return; } server.send(message); @@ -125,25 +121,20 @@ export async function holdNextArchiveRequest(page: Page): Promise expect.poll(() => held !== null).toBe(true), - fail: (error) => { + releaseForUnknownWorkspace: (workspaceId) => { if (!held) throw new Error("No archive request is held"); - const { requestId, workspaceId, respond } = held; - respond( - JSON.stringify({ - type: "session", - message: { - type: "archive_workspace_response", - payload: { requestId, workspaceId, archivedAt: null, error }, - }, - }), - ); + held.forward(JSON.stringify({ type: "session", message: { ...held.request, workspaceId } })); }, }; } -function parseSessionRequest( - message: string | Buffer, -): { type: string; requestId: string; workspaceId: string } | null { +interface SessionRequest { + type: string; + requestId: string; + workspaceId: string; +} + +function parseSessionRequest(message: string | Buffer): SessionRequest | null { try { const envelope = JSON.parse(typeof message === "string" ? message : message.toString("utf8")); return envelope?.type === "session" ? envelope.message : null;