import { render, screen, waitFor } from "@testing-library/react"; import { QueryClientProvider } from "@tanstack/react-query"; import { createQueryClient } from "@/lib/queryClient"; import DefinitionList from "@/ui/DefinitionList"; import ConfigLockIndicator from "./ConfigLockIndicator"; import { CONFIG_PATH, DATABASE, MANAGED_FILE, stubApi } from "./testFixtures"; import type { ConfigStatus } from "@/lib/types"; /** * The two shared pieces the redesign adds: the file-mode rendering of a scalar * and the compact lock a configuration control outside a configuration page * carries. */ afterEach(() => { vi.unstubAllGlobals(); }); function renderIndicator(status: ConfigStatus | "failed") { if (status === "failed") { stubApi(DATABASE, { responses: { "GET /api/config/status": new Response(JSON.stringify({ error: "unavailable" }), { status: 503 }), }, }); } else { stubApi(status); } render( , ); } test("a definition names the value in words and the file key beside it", () => { render( , ); const port = screen.getByText("Port"); expect(port.tagName).toBe("DT"); expect(port.textContent).toBe("Portdns.port"); // A derived value has no key: inventing one would send the reader looking // for a line that is not in the file. expect(screen.getByText("Authentication").textContent).toBe("Authentication"); expect(screen.getByText("required").tagName).toBe("DD"); }); test("the lock is silent when the database owns the configuration", async () => { renderIndicator(DATABASE); await waitFor(() => expect(screen.queryByText("Locked")).toBeNull()); }); test("under file authority the lock names the file, in words a reader hears", async () => { renderIndicator(MANAGED_FILE); const lock = await screen.findByText("Locked"); await waitFor(() => expect(lock.getAttribute("aria-label")).toBe( `Locked. Managed by ${CONFIG_PATH}; edit the file and restart nxdns.`, ), ); }); test("an unanswered status still locks, and says that is why", async () => { renderIndicator("failed"); const lock = await screen.findByText("Locked"); await waitFor(() => expect(lock.getAttribute("aria-label")).toContain("Configuration status unavailable")); });