// @vitest-environment jsdom // // E31 (the owner's pick): Configuration's sixteen group tabs wrapped to three rows at 133% zoom, so they // are a side list under four headings, as Settings has. The registry owns the order: the groups follow // its sections, not the order the groups object happens to arrive in. import { afterEach, describe, expect, it, vi } from "vitest"; import { cleanup, fireEvent, render, screen } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { ConfigItem } from "../lib/api"; vi.mock("react-i18next", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useTranslation: () => ({ t: (key: string) => key, i18n: { language: "en" } }), }; }); const text = (key: string, group: string): ConfigItem => ({ key, type: "str", group, secret: false, min: null, max: null, is_set: false, allow_empty: true, choices: [], value: "", default: "", }); vi.mock("../lib/api", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, api: { ...actual.api, adminConfig: () => Promise.resolve({ groups: { b: [text("kb", "b")], c: [text("kc", "c")], a: [text("ka", "a")] }, sections: [ { id: "one", groups: ["a", "b"] }, { id: "two", groups: ["c"] }, ], secrets_manageable: true, }), }, }; }); vi.mock("../lib/useMe", () => ({ useMe: () => ({ email_configured: true }) })); import ConfigPanel from "./ConfigPanel"; afterEach(() => { cleanup(); localStorage.clear(); }); const renderPanel = () => render( , ); describe("Configuration sections (E31)", () => { it("lists the groups in the registry's sections, each heading once above its run", async () => { renderPanel(); const list = await screen.findByRole("tablist"); expect(list.getAttribute("aria-orientation")).toBe("vertical"); // The list's own lines, top to bottom: headings and tabs. const lines = Array.from(list.children).map((el) => el.getAttribute("role") === "tab" ? `tab:${el.textContent}` : `head:${el.textContent}`, ); expect(lines).toEqual([ "head:config.sections.one", "tab:config.groups.a", "tab:config.groups.b", "head:config.sections.two", "tab:config.groups.c", ]); }); it("opens on the first group and switches to the one picked", async () => { renderPanel(); expect(await screen.findByText("config.fields.ka.label")).toBeTruthy(); fireEvent.click(screen.getByRole("tab", { name: "config.groups.c" })); expect(screen.getByText("config.fields.kc.label")).toBeTruthy(); expect(screen.queryByText("config.fields.ka.label")).toBeNull(); }); });