feat(management-navigation-single-company-ux): 收敛管理导航与单公司配置体验
这个提交包含在:
@@ -0,0 +1,130 @@
|
||||
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" }],
|
||||
});
|
||||
});
|
||||
在新工单中引用
屏蔽一个用户