summaryrefslogtreecommitdiffhomepage
path: root/src/features/workspaces/ui/WorkspacesHome.test.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-10-19 13:38:57 +0900
committerAdam Malczewski <[email protected]>2026-10-19 13:38:57 +0900
commitc4397f633415a46852f0e3b49c78ab7b2d87d4c1 (patch)
tree047a5687565059422cbb38aeda8988502a66b78d /src/features/workspaces/ui/WorkspacesHome.test.ts
parentf6d96289470ac888670050ff64c54bbe69b973cb (diff)
downloaddispatch-web-c4397f633415a46852f0e3b49c78ab7b2d87d4c1.tar.gz
dispatch-web-c4397f633415a46852f0e3b49c78ab7b2d87d4c1.zip
feat(workspaces): block creating a workspace whose slug is archived
Diffstat (limited to 'src/features/workspaces/ui/WorkspacesHome.test.ts')
-rw-r--r--src/features/workspaces/ui/WorkspacesHome.test.ts38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/features/workspaces/ui/WorkspacesHome.test.ts b/src/features/workspaces/ui/WorkspacesHome.test.ts
index 6316930..d4316b1 100644
--- a/src/features/workspaces/ui/WorkspacesHome.test.ts
+++ b/src/features/workspaces/ui/WorkspacesHome.test.ts
@@ -5,6 +5,7 @@ import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import type { WorkspaceHttp, WorkspaceResult } from "../adapter/http";
import type { TileLayoutHttp } from "../adapter/tile-layout-http";
+import type { WorkspaceLookup } from "../logic/create";
import { createTileLayoutStore } from "../tile-layout-store.svelte";
import WorkspacesHome from "./WorkspacesHome.svelte";
@@ -24,7 +25,10 @@ function ws(overrides: Partial<WorkspaceEntry> = {}): WorkspaceEntry {
}
/** A fake WorkspaceHttp edge with a controllable list (no mocks of our modules). */
-function fakeHttp(list: WorkspaceEntry[] = [ws()]): WorkspaceHttp {
+function fakeHttp(
+ list: WorkspaceEntry[] = [ws()],
+ lookup: (id: string) => Promise<WorkspaceLookup> = async () => ({ kind: "missing" }),
+): WorkspaceHttp {
return {
list: vi.fn(async (): Promise<WorkspaceEntry[]> => list),
// Create-on-miss: the backend persists the new workspace, so the next
@@ -33,7 +37,7 @@ function fakeHttp(list: WorkspaceEntry[] = [ws()]): WorkspaceHttp {
if (!list.some((w) => w.id === id)) list.push(ws({ id, title: id }));
return { ok: true, value: ws({ id, title: id }) };
}),
- get: vi.fn(),
+ get: vi.fn(lookup),
setTitle: vi.fn(),
setDefaultCwd: vi.fn(),
setDefaultComputer: vi.fn(),
@@ -140,6 +144,36 @@ describe("WorkspacesHome (tile canvas)", () => {
expect(store.list.map((w) => w.id)).toContain("fresh-ws");
});
+ it("refuses to create an archived slug: message in the popover, form stays open, no tile", async () => {
+ const user = userEvent.setup();
+ const list = [ws({ id: "a", title: "A" })];
+ const http = fakeHttp(list, async (id) => ({
+ kind: "found",
+ workspace: ws({ id, title: id, archived: true }),
+ }));
+ const store = (await import("../store.svelte")).createWorkspaceStore(http);
+ render(WorkspacesHome, {
+ props: {
+ store,
+ onNavigate: vi.fn(),
+ computers: [],
+ tiles: createTileLayoutStore({ http: memoryLayout() }),
+ },
+ });
+
+ await screen.findByRole("button", { name: "Open workspace A" });
+ await user.click(screen.getByRole("button", { name: "New workspace" }));
+ await user.type(screen.getByRole("textbox", { name: "New workspace" }), "old-ws{Enter}");
+
+ expect(await screen.findByText(/already exists and is archived/)).toBeInTheDocument();
+ // The popover stays open (the form/input is still mounted).
+ expect(screen.getByRole("textbox", { name: "New workspace" })).toBeInTheDocument();
+ // Nothing was ensured, no tile appeared, and no rename mode was entered.
+ expect(http.ensure).not.toHaveBeenCalled();
+ expect(store.list.map((w) => w.id)).toEqual(["a"]);
+ expect(screen.queryByLabelText("Workspace title")).toBeNull();
+ });
+
it("right-clicking a tile opens the action bar; Delete keeps the confirm + store call", async () => {
const user = userEvent.setup();
const confirmSpy = vi.spyOn(window, "confirm").mockReturnValue(true);