179 lines
7.4 KiB
JavaScript
179 lines
7.4 KiB
JavaScript
import { describe, expect, test } from "vitest";
|
|
import { fallbackNavigation, filterNavigationByPermission, mapBackendMenus, mergeNavigationItems } from "./menu.js";
|
|
|
|
describe("navigation menu helpers", () => {
|
|
test("keeps requested parent menu order in fallback navigation", () => {
|
|
expect(fallbackNavigation.map((item) => item.code)).toEqual([
|
|
"overview",
|
|
"app-users",
|
|
"host-org",
|
|
"rooms",
|
|
"app-config",
|
|
"resources",
|
|
"operations",
|
|
"payment",
|
|
"activities",
|
|
"games",
|
|
"geo",
|
|
"system",
|
|
]);
|
|
});
|
|
|
|
test("normalizes requested parent menu order from backend menus", () => {
|
|
const mapped = mapBackendMenus([
|
|
{ children: [], code: "system", icon: "settings", id: "system", label: "后台设置" },
|
|
{ children: [], code: "geo", icon: "map", id: "geo", label: "地区管理" },
|
|
{ children: [], code: "host-org", icon: "network", id: "host-org", label: "团队管理" },
|
|
{ children: [], code: "app-users", icon: "users", id: "app-users", label: "用户管理" },
|
|
{ children: [], code: "overview", icon: "dashboard", id: "overview", label: "总览" },
|
|
]);
|
|
|
|
expect(mapped.map((item) => item.code)).toEqual(["overview", "app-users", "host-org", "geo", "system"]);
|
|
});
|
|
|
|
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("keeps payment children under payment menu when backend menu is current", () => {
|
|
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-third-party",
|
|
icon: "wallet",
|
|
id: "payment-third-party",
|
|
label: "第三方支付",
|
|
path: "/payment/third-party",
|
|
permissionCode: "payment-third-party: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 || []).toEqual([]);
|
|
expect(payment.children.map((item) => item.code)).toEqual(["payment-recharge-products", "payment-third-party"]);
|
|
expect(payment.children.find((item) => item.code === "payment-recharge-products").path).toBe(
|
|
"/payment/recharge-products",
|
|
);
|
|
});
|
|
|
|
test("places splash screens after banners when backend menu is stale", () => {
|
|
const backendMenus = [
|
|
{
|
|
children: [
|
|
{ code: "app-config-h5", id: "app-config-h5", label: "H5配置", path: "/app-config/h5" },
|
|
{
|
|
code: "app-config-banners",
|
|
id: "app-config-banners",
|
|
label: "BANNER配置",
|
|
path: "/app-config/banners",
|
|
},
|
|
{
|
|
code: "app-config-explore",
|
|
id: "app-config-explore",
|
|
label: "Explore配置",
|
|
path: "/app-config/explore",
|
|
},
|
|
{
|
|
code: "app-config-popups",
|
|
id: "app-config-popups",
|
|
label: "弹窗配置",
|
|
path: "/app-config/popups",
|
|
},
|
|
{
|
|
code: "app-config-versions",
|
|
id: "app-config-versions",
|
|
label: "版本管理",
|
|
path: "/app-config/versions",
|
|
},
|
|
],
|
|
code: "app-config",
|
|
icon: "settings",
|
|
id: "app-config",
|
|
label: "APP配置",
|
|
},
|
|
];
|
|
const fallbackMenus = filterNavigationByPermission(fallbackNavigation, (code) => code === "app-config:view");
|
|
const merged = mergeNavigationItems(mapBackendMenus(backendMenus), fallbackMenus);
|
|
const appConfig = merged.find((item) => item.code === "app-config");
|
|
|
|
expect(appConfig.children.map((item) => item.code)).toEqual([
|
|
"app-config-h5",
|
|
"app-config-banners",
|
|
"app-config-splash-screens",
|
|
"app-config-popups",
|
|
"app-config-explore",
|
|
"app-config-versions",
|
|
]);
|
|
});
|
|
});
|
|
|
|
function flattenCodes(items) {
|
|
return items.flatMap((item) => [item.code, ...flattenCodes(item.children || [])]);
|
|
}
|