Files
nxdns/admin/src/shell/AppShell.test.tsx
T
mokhtar 037f209179
Gates / frontend (push) Successful in 1m33s
Gates / test (push) Successful in 1m48s
Gates / test-aarch64 (push) Successful in 7m10s
Gates / package (push) Successful in 5m31s
Gates / container (push) Successful in 15s
CI / gates (push) Successful in 14m51s
milestone 27: diagnostics — operational failures land in one curated log, resolved history purgeable
2026-08-20 20:05:59 +02:00

129 lines
3.8 KiB
TypeScript

import { fireEvent, render, screen } from "@testing-library/react";
import { QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider, createMemoryHistory } from "@tanstack/react-router";
import { AuthProvider, resetAuthProbeForTests } from "@/auth/store";
import { createQueryClient } from "@/lib/queryClient";
import { createAppRouter } from "@/routes";
const NAV_LABELS = [
"Dashboard",
"Query Log",
"Live",
"Clients",
"Groups",
"Blocklists",
"Rules",
"Local DNS",
"Upstreams",
"Lookup",
"Diagnostics",
"Settings",
];
const RESPONSES: Record<string, unknown> = {
"/api/stats?period=24h": {
period: "24h",
since: 0,
until: 86400,
queries: 0,
blocked: 0,
cached: 0,
clients: 0,
avg_response_time_us: null,
},
"/api/stats/timeseries?period=24h": { period: "24h", since: 0, until: 86400, bucket_seconds: 1800, buckets: [] },
"/api/health": {
status: "ok",
disk: { state: "ok", free_bytes: 0, db_bytes: 0, log_bytes: 0, sample_failures: 0 },
upstreams: { available: 1, total: 1 },
queries_dropped: 0,
writer_failed: false,
refreshes_gated: 0,
snapshot_generation: null,
diagnostics: { state: "recording", active_warnings: 0, active_errors: 0 },
},
"/api/upstream/health": { upstreams: [], available: 1, total: 1 },
"/api/version": { version: "0.0.0-test", git_commit: "0000000", zig_version: "0.16.0", uptime_seconds: 1 },
};
beforeEach(() => {
sessionStorage.clear();
resetAuthProbeForTests();
vi.stubGlobal(
"fetch",
vi.fn(async (input: RequestInfo | URL) => {
const url = String(input);
const payload = RESPONSES[url];
if (payload === undefined) return new Response(JSON.stringify({ error: "not stubbed" }), { status: 404 });
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "content-type": "application/json" },
});
}),
);
});
afterEach(() => {
vi.unstubAllGlobals();
});
test("shell renders the dashboard route with all nav links", async () => {
const queryClient = createQueryClient();
const router = createAppRouter(createMemoryHistory({ initialEntries: ["/"] }), queryClient);
render(
<AuthProvider>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</AuthProvider>,
);
await screen.findByRole("heading", { name: "Dashboard" });
const nav = screen.getByRole("navigation", { name: "Main" });
expect(nav).toBeTruthy();
for (const label of NAV_LABELS) {
expect(screen.getByRole("link", { name: label })).toBeTruthy();
}
});
test("mount probe reveals the logout button and a failed logout surfaces inline", async () => {
vi.stubGlobal(
"fetch",
vi.fn(async (input: RequestInfo | URL) => {
const url = String(input);
if (url === "/api/auth/login")
return new Response(JSON.stringify({ error: "password required" }), {
status: 401,
headers: { "content-type": "application/json" },
});
if (url === "/api/auth/logout")
return new Response(JSON.stringify({ error: "rate limited" }), {
status: 429,
headers: { "content-type": "application/json", "retry-after": "7" },
});
const payload = RESPONSES[url];
if (payload === undefined) return new Response(JSON.stringify({ error: "not stubbed" }), { status: 404 });
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "content-type": "application/json" },
});
}),
);
const queryClient = createQueryClient();
const router = createAppRouter(createMemoryHistory({ initialEntries: ["/"] }), queryClient);
render(
<AuthProvider>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</AuthProvider>,
);
fireEvent.click(await screen.findByRole("button", { name: "Log out" }));
await screen.findByText("Rate limited. Try again in 7s.");
expect(screen.getByRole("heading", { name: "Dashboard" })).toBeTruthy();
});