fix: validate workspace drafts and reconcile models

This commit is contained in:
2026-08-04 05:38:43 +02:00
parent cee4cfa63d
commit 959c6871ee
4 changed files with 279 additions and 80 deletions
+50
View File
@@ -181,6 +181,56 @@ test("footer limits model choices to the selected workspace policy", async () =>
await waitFor(() => expect(selector).not.toHaveTextContent("DeepSeek V4 Pro"));
});
test("switching workspaces replaces an out-of-policy model before session creation", async () => {
let body: unknown;
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspaceId: "research", provider: "deepseek", model: "deepseek-v4-pro", thinking: "medium",
}));
const revision = (id: string) => ({
id, commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", state: "operational" as const,
});
server.use(
http.get("http://localhost:8787/settings", () => HttpResponse.json({
workspace: "research", provider: "deepseek", model: "deepseek-v4-pro", thinking: "medium",
})),
http.get("http://localhost:8787/workspaces", () => HttpResponse.json([
{ id: "research", name: "research", file: "research.yaml", displayName: "Research", revision: revision("research") },
{ id: "psd-clinical", name: "psd-clinical", file: "psd-clinical.yaml", displayName: "PSD Clinical", revision: revision("psd-clinical") },
])),
http.get("http://localhost:8787/workspaces/research", () => HttpResponse.json({
workspace: { workspace: { id: "research" }, llm_policy: { allowed: ["deepseek/deepseek-v4-pro"] } },
revision: revision("research"),
})),
http.get("http://localhost:8787/workspaces/psd-clinical", () => HttpResponse.json({
workspace: { workspace: { id: "psd-clinical" }, llm_policy: { default: "zai/glm-5.2", allowed: ["zai/glm-5.2"] } },
revision: revision("psd-clinical"),
})),
http.get("http://localhost:8787/models", () => HttpResponse.json({ models: [
{ provider: "zai", id: "glm-5.2", name: "GLM-5.2", reasoning: true },
{ provider: "deepseek", id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", reasoning: true },
] })),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
}),
);
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
render(<QueryClientProvider client={client}><ComposerFooter /><SteerInput sessionId={null} /></QueryClientProvider>);
const workspaceSelector = await screen.findByRole("combobox", { name: "Workspace" });
await waitFor(() => expect(workspaceSelector).toHaveTextContent("psd-clinical"));
await userEvent.selectOptions(workspaceSelector, "psd-clinical");
await waitFor(() => expect(screen.getByRole("combobox", { name: "Model" })).toHaveValue("glm-5.2"));
expect(screen.getByRole("combobox", { name: "Model" })).not.toHaveTextContent("DeepSeek V4 Pro");
await userEvent.type(screen.getByRole("textbox", { name: /new question/i }), "q");
await userEvent.click(screen.getByRole("button", { name: /send/i }));
await waitFor(() => expect(body).toEqual({
question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "medium",
}));
});
test("pulses the stop dot only while the harness is working", () => {
const { rerender } = render(<SteerInput sessionId="s1" working />);
const dot = () =>