import { http, HttpResponse } from "msw"; import { server } from "../test/msw"; import { canonicalWorkspaceFixture, workspaceRevisionFixture, workspaceSummaryFixture } from "../test/workspace-fixtures"; import { createSession, getMe, listSessions, prewarmRuntime, resumeSession } from "./sessions"; import { renameSession, setSessionGroup, archiveSession, unarchiveSession, deleteSession, getSessionDocuments, } from "./sessions"; import { workspacePreferences } from "../workspaces/preferences"; test("createSession seeds ephemeral selections and posts them", async () => { localStorage.clear(); let body: unknown = null; server.use( http.get("/api/settings", () => HttpResponse.json({ workspace: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", })), http.get("/api/workspaces", () => HttpResponse.json([{ ...workspaceSummaryFixture("psd-clinical", { displayName: "PSD Clinical", revision: workspaceRevisionFixture("psd-clinical"), }), }])), http.get("/api/workspaces/psd-clinical", () => HttpResponse.json({ workspace: canonicalWorkspaceFixture("psd-clinical"), revision: { id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot" }, })), http.post("/api/sessions", async ({ request }) => { body = await request.json(); return HttpResponse.json({ id: "s1" }); }), ); expect(await createSession({ question: "q" })).toEqual({ id: "s1" }); expect(body).toEqual({ question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); expect(workspacePreferences.load()).toEqual({ workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); expect(localStorage.getItem("thothii.workspace-registry.v1.preferences")).toBeNull(); }); test("createSession does not POST when a selected summary aliases another workspace name", async () => { workspacePreferences.save({ workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); let posted = false; server.use( http.get("/api/workspaces", () => HttpResponse.json([{ ...workspaceSummaryFixture("psd-clinical", { displayName: "PSD Clinical", revision: workspaceRevisionFixture("psd-clinical"), }), name: "other-workspace", }])), http.get("/api/workspaces/psd-clinical", () => HttpResponse.json({ workspace: canonicalWorkspaceFixture("psd-clinical"), revision: { id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", }, })), http.post("/api/sessions", () => { posted = true; return HttpResponse.json({ id: "s1" }); }), ); await expect(createSession({ question: "q" })).rejects.toMatchObject({ message: "Could not load workspace registry. Please retry.", }); expect(posted).toBe(false); }); test.each([ ["historical state", { state: "operational" }], ["an unknown revision field", { generation: 1 }], ["a malformed revision", { commit: "not-a-commit" }], ])("createSession does not POST when the selected summary revision has %s", async (_case, revisionPatch) => { workspacePreferences.save({ workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); const revision = { id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", ...revisionPatch, }; let posted = false; server.use( http.get("/api/workspaces", () => HttpResponse.json([{ ...workspaceSummaryFixture("psd-clinical", { displayName: "PSD Clinical", revision: revision as any, }), }])), http.get("/api/workspaces/psd-clinical", () => HttpResponse.json({ workspace: canonicalWorkspaceFixture("psd-clinical"), revision: { id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", }, })), http.post("/api/sessions", () => { posted = true; return HttpResponse.json({ id: "s1" }); }), ); await expect(createSession({ question: "q" })).rejects.toMatchObject({ message: "Could not load workspace registry. Please retry.", }); expect(posted).toBe(false); }); test("createSession replaces a stale ephemeral workspace with the current installation default", async () => { workspacePreferences.save({ workspaceId: "retired-workspace", provider: "zai", model: "glm-5.2", thinking: "low", }); let body: unknown; server.use( http.get("/api/settings", () => HttpResponse.json({ workspace: "psd-clinical" })), http.get("/api/workspaces", () => HttpResponse.json([{ ...workspaceSummaryFixture("psd-clinical", { displayName: "PSD Clinical", revision: workspaceRevisionFixture("psd-clinical"), }), }])), http.get("/api/workspaces/psd-clinical", () => HttpResponse.json({ workspace: canonicalWorkspaceFixture("psd-clinical"), revision: { id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", }, })), http.post("/api/sessions", async ({ request }) => { body = await request.json(); return HttpResponse.json({ id: "s1" }); }), ); await expect(createSession({ question: "q" })).resolves.toEqual({ id: "s1" }); expect(body).toEqual({ question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); expect(workspacePreferences.load()).toEqual({ workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", }); }); test("createSession preserves a local legacy selection when the registry is empty", async () => { workspacePreferences.save({ workspaceId: "legacy-workspace", provider: "zai", model: "glm-5.2", thinking: "low", }); let body: unknown; server.use( http.get("/api/workspaces", () => HttpResponse.json([])), http.post("/api/sessions", async ({ request }) => { body = await request.json(); return HttpResponse.json({ id: "s1" }); }), ); await expect(createSession({ question: "q" })).resolves.toEqual({ id: "s1" }); expect(body).toEqual({ question: "q", workspaceId: "legacy-workspace", provider: "zai", model: "glm-5.2", thinking: "low", }); }); test("createSession rejects a workspace summary that omits the canonical revision", async () => { localStorage.clear(); let posted = false; server.use( http.get("/api/settings", () => HttpResponse.json({ workspace: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "low", })), http.get("/api/workspaces", () => HttpResponse.json([{ ...workspaceSummaryFixture("psd-clinical", { displayName: "PSD Clinical", configurationState: "configuration_required", }), }])), http.post("/api/sessions", async () => { posted = true; return HttpResponse.json({ id: "s1" }); }), ); await expect(createSession({ question: "q" })).rejects.toMatchObject({ message: "Could not load workspace registry. Please retry.", }); expect(posted).toBe(false); }); test.each([202, 204])("prewarmRuntime accepts a body-less %s response", async (status) => { let called = false; server.use( http.post("/api/runtime/prewarm", () => { called = true; return new HttpResponse(null, { status }); }), ); await expect(prewarmRuntime()).resolves.toBeUndefined(); expect(called).toBe(true); }); test("listSessions defaults to the current user's scope", async () => { let scope: string | null = null; server.use(http.get("/api/sessions", ({ request }) => { scope = new URL(request.url).searchParams.get("scope"); return HttpResponse.json([{ id: "s1", status: "open", question: "q", summary: null, created_at: "t", updated_at: null, author: null }]); })); const rows = await listSessions(); expect(rows[0].id).toBe("s1"); expect(scope).toBe("mine"); }); test("listSessions requests the selected administrator scope", async () => { let scope: string | null = null; server.use(http.get("/api/sessions", ({ request }) => { scope = new URL(request.url).searchParams.get("scope"); return HttpResponse.json([]); })); await listSessions("all"); expect(scope).toBe("all"); }); test("getMe fetches the typed authenticated principal", async () => { server.use(http.get("/api/me", () => HttpResponse.json({ issuer: "portal", subject: "42", displayName: "Alice", isAdmin: true }), )); await expect(getMe()).resolves.toEqual({ issuer: "portal", subject: "42", displayName: "Alice", isAdmin: true, }); }); test("resumeSession returns the typed runtime disposition", async () => { server.use(http.post("/api/sessions/s1/resume", () => HttpResponse.json({ id: "s1", alreadyActive: false }))); const result: { id: string; alreadyActive: boolean } = await resumeSession("s1"); expect(result).toEqual({ id: "s1", alreadyActive: false }); }); test("renameSession POSTs {name}", async () => { let body: unknown = null; server.use(http.post("/api/sessions/s1/rename", async ({ request }) => { body = await request.json(); return new HttpResponse(null, { status: 204 }); })); await renameSession("s1", "Nome"); expect(body).toEqual({ name: "Nome" }); }); test("setSessionGroup POSTs {group}", async () => { let body: unknown = null; server.use(http.post("/api/sessions/s1/group", async ({ request }) => { body = await request.json(); return new HttpResponse(null, { status: 204 }); })); await setSessionGroup("s1", "G"); expect(body).toEqual({ group: "G" }); }); test("archive / unarchive / delete hit the right verbs+paths", async () => { const hits: string[] = []; server.use( http.post("/api/sessions/s1/archive", () => { hits.push("archive"); return new HttpResponse(null, { status: 204 }); }), http.post("/api/sessions/s1/unarchive", () => { hits.push("unarchive"); return new HttpResponse(null, { status: 204 }); }), http.delete("/api/sessions/s1", () => { hits.push("delete"); return new HttpResponse(null, { status: 204 }); }), ); await archiveSession("s1"); await unarchiveSession("s1"); await deleteSession("s1"); expect(hits).toEqual(["archive", "unarchive", "delete"]); }); test("getSessionDocuments GETs the array", async () => { server.use(http.get("/api/sessions/s1/documents", () => HttpResponse.json([{ phase: "—", key: "question", title: "t", format: "text", content: "q" }]), )); const docs = await getSessionDocuments("s1"); expect(docs[0].key).toBe("question"); });