import { render, screen, waitFor, within } 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 { workspaceSummaryFixture } from "../test/workspace-fixtures"; import { FakeEventSource } from "../test/fakeEventSource"; import { useSessionStore } from "../store/sessionStore"; import { clearAuthState, setAuthState } from "../auth/authState"; import { AppShell, resolveDatabaseManagementPresentation } from "./AppShell"; function renderShell() { const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return render( , ); } async function expandAdministration() { await userEvent.click(screen.getByRole("button", { name: "Administration" })); } beforeEach(() => { clearAuthState(); setAuthState({ issuer: "test", subject: "test", roles: ["admin"], permissions: ["session.use", "workspace.manage", "workspace.secrets.manage", "database.manage", "pi.manage"], isAdmin: true, csrfToken: null, session: null, }); localStorage.clear(); window.history.replaceState(null, "", "/"); FakeEventSource.instances = []; (globalThis as any).EventSource = FakeEventSource; useSessionStore.getState().resetSession(); server.use( http.get("/api/me", () => HttpResponse.json({ issuer: "test", subject: "test", displayName: "Test", isAdmin: true, })), http.get("/api/sessions", () => HttpResponse.json([])), http.get("/api/settings", () => HttpResponse.json({ workspace: "default", provider: "test", model: "test", thinking: "low", })), http.get("/api/workspaces", () => HttpResponse.json([workspaceSummaryFixture("default")])), http.get("/api/models", () => HttpResponse.json({ models: [{ provider: "test", id: "test", name: "Test LLM", reasoning: true }] })), http.post("/api/runtime/prewarm", () => new HttpResponse(null, { status: 202 })), http.get("/api/catalog/metrics", () => HttpResponse.json({ scope: "global", databaseId: null, tables: 0, columns: 0, sensitiveColumns: 0, relationships: 0, descriptionTargets: 0, describedTargets: 0, descriptionCoverage: 0, updatedAt: null, })), ); }); test("uses Fleet Ledger by default and gates the legacy fallback to non-production environments", () => { expect(resolveDatabaseManagementPresentation({ isDevelopment: true, mode: "development", search: "", })).toBe("fleet"); expect(resolveDatabaseManagementPresentation({ isDevelopment: true, mode: "development", search: "?db-ui=legacy", })).toBe("legacy"); expect(resolveDatabaseManagementPresentation({ isDevelopment: false, mode: "staging", legacyFlag: "true", search: "", })).toBe("legacy"); expect(resolveDatabaseManagementPresentation({ isDevelopment: false, mode: "production", legacyFlag: "true", search: "?db-ui=legacy", })).toBe("fleet"); }); test("starts on the core activity after a hard refresh even if metadata management was open", async () => { localStorage.setItem("thothii:app-navigation", JSON.stringify({ surface: "database-management", panel: null, })); renderShell(); await expandAdministration(); const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" }); expect(within(sessionNavigation).getByRole("button", { name: "Session" })) .toHaveAttribute("aria-current", "page"); expect(within(sessionNavigation).getByRole("button", { name: "Database" })) .not.toHaveAttribute("aria-current"); expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument(); }); test("replaces the core conversation while keeping the session navigation", async () => { renderShell(); await expandAdministration(); const conversationColumn = screen.getByTestId("conversation-column"); const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" }); const newSession = within(sessionNavigation).getByRole("button", { name: "Session" }); const databaseManagement = within(sessionNavigation).getByRole("button", { name: "Database" }); expect(newSession).toHaveAttribute("aria-current", "page"); expect(newSession).toHaveAttribute("data-navigation-state", "current"); expect(newSession).toHaveClass("bg-[oklch(var(--nav-active))]"); expect(databaseManagement).toHaveAttribute("data-navigation-state", "available"); expect(databaseManagement).not.toHaveAttribute("aria-current"); await userEvent.click(databaseManagement); const manager = screen.getByRole("main", { name: "Database management" }); expect(manager).toBeVisible(); expect(conversationColumn).toContainElement(manager); expect(screen.getByRole("complementary", { name: "Session navigation" })).toBe(sessionNavigation); expect(sessionNavigation).toBeVisible(); expect(newSession).toBeVisible(); expect(newSession).toHaveAttribute("data-navigation-state", "available"); expect(newSession).not.toHaveAttribute("aria-current"); expect(newSession).not.toHaveClass("bg-[oklch(var(--nav-active))]"); expect(databaseManagement).toHaveAttribute("aria-current", "page"); expect(databaseManagement).toHaveAttribute("data-navigation-state", "current"); expect(databaseManagement).toHaveClass("bg-[oklch(var(--nav-active))]"); expect(screen.queryByRole("button", { name: "Back to workspace" })).not.toBeInTheDocument(); expect(screen.queryByRole("textbox", { name: /new question/i })).not.toBeInTheDocument(); }); test("keeps a live core session connected while returning from database management", async () => { let resumes = 0; server.use( http.get("/api/sessions", () => HttpResponse.json([{ id: "s1", status: "open", question: "Active question", summary: null, created_at: "2026-01-02T00:00:00Z", updated_at: null, author: "test", name: null, group: null, archived: false, active: true, }])), http.post("/api/sessions/:id/resume", ({ params }) => { resumes++; return HttpResponse.json({ id: params.id, alreadyActive: true, }); }), http.get("/api/sessions/:id", ({ params }) => HttpResponse.json({ id: params.id, status: "open", phase: 1, })), ); renderShell(); await expandAdministration(); await userEvent.click(screen.getByRole("button", { name: "Active sessions" })); const session = await screen.findByTestId("session-item-s1"); await userEvent.click(session); await waitFor(() => expect(FakeEventSource.instances).toHaveLength(1)); const source = FakeEventSource.instances[0]; await userEvent.click(screen.getByRole("button", { name: "Database" })); expect(screen.getByRole("main", { name: "Database management" })).toBeVisible(); expect(source.closed).toBe(false); expect(FakeEventSource.instances).toHaveLength(1); expect(session).toBeVisible(); expect(screen.queryByRole("button", { name: "Return to session" })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: "New session" })).not.toBeInTheDocument(); await userEvent.click(screen.getByRole("button", { name: "Session" })); await waitFor(() => { expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument(); }); expect(source.closed).toBe(false); expect(FakeEventSource.instances).toHaveLength(1); expect(resumes).toBe(1); await userEvent.click(screen.getByRole("button", { name: "Session" })); expect(source.closed).toBe(false); expect(resumes).toBe(1); }); test("hides the complete administrative navigation from a regular user", () => { clearAuthState(); setAuthState({ issuer: "test", subject: "test", roles: ["user"], permissions: ["session.use"], isAdmin: false, csrfToken: null, session: null, }); renderShell(); expect(screen.getByRole("button", { name: "Session" })).toBeInTheDocument(); expect(screen.queryByRole("button", { name: "Administration" })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: "Workspace" })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: "Database" })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: "Pi configuration" })).not.toBeInTheDocument(); }); test("requires saving or cancelling a dirty database form before leaving", async () => { server.use(http.get("/api/catalog/databases", () => HttpResponse.json([{ id: "11111111-1111-4111-8111-111111111111", workspaceId: "default", workspaceName: "Policlinico San Donato", workspaceAvailable: true, workspaceRevision: { commit: "a".repeat(40), blob: "b".repeat(40) }, workspaceEvidence: { sourceType: "filesystem", state: "materialized_current_revision" }, runtimeBinding: { transport: "postgres_direct", configurationState: "ready", sessionTransportSupported: true, }, configured: true, engine: "postgres", databaseName: "warehouse", schema: "datawarehouse", version: 3, createdAt: "2026-08-27T08:00:00Z", updatedAt: "2026-08-27T09:00:00Z", binding: { transport: "postgres_direct", host: "db.internal", port: 5432, username: "reader" }, connectionStatus: "untested", secrets: { password: false, apiKey: false, sshPrivateKey: false, sshPrivateKeyPassphrase: false, sshKnownHosts: false, tlsCa: false, }, }]))); const confirm = vi.spyOn(window, "confirm").mockReturnValue(false); renderShell(); await expandAdministration(); await userEvent.click(screen.getByRole("button", { name: "Database" })); await userEvent.click(await screen.findByRole("button", { name: "Edit Policlinico San Donato" })); const schema = await screen.findByLabelText("Schema"); await userEvent.clear(schema); await userEvent.type(schema, "reporting"); const newSession = screen.getByRole("button", { name: "Session" }); await userEvent.click(newSession); expect(confirm).not.toHaveBeenCalled(); expect(screen.getByRole("main", { name: "Database management" })).toBeVisible(); expect(schema).toHaveValue("reporting"); confirm.mockReturnValue(true); await userEvent.click(screen.getByRole("button", { name: "Back to list" })); await userEvent.click(newSession); await waitFor(() => expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument()); confirm.mockRestore(); });