import { expect, test } from "@playwright/test"; import { getVisibleManagementItems, getManagementRoutePermissions, isKnownManagementPath, isManagementPath, MANAGEMENT_ROOT_PERMISSIONS, MANAGEMENT_ROUTES, resolveManagementBreadcrumbs, resolveManagementRoute, } from "../../src/features/navigation/managementRoutes"; import { resolvePageMeta } from "../../src/features/navigation/schema"; import { filterRecentVisitsByPermissions, type RecentVisit, } from "../../src/lib/recentVisits"; import { resolveSingleCompanyState } from "../../src/features/company/singleCompany"; const REGISTERED_MANAGEMENT_PATHS = [ "/system/settings", "/people", "/people/stats", "/people/:employeeId", "/organization", "/system/users", "/system/departments", "/system/approval-rules", "/system/workflow-definitions", "/system/expense-standards", "/system/reimbursement-templates", "/system/workspace", "/audit-logs", "/system/master-data", "/system/payment-accounts", "/system/notification-channels", "/system/feature-flags", "/system/announcements", "/system/cutover", "/performance", ]; test("管理路由注册表覆盖路径、父级、权限和聚合入口合同", () => { expect(MANAGEMENT_ROUTES.map((route) => route.path)).toEqual(REGISTERED_MANAGEMENT_PATHS); expect(new Set(MANAGEMENT_ROUTES.map((route) => route.key)).size).toBe(MANAGEMENT_ROUTES.length); const keys = new Set(MANAGEMENT_ROUTES.map((route) => route.key)); const routesByKey = new Map(MANAGEMENT_ROUTES.map((route) => [route.key, route])); for (const route of MANAGEMENT_ROUTES) { expect(route.title.trim()).not.toBe(""); expect(route.anyOf.length).toBeGreaterThan(0); if (route.parentKey) { expect(keys.has(route.parentKey)).toBe(true); } if (route.showOnLanding) { expect(route.group).not.toBeNull(); expect(route.icon.trim()).not.toBe(""); expect(route.description.trim()).not.toBe(""); } const ancestors = new Set(); let cursor = route; while (cursor.parentKey) { expect(ancestors.has(cursor.key)).toBe(false); ancestors.add(cursor.key); cursor = routesByKey.get(cursor.parentKey)!; } } const expectedRootPermissions = new Set( MANAGEMENT_ROUTES.filter((route) => route.showOnLanding).flatMap((route) => route.anyOf), ); expect(new Set(MANAGEMENT_ROOT_PERMISSIONS)).toEqual(expectedRootPermissions); }); test("企业银行账户与人员档案按当前权限解析管理父链", () => { const paymentPermissions = ["payment.account.read"]; expect(resolveManagementRoute("/system/payment-accounts", paymentPermissions)?.title).toBe("企业银行账户"); expect(isManagementPath("/system/payment-accounts", paymentPermissions)).toBe(true); expect(resolveManagementBreadcrumbs("/system/payment-accounts", paymentPermissions)).toEqual([ { key: "management", title: "管理", href: "/system/settings" }, { key: "payment_accounts", title: "企业银行账户", href: null }, ]); const peoplePermissions = ["system.users"]; expect(getManagementRoutePermissions("employee_profile")).toEqual(peoplePermissions); expect(resolveManagementBreadcrumbs("/people/synthetic-employee", peoplePermissions)).toEqual([ { key: "management", title: "管理", href: "/system/settings" }, { key: "people", title: "人员", href: "/people" }, { key: "employee_profile", title: "员工档案", href: null }, ]); }); test("无权限路径不披露管理标题或面包屑", () => { expect(isKnownManagementPath("/system/payment-accounts")).toBe(true); expect(resolveManagementRoute("/system/payment-accounts", [])).toBeNull(); expect(resolveManagementBreadcrumbs("/system/payment-accounts", [])).toEqual([]); expect(resolvePageMeta("/system/payment-accounts", [])).toEqual({ title: "管理", group: "管理" }); expect(getVisibleManagementItems([])).toEqual([]); }); test("最近访问在权限撤销后移除受限管理标题和链接", () => { const visits: RecentVisit[] = [ { path: "/system/payment-accounts", title: "企业银行账户", visitedAt: "2026-08-03T00:00:00.000Z", }, { path: "/reimbursements", title: "报销", visitedAt: "2026-08-02T00:00:00.000Z", }, ]; expect(filterRecentVisitsByPermissions(visits, ["payment.account.read"])).toEqual(visits); expect(filterRecentVisitsByPermissions(visits, [])).toEqual([visits[1]]); }); test("单公司状态对零个、一个和多个启用公司采用明确且保守的分支", () => { expect(resolveSingleCompanyState([])).toEqual({ kind: "empty" }); expect(resolveSingleCompanyState([{ id: "company-1" }])).toEqual({ kind: "single", company: { id: "company-1" }, }); expect(resolveSingleCompanyState([{ id: "company-1" }, { id: "company-2" }])).toEqual({ kind: "multiple", companies: [{ id: "company-1" }, { id: "company-2" }], }); });