131 行
4.8 KiB
TypeScript
131 行
4.8 KiB
TypeScript
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<string>();
|
|
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" }],
|
|
});
|
|
});
|