Keep New Workspace drafts when archiving a workspace (#1838)

* fix(app): preserve new workspace drafts across archive

The New Workspace project picker was still tied to the last active workspace. Archiving that workspace could make the picker fall back to another project, changing the draft key and clearing the composer.

* refactor(app): extract new workspace project selection

Keep the archive-draft fix out of the screen effect by moving the project selection transition into a small pure model with focused coverage.

* test(app): seed host in archive draft regression

Make the new Playwright regression self-contained by seeding the local host before opening the app shell.

* refactor(app): home new workspace project picker state

* fix(app): reset project picker on capability hydration

* fix(app): preserve manual project picks during hydration

* fix(app): keep project selection through archive gaps

* fix(app): narrow archive-gap project preservation

* fix(app): refresh new workspace project selection
This commit is contained in:
Mohamed Boudra
2026-07-01 21:53:16 +02:00
committed by GitHub
parent 31e9a210d0
commit 48d07dedb5
5 changed files with 715 additions and 127 deletions
@@ -10,6 +10,7 @@ import { getE2EDaemonPort } from "./helpers/daemon-port";
import { seedWorkspace, type SeededWorkspace } from "./helpers/seed-client";
import { seedSavedSettingsHosts } from "./helpers/settings";
import { getServerId } from "./helpers/server-id";
import { clickArchiveWorkspaceMenuItem, expectWorkspaceAbsentFromSidebar } from "./helpers/sidebar";
import { waitForSidebarHydration } from "./helpers/workspace-ui";
// Model B entry points into the New Workspace screen. The per-project
@@ -105,6 +106,54 @@ test.describe("New workspace entry points", () => {
}
});
test("keeps the in-progress form when the remembered workspace is archived elsewhere", async ({
page,
}) => {
const otherProject: SeededWorkspace = await seedWorkspace({
repoPrefix: "aa-new-workspace-archive-other-",
});
const rememberedProject: SeededWorkspace = await seedWorkspace({
repoPrefix: "zz-new-workspace-archive-remembered-",
});
const serverId = getServerId();
const draftText = "keep this new workspace draft";
try {
await seedSavedSettingsHosts(page, [
{
serverId,
label: "localhost",
endpoint: `127.0.0.1:${getE2EDaemonPort()}`,
},
]);
await gotoAppShell(page);
await waitForSidebarHydration(page);
await page
.getByTestId(`sidebar-workspace-row-${serverId}:${rememberedProject.workspaceId}`)
.click();
await expect(page).toHaveURL(/\/workspace\//, { timeout: 30_000 });
await page.goto(`/new?serverId=${encodeURIComponent(serverId)}`);
await expectNewWorkspaceProjectSelected(page, rememberedProject.projectDisplayName);
const composer = page.getByRole("textbox", { name: "Message agent..." });
await expect(composer).toBeEditable({ timeout: 30_000 });
await composer.fill(draftText);
await expect(composer).toHaveValue(draftText);
await clickArchiveWorkspaceMenuItem(page, rememberedProject.workspaceId);
await expectWorkspaceAbsentFromSidebar(page, rememberedProject.workspaceId);
await expect(page).toHaveURL(/\/new(?:\?.*)?$/, { timeout: 30_000 });
await expect(composer).toHaveValue(draftText);
await expectNewWorkspaceProjectSelected(page, rememberedProject.projectDisplayName);
} finally {
await otherProject.cleanup();
await rememberedProject.cleanup();
}
});
test("each project's row icon preselects that project, and the reused screen resets a stale manual choice across projects", async ({
page,
}) => {