import { describe, expect, test } from "vitest"; import { fallbackNavigation, filterNavigationByPermission, mapBackendMenus, mergeNavigationItems } from "./menu.js"; describe("navigation menu helpers", () => { test("keeps only fallback menu items allowed by permissions", () => { const items = filterNavigationByPermission( fallbackNavigation, (code) => code === "agency:view" || code === "host:view", ); expect(flattenCodes(items)).not.toContain("geo"); expect(flattenCodes(items)).toContain("host-org"); expect(flattenCodes(items)).toContain("host-org-managers"); expect(flattenCodes(items)).toContain("host-org-agencies"); expect(flattenCodes(items)).toContain("host-org-hosts"); expect(flattenCodes(items)).not.toContain("host-org-bds"); }); test("places country and region pages under geo menu", () => { const items = filterNavigationByPermission( fallbackNavigation, (code) => code === "country:view" || code === "region:view", ); const geo = items.find((item) => item.code === "geo"); expect(geo).toBeTruthy(); expect(geo.children.map((item) => item.code)).toEqual(["host-org-countries", "host-org-regions"]); expect(flattenCodes(items)).not.toContain("host-org"); }); test("keeps the app user login log entry routable", () => { const items = filterNavigationByPermission(fallbackNavigation, (code) => code === "app-user:view"); const appUsers = items.find((item) => item.code === "app-users"); expect(appUsers.children.map((item) => item.code)).toContain("app-user-login-logs"); expect(appUsers.children.find((item) => item.code === "app-user-login-logs").path).toBe( "/app/users/login-logs", ); }); test("adds missing permitted fallback children to backend menu groups", () => { const backendMenus = [ { children: [], code: "host-org", icon: fallbackNavigation.find((item) => item.code === "host-org").icon, id: "host-org", label: "团队管理", }, ]; const fallbackMenus = filterNavigationByPermission(fallbackNavigation, (code) => code === "agency:view"); const merged = mergeNavigationItems(backendMenus, fallbackMenus); expect(flattenCodes(merged)).toContain("host-org-agencies"); expect(flattenCodes(merged)).toContain("host-org-managers"); }); test("places recharge products under app config even when backend menu is stale", () => { const mapped = mapBackendMenus([ { children: [], code: "app-config", icon: "settings", id: "app-config", label: "APP配置" }, { children: [ { code: "payment-recharge-products", icon: "wallet", id: "payment-recharge-products", label: "内购配置", path: "/payment/recharge-products", permissionCode: "payment-product:view", }, ], code: "payment", icon: "wallet", id: "payment", label: "支付管理", }, ]); const appConfig = mapped.find((item) => item.code === "app-config"); const payment = mapped.find((item) => item.code === "payment"); expect(appConfig.children.map((item) => item.code)).toContain("payment-recharge-products"); expect(appConfig.children.find((item) => item.code === "payment-recharge-products").path).toBe( "/app-config/recharge-products", ); expect(payment).toBeUndefined(); }); }); function flattenCodes(items) { return items.flatMap((item) => [item.code, ...flattenCodes(item.children || [])]); }