import type { ServerConfig } from "@shared/serverConfig"; import { render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { getConfig } from "@/modules/config"; import App from "./App"; vi.mock("@/modules/config", async (importOriginal) => ({ ...(await importOriginal()), getConfig: vi.fn(), })); vi.mock("@/modules/accessKey", () => ({ verifyStoredAccessKey: vi.fn().mockResolvedValue(false), })); vi.mock("../Pages/Main/MainPage", () => ({ default: () =>
, })); vi.mock("../Pages/AccessPage", () => ({ default: () =>
, })); const serverConfig: ServerConfig = { accessKeysEnabled: false, accessKeyTimeoutHours: 24, wllamaDefaultModelId: "littlelamb-290m", internalApiEnabled: false, internalApiName: "Internal API", defaultInferenceType: "browser", searchToken: "a".repeat(64), }; describe("App", () => { beforeEach(() => { vi.clearAllMocks(); localStorage.clear(); }); it("shows the main page when access keys are disabled", async () => { vi.mocked(getConfig).mockResolvedValue(serverConfig); render(); expect(await screen.findByTestId("main-page")).toBeInTheDocument(); }); it("shows the access page when access keys are enabled", async () => { vi.mocked(getConfig).mockResolvedValue({ ...serverConfig, accessKeysEnabled: true, }); render(); expect(await screen.findByTestId("access-page")).toBeInTheDocument(); expect(screen.queryByTestId("main-page")).not.toBeInTheDocument(); }); /** * Renders a fresh module instance so the settings module reads the profile * seeded here, since it captures localStorage once at import. */ async function renderWithStoredSettings(stored: Record) { vi.resetModules(); localStorage.setItem("settings", JSON.stringify(stored)); const [ { getConfig: freshGetConfig }, { default: FreshApp }, { getSettings }, ] = await Promise.all([ import("@/modules/config"), import("./App"), import("@/modules/pubSub"), ]); vi.mocked(freshGetConfig).mockResolvedValue(serverConfig); render(); await screen.findByTestId("main-page"); return getSettings; } it("fills in a setting the stored profile predates", async () => { const getSettings = await renderWithStoredSettings({ enableAiResponse: true, }); await waitFor(() => expect(getSettings().enablePageContentFetch).toBe(true), ); }); // The other half of that merge: a stored value is a choice, including one // that turns off something shipped on. it("keeps a setting the user turned off", async () => { const getSettings = await renderWithStoredSettings({ enableAiResponse: true, enablePageContentFetch: false, }); await waitFor(() => expect(getSettings().enablePageContentFetch).toBe(false), ); }); // Guards the fail-open regression: an unreachable /api/config used to look // exactly like `accessKeysEnabled: false`, letting the app through the gate. it("refuses to render the app when the config cannot be loaded", async () => { vi.mocked(getConfig).mockRejectedValue(new Error("Network error")); render(); await waitFor(() => { expect( screen.getByText(/could not load the server configuration/i), ).toBeInTheDocument(); }); expect(screen.queryByTestId("main-page")).not.toBeInTheDocument(); expect(screen.queryByTestId("access-page")).not.toBeInTheDocument(); }); });