Files
gongxue-base/apps/admin/src/auth/menu-policy.integration.test.ts
2026-07-21 16:04:17 +08:00

106 lines
3.4 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { buildMenu, collectMenuPaths, findRoleAwareLandingPath } from './menu-policy';
const teacherPermissions = [
'teacher-workspace:view',
'schedule:view',
'attendance:view',
'notification:view',
];
const academicPermissions = [
'dashboard:view',
'student:view',
'class:view',
'exam:view',
'teacher:view',
'schedule:view',
'attendance:view',
'classroom:view',
'notification:view',
];
const accommodationPermissions = [
'dashboard:view',
'room:view',
'occupancy:view',
'expense:view',
'bill:view',
'deposit:view',
'notification:view',
];
const systemPermissions = [
'user:view',
'role:view',
'log:view',
'integration:read',
'ai:config:read',
'notification:view',
];
describe('role-aware menu policy', () => {
it('builds a teacher flow without global student or class management', () => {
const menu = buildMenu(['任课老师'], teacherPermissions);
expect(menu.map((item) => item.label)).toEqual(['教学工作', '通知中心']);
expect(collectMenuPaths(menu)).toEqual([
'/teacher-workspace',
'/schedules',
'/attendance',
'/notifications',
]);
expect(findRoleAwareLandingPath(['任课老师'], teacherPermissions)).toBe('/teacher-workspace');
});
it('places schedules and attendance only once in academic management', () => {
const menu = buildMenu(['教务管理员'], academicPermissions);
const paths = collectMenuPaths(menu);
expect(menu.map((item) => item.label)).toEqual(['数据面板', '教务管理', '通知中心']);
expect(paths.filter((path) => path === '/schedules')).toHaveLength(1);
expect(paths.filter((path) => path === '/attendance')).toHaveLength(1);
expect(paths).toContain('/exams');
expect(paths).not.toContain('/teacher-workspace');
});
it('keeps accommodation billing in one business workspace', () => {
const menu = buildMenu(['住宿运营管理员'], accommodationPermissions);
expect(menu.map((item) => item.label)).toEqual(['数据面板', '住宿运营', '通知中心']);
expect(collectMenuPaths(menu)).toEqual([
'/dashboard',
'/room-visual',
'/rooms',
'/occupancies',
'/expenses',
'/bills',
'/deposits',
'/notifications',
]);
});
it('lands system administrators on account management rather than notifications', () => {
expect(findRoleAwareLandingPath(['系统管理员'], systemPermissions)).toBe('/users');
});
it('builds a super-admin menu with unique routes and no teacher workspace', () => {
const allPermissions = [
...academicPermissions,
...accommodationPermissions,
...systemPermissions,
'rental:view',
'organization:view',
];
const menu = buildMenu(['超级管理员'], [...new Set(allPermissions)]);
const paths = collectMenuPaths(menu);
expect(new Set(paths).size).toBe(paths.length);
expect(paths).not.toContain('/teacher-workspace');
expect(paths.filter((path) => path === '/attendance')).toHaveLength(1);
expect(paths.filter((path) => path === '/schedules')).toHaveLength(1);
});
it('deduplicates routes when an account has multiple business roles', () => {
const menu = buildMenu(
['教务管理员', '住宿运营管理员'],
[...academicPermissions, ...accommodationPermissions],
);
const paths = collectMenuPaths(menu);
expect(new Set(paths).size).toBe(paths.length);
});
});