Files
ThothII/frontend/src/App.test.tsx
T

120 lines
4.4 KiB
TypeScript

import { cleanup, render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { http, HttpResponse } from "msw";
import { server } from "./test/msw";
import { App } from "./App";
beforeEach(() => { window.__THOTHII_CONFIG__ = { shell: { mode: "full", defaultLocale: "en" } }; });
afterEach(() => {
cleanup();
delete window.__THOTHII_CONFIG__;
document.querySelector(".omics-language-select")?.remove();
document.documentElement.removeAttribute("data-bs-theme");
});
function registerAuthenticatedShell(mode: "local" | "upstream") {
server.use(
http.get("/api/auth/config", () => HttpResponse.json({
mode,
localLogin: mode === "local",
oidcLogin: false,
})),
http.get("/api/me", () => HttpResponse.json({
issuer: mode === "local" ? "local" : "portal",
subject: "portal-user",
displayName: "Portal user",
roles: ["user"],
permissions: ["session.use"],
isAdmin: false,
csrfToken: mode === "local" ? "c".repeat(43) : null,
session: null,
})),
http.get("/api/settings", () => HttpResponse.json({
workspace: "psd", provider: "zai", model: "glm-5.2", thinking: "medium",
})),
http.get("/api/workspaces", () => HttpResponse.json([])),
http.get("/api/models", () => HttpResponse.json({ models: [] })),
http.get("/api/sessions", () => HttpResponse.json([])),
http.get("/api/workspace-registry/status", () => HttpResponse.json({
branch: "main", ahead: 0, behind: 0, degraded: false,
})),
);
}
test("local authentication renders the standalone logout control", async () => {
registerAuthenticatedShell("local");
render(<App />);
expect(await screen.findByRole("button", { name: "Session" })).toBeInTheDocument();
expect(screen.getByText("Portal user")).toBeInTheDocument();
await userEvent.click(within(screen.getByRole("banner", { name: "Application header" })).getByRole("button", { name: "Portal user" }));
expect(await screen.findByRole("menuitem", { name: "Log out" })).toBeInTheDocument();
});
test("trusted upstream authentication keeps identity but omits ThothII logout", async () => {
delete window.__THOTHII_CONFIG__;
const select = document.createElement("select");
select.className = "omics-language-select";
select.dataset.lang = "en";
document.body.append(select);
document.documentElement.setAttribute("data-bs-theme", "light");
registerAuthenticatedShell("upstream");
render(<App />);
expect(await screen.findByText("Portal user")).toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Log out" })).not.toBeInTheDocument();
});
test("a local login always enters the core activity", async () => {
let signedIn = false;
localStorage.setItem("thothii:app-navigation", JSON.stringify({
surface: "database-management",
panel: null,
}));
server.use(
http.get("/api/auth/config", () => HttpResponse.json({
mode: "local",
localLogin: true,
oidcLogin: false,
})),
http.get("/api/me", () => signedIn
? HttpResponse.json({
issuer: "local",
subject: "admin-user",
displayName: "Admin user",
roles: ["admin"],
permissions: ["session.use", "database.manage"],
isAdmin: true,
csrfToken: "c".repeat(43),
session: null,
})
: new HttpResponse(null, { status: 401 })),
http.post("/api/auth/local/login", () => {
signedIn = true;
return HttpResponse.json({});
}),
http.get("/api/settings", () => HttpResponse.json({
workspace: "psd", provider: "zai", model: "glm-5.2", thinking: "medium",
})),
http.get("/api/workspaces", () => HttpResponse.json([])),
http.get("/api/models", () => HttpResponse.json({ models: [] })),
http.get("/api/sessions", () => HttpResponse.json([])),
http.get("/api/workspace-registry/status", () => HttpResponse.json({
branch: "main", ahead: 0, behind: 0, degraded: false,
})),
);
render(<App />);
await screen.findByRole("heading", { name: /sign in to thothii/i });
await userEvent.type(screen.getByLabelText(/username/i), "admin");
await userEvent.type(screen.getByLabelText(/^password$/i), "correct-password");
await userEvent.click(screen.getByRole("button", { name: /sign in/i }));
expect(await screen.findByRole("button", { name: "Session" }))
.toHaveAttribute("aria-current", "page");
expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument();
});