feat(frontend): add database management surface
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
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 { FakeEventSource } from "../test/fakeEventSource";
|
||||
import { useSessionStore } from "../store/sessionStore";
|
||||
import { clearAuthState, setAuthState } from "../auth/authState";
|
||||
import { AppShell } from "./AppShell";
|
||||
|
||||
function renderShell() {
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
return render(
|
||||
<QueryClientProvider client={client}>
|
||||
<AppShell canLogout={false} />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
clearAuthState();
|
||||
setAuthState({
|
||||
issuer: "test",
|
||||
subject: "test",
|
||||
roles: ["user"],
|
||||
permissions: ["session.use", "workspace.manage"],
|
||||
isAdmin: false,
|
||||
csrfToken: null,
|
||||
session: null,
|
||||
});
|
||||
localStorage.clear();
|
||||
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: false,
|
||||
})),
|
||||
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([])),
|
||||
http.get("/api/models", () => HttpResponse.json({ models: [] })),
|
||||
http.post("/api/runtime/prewarm", () => new HttpResponse(null, { status: 202 })),
|
||||
);
|
||||
});
|
||||
|
||||
test("opens the blank database management surface and returns to the core", async () => {
|
||||
renderShell();
|
||||
|
||||
const composer = screen.getByRole("textbox", { name: /new question/i });
|
||||
await userEvent.type(composer, "Unsent draft");
|
||||
|
||||
const databaseManagement = screen.getByRole("button", { name: "Database management" });
|
||||
await userEvent.click(databaseManagement);
|
||||
|
||||
expect(screen.getByRole("main", { name: "Database management" })).toBeVisible();
|
||||
expect(databaseManagement).toHaveAttribute("aria-current", "page");
|
||||
expect(databaseManagement).toHaveClass("bg-sidebar-accent", "font-bold");
|
||||
expect(screen.queryByRole("textbox", { name: /new question/i })).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "New session" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByRole("textbox", { name: /new question/i })).toHaveValue("Unsent draft");
|
||||
});
|
||||
|
||||
test("keeps a live core session connected and returns when that session is opened", async () => {
|
||||
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 }) => HttpResponse.json({
|
||||
id: params.id,
|
||||
alreadyActive: true,
|
||||
})),
|
||||
http.get("/api/sessions/:id", ({ params }) => HttpResponse.json({
|
||||
id: params.id,
|
||||
status: "open",
|
||||
phase: 1,
|
||||
})),
|
||||
);
|
||||
renderShell();
|
||||
|
||||
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 management" }));
|
||||
|
||||
expect(screen.getByRole("main", { name: "Database management" })).toBeVisible();
|
||||
expect(source.closed).toBe(false);
|
||||
expect(FakeEventSource.instances).toHaveLength(1);
|
||||
|
||||
await userEvent.click(session);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument();
|
||||
});
|
||||
expect(source.closed).toBe(false);
|
||||
expect(FakeEventSource.instances).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("hides database management from users without workspace management permission", () => {
|
||||
clearAuthState();
|
||||
setAuthState({
|
||||
issuer: "test",
|
||||
subject: "test",
|
||||
roles: ["user"],
|
||||
permissions: ["session.use"],
|
||||
isAdmin: false,
|
||||
csrfToken: null,
|
||||
session: null,
|
||||
});
|
||||
|
||||
renderShell();
|
||||
|
||||
expect(screen.queryByRole("button", { name: "Database management" })).not.toBeInTheDocument();
|
||||
});
|
||||
Reference in New Issue
Block a user