import { describe, expect, it, vi } from "vitest"; import { PERMS } from "@/lib/permission-slugs"; import { HOUSEKEEPING_MANIFESTS } from "../manifests"; import { anyCapability, type HousekeepingCapabilityContext } from "./contracts"; import { buildHousekeepingNavigation } from "./navigation"; import { createHousekeepingRegistry } from "./registry"; const context = ( granted: readonly string[], ): HousekeepingCapabilityContext => ({ actor: { id: 42, username: "moderator", rank: 3 }, isSuperAdmin: false, has: (slug) => granted.includes(slug), hasAny: (...slugs) => slugs.some((slug) => granted.includes(slug)), hasAll: (...slugs) => slugs.every((slug) => granted.includes(slug)), }); describe("housekeeping navigation", () => { it("shows People to a moderator with a mod view capability while hiding Economy", () => { const registry = createHousekeepingRegistry([ { id: "people", labelKey: "pages.housekeeping.domains.people.title", descriptionKey: "pages.housekeeping.domains.people.description", iconId: "users", canonicalHref: "/ase/people", capability: anyCapability(PERMS.MOD_CFH_VIEW), routes: [], searchProviders: [], inboxSources: [], widgets: [], }, { id: "economy", labelKey: "pages.housekeeping.domains.economy.title", descriptionKey: "pages.housekeeping.domains.economy.description", iconId: "gem", canonicalHref: "/ase/economy", capability: anyCapability(PERMS.CATALOG_VIEW), routes: [], searchProviders: [], inboxSources: [], widgets: [], }, ]); const navigation = buildHousekeepingNavigation( registry, context([PERMS.MOD_CFH_VIEW]), "canonical", (key) => key, ); expect(navigation).toEqual([ { id: "people", href: "/ase/people", iconId: "users", label: "pages.housekeeping.domains.people.title", description: "pages.housekeeping.domains.people.description", items: [], }, ]); }); it("filters unauthorized domains and routes before translation", () => { const registry = createHousekeepingRegistry([ { id: "people", labelKey: "people.title", descriptionKey: "people.description", iconId: "users", canonicalHref: "/ase/people", capability: anyCapability(PERMS.USERS_VIEW), routes: [ { id: "users", labelKey: "people.users", href: "/ase/people/users", capability: anyCapability(PERMS.USERS_VIEW), }, { id: "bans", labelKey: "people.bans", href: "/ase/people/bans", capability: anyCapability(PERMS.BANS_VIEW), }, ], searchProviders: [], inboxSources: [], widgets: [], }, { id: "system", labelKey: "system.title", descriptionKey: "system.description", iconId: "settings", canonicalHref: "/ase/system", capability: anyCapability(PERMS.SETTINGS_VIEW), routes: [], searchProviders: [], inboxSources: [], widgets: [], }, ]); const translate = vi.fn((key: string) => `translated:${key}`); const navigation = buildHousekeepingNavigation( registry, context([PERMS.USERS_VIEW]), "canonical", translate, ); expect(navigation).toEqual([ { id: "people", href: "/ase/people", iconId: "users", label: "translated:people.title", description: "translated:people.description", items: [ { id: "users", href: "/ase/people/users", label: "translated:people.users", }, ], }, ]); expect(translate).not.toHaveBeenCalledWith("people.bans"); expect(translate).not.toHaveBeenCalledWith("system.title"); expect(translate).not.toHaveBeenCalledWith("system.description"); }); it("shows real domains to operators authorized by owned migration capabilities", () => { const registry = createHousekeepingRegistry(HOUSEKEEPING_MANIFESTS); const translate = (key: string) => key; expect( buildHousekeepingNavigation( registry, context([PERMS.MOD_CFH_VIEW]), "preview", translate, ).map((domain) => domain.id), ).toContain("people"); expect( buildHousekeepingNavigation( registry, context([PERMS.MOD_CFH_VIEW]), "preview", translate, ).map((domain) => domain.id), ).not.toContain("economy"); for (const [slug, expectedDomain] of [ [PERMS.MOD_ACTIONS, "people"], [PERMS.USERS_EDIT, "people"], [PERMS.SETTINGS_VIEW, "people"], [PERMS.NEWS_EDIT, "content"], [PERMS.SHOP_EDIT, "economy"], [PERMS.ROOMS_EDIT, "hotel"], ] as const) { const visibleDomainIds = buildHousekeepingNavigation( registry, context([slug]), "preview", translate, ).map((domain) => domain.id); expect(visibleDomainIds, slug).toContain(expectedDomain); } }); }); it("maps canonical navigation hrefs onto the requested surface", () => { const registry = createHousekeepingRegistry([ { id: "people", labelKey: "people.title", descriptionKey: "people.description", iconId: "users", canonicalHref: "/ase/people", capability: anyCapability(PERMS.USERS_VIEW), routes: [ { id: "users", labelKey: "people.users", href: "/ase/people/users", capability: anyCapability(PERMS.USERS_VIEW), }, ], searchProviders: [], inboxSources: [], widgets: [], }, ]); const navigation = buildHousekeepingNavigation( registry, context([PERMS.USERS_VIEW]), "preview", (key) => key, ); expect(navigation[0]).toMatchObject({ href: "/ase-next/people", items: [{ href: "/ase-next/people/users" }], }); });