diff --git a/packages/app/e2e/browser/root-error-recovery.spec.ts b/packages/app/e2e/browser/root-error-recovery.spec.ts index 26fc70c4bb..55f5f37b42 100644 --- a/packages/app/e2e/browser/root-error-recovery.spec.ts +++ b/packages/app/e2e/browser/root-error-recovery.spec.ts @@ -4,9 +4,15 @@ import { expect, test, type Page, type TestInfo } from "@playwright/test"; let server: Server; let appUrl: string; test.beforeAll(async () => { + // Compile this separate fixture entrypoint in setup, like the main app warmup. + // Cold Metro compilation must not consume the recovery interaction's timeout. + test.setTimeout(120_000); const metroPort = process.env.E2E_METRO_PORT; if (!metroPort) throw new Error("E2E_METRO_PORT is required"); const bundle = `http://localhost:${metroPort}/packages/app/e2e/support/recovery-app.bundle?platform=web&dev=true&minify=false&hot=false&lazy=true&transform.engine=hermes&transform.routerRoot=src%2Fapp`; + const compiled = await fetch(bundle, { signal: AbortSignal.timeout(120_000) }); + if (!compiled.ok) throw new Error(`Recovery fixture compilation failed: HTTP ${compiled.status}`); + await compiled.arrayBuffer(); server = createServer((_request, response) => { response.setHeader("Content-Type", "text/html"); response.end( diff --git a/packages/app/e2e/browser/sidebar-model-b.spec.ts b/packages/app/e2e/browser/sidebar-model-b.spec.ts index 33e6ff8ddc..336ed97245 100644 --- a/packages/app/e2e/browser/sidebar-model-b.spec.ts +++ b/packages/app/e2e/browser/sidebar-model-b.spec.ts @@ -7,7 +7,6 @@ import { getServerId } from "../support/helpers/server-id"; import { projectEquivalenceViewKey } from "../support/helpers/project-view-key"; import { selectSidebarStatusGrouping } from "../support/helpers/sidebar"; import { waitForSidebarHydration } from "../support/helpers/workspace-ui"; -import { getVisibleWorkspaceAgentTabIds } from "../support/helpers/workspace-tabs"; // Model B sidebar shape: every project — git or non-git, single- or // multi-workspace — renders as the same expandable parent, the deepest sidebar @@ -96,8 +95,9 @@ test.describe("Model B sidebar shape", () => { try { // Open the workspace and materialize both an agent tab and a terminal tab. await gotoWorkspace(page, mock.workspaceId); - const agentTabs = await getVisibleWorkspaceAgentTabIds(page); - expect(agentTabs).toContain(`workspace-tab-agent_${mock.agentId}`); + await expect( + page.getByTestId(`workspace-tab-agent_${mock.agentId}`).filter({ visible: true }), + ).toBeVisible(); await clickNewTerminal(page); await expect( diff --git a/packages/app/e2e/browser/worktree-restore.spec.ts b/packages/app/e2e/browser/worktree-restore.spec.ts index 4f6096ed07..3926b43a97 100644 --- a/packages/app/e2e/browser/worktree-restore.spec.ts +++ b/packages/app/e2e/browser/worktree-restore.spec.ts @@ -265,7 +265,7 @@ test.describe("Worktree restore", () => { ).toHaveText(switchedBranch, { timeout: 30_000 }); }); - test("recovers the selected agent with its workspace and later rescues another archived agent", async ({ + test("restores the workspace before explicitly unarchiving each selected agent", async ({ page, }) => { const { agents, worktree } = await createArchivedMissingWorktree("restore-agents", { @@ -292,9 +292,16 @@ test.describe("Worktree restore", () => { await expect( page.getByTestId(`workspace-tab-agent_${firstAgent.id}`).filter({ visible: true }).first(), ).toBeVisible({ timeout: 30_000 }); + await expect( + page.getByTestId(`workspace-tab-agent_${firstAgent.id}`).filter({ visible: true }).first(), + ).toHaveAttribute("aria-selected", "true"); + expect(await fetchAgentArchivedAt(client, firstAgent.id)).not.toBeNull(); + expect(await fetchAgentArchivedAt(client, secondAgent.id)).not.toBeNull(); + await page.getByRole("button", { name: "Unarchive", exact: true }).click(); await expect .poll(() => fetchAgentArchivedAt(client, firstAgent.id), { timeout: 30_000 }) .toBeNull(); + expect(await fetchAgentArchivedAt(client, secondAgent.id)).not.toBeNull(); await expect(page.getByRole("button", { name: "Unarchive" })).toHaveCount(0, { timeout: 30_000, });