// frontend/src/shell/NewSessionDialog.test.tsx
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { http, HttpResponse } from "msw";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { server } from "../test/msw";
import { NewSessionDialog } from "./NewSessionDialog";
function renderDialog() {
const onCreated = vi.fn();
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
render(
,
);
return { onCreated };
}
test("the form has only a question field (no workspace/model/provider/thinking)", async () => {
renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));
expect(await screen.findByLabelText(/question/i)).toBeInTheDocument();
expect(screen.queryByLabelText(/workspace/i)).not.toBeInTheDocument();
expect(screen.queryByLabelText(/model/i)).not.toBeInTheDocument();
expect(screen.queryByLabelText(/provider/i)).not.toBeInTheDocument();
expect(screen.queryByLabelText(/thinking/i)).not.toBeInTheDocument();
});
test("submitting includes browser-local migrated preferences and calls onCreated", async () => {
localStorage.clear();
let body: unknown = null;
server.use(
http.get("http://localhost:8787/settings", () => HttpResponse.json({
workspace: "default", provider: "zai", model: "glm-5.2", thinking: "low",
})),
http.get("http://localhost:8787/workspaces", () => HttpResponse.json([{
id: "default", name: "default", file: "default.yaml", displayName: "Default",
}])),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
}),
);
const { onCreated } = renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));
await userEvent.type(await screen.findByLabelText(/question/i), "Quante vendite nel 2025?");
await userEvent.click(screen.getByRole("button", { name: /^create$/i }));
await waitFor(() => expect(body).toEqual({
question: "Quante vendite nel 2025?",
workspaceId: "default", provider: "zai", model: "glm-5.2", thinking: "low",
}));
await waitFor(() => expect(onCreated).toHaveBeenCalledWith("s1"));
});
test("first-run direct dialog creation waits for registry policy without a mounted footer", async () => {
let body: unknown;
let releasePolicy!: () => void;
let summaryRequestStarted = false;
let policyRequestStarted = false;
const policyMayFinish = new Promise((resolve) => { releasePolicy = resolve; });
const revision = {
id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", state: "operational" as const,
};
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspaceId: "psd-clinical", provider: "deepseek", model: "deepseek-v4-pro", thinking: "medium",
}));
server.use(
http.get("http://localhost:8787/workspaces", () => {
summaryRequestStarted = true;
return HttpResponse.json([{
id: "psd-clinical", name: "psd-clinical", file: "psd-clinical.yaml", displayName: "PSD Clinical",
revision,
}]);
}),
http.get("http://localhost:8787/workspaces/psd-clinical", async () => {
policyRequestStarted = true;
await policyMayFinish;
return HttpResponse.json({
workspace: { llm_policy: { default: "zai/glm-5.2", allowed: ["zai/glm-5.2"] } }, revision,
});
}),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
}),
);
const { onCreated } = renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));
await userEvent.type(await screen.findByLabelText(/question/i), "q");
await userEvent.click(screen.getByRole("button", { name: /^create$/i }));
await waitFor(() => expect(summaryRequestStarted).toBe(true));
await waitFor(() => expect(policyRequestStarted).toBe(true));
expect(body).toBeUndefined();
expect(screen.getByRole("button", { name: /creating/i })).toBeDisabled();
releasePolicy();
await waitFor(() => expect(body).toEqual({
question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "medium",
}));
await waitFor(() => expect(onCreated).toHaveBeenCalledWith("s1"));
});
test("empty question shows a validation error and does not submit", async () => {
renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));
await userEvent.click(screen.getByRole("button", { name: /^create$/i }));
expect(await screen.findByRole("alert")).toHaveTextContent(/empty/i);
});