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); }); });