| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import { describe, expect, it } from 'vitest';
- import { readFileSync } from 'node:fs';
- import { resolve } from 'node:path';
- import {
- MOBILE_BUSINESS_REGISTRY,
- buildMenuPathSet,
- canAccessUniPage,
- getAuthorizedBusinessEntries,
- hasButtonPermission,
- } from '@/permissions/mobileMenuRegistry';
- describe('mobile menu permissions', () => {
- const menuTree = [
- {
- id: 1,
- path: '/aidop',
- children: [
- { id: 2, path: '/aidop/flowManage/approvalFlowCenter', title: '审批中心' },
- { id: 3, path: '/aidop/smart-ops/s3', title: 'S3 看板' },
- { id: 4, path: '/aidop/s5/inventory/stock-query', title: '库存查询' },
- ],
- },
- ];
- it('registers every implemented mobile business family', () => {
- expect(MOBILE_BUSINESS_REGISTRY.map((entry) => entry.key)).toEqual([
- 'approval',
- 's8',
- 'kanban-S1',
- 'kanban-S2',
- 'kanban-S3',
- 'kanban-S4',
- 'kanban-S5',
- 'kanban-S6',
- 'kanban-S7',
- 'kanban-S9',
- 'stock',
- 'workorder',
- 'delivery',
- 'fqc',
- ]);
- });
- it('flattens nested loginMenuTree paths and exposes only implemented authorized entries', () => {
- const paths = buildMenuPathSet(menuTree);
- expect(paths.has('/aidop/smart-ops/s3')).toBe(true);
- expect(getAuthorizedBusinessEntries(paths).map((entry) => entry.key)).toEqual([
- 'approval',
- 'kanban-S3',
- 'stock',
- ]);
- });
- it('keeps fixed pages available and fails closed for unloaded or unauthorized business pages', () => {
- const paths = buildMenuPathSet(menuTree);
- expect(canAccessUniPage('/pages/index/index', new Set(), false)).toBe(true);
- expect(canAccessUniPage('/pages/message/index', new Set(), false)).toBe(true);
- expect(canAccessUniPage('/pages/todo/index', paths, true)).toBe(true);
- expect(canAccessUniPage('/pages/approval/detail?taskId=1', paths, true)).toBe(true);
- expect(canAccessUniPage('/pages/s8/dashboard', paths, true)).toBe(false);
- expect(canAccessUniPage('/pages/s8/detail?id=1', paths, true)).toBe(false);
- expect(canAccessUniPage('/pages/query/fqc?id=1', paths, true)).toBe(false);
- expect(canAccessUniPage('/pages/query/stock', paths, false)).toBe(false);
- });
- it('separates S8 dashboard and exception-list permissions', () => {
- const dashboardOnly = buildMenuPathSet([{ id: 1, path: '/aidop/s8/dashboard' }]);
- const exceptionsOnly = buildMenuPathSet([{ id: 2, path: '/aidop/s8/exceptions' }]);
- expect(canAccessUniPage('/pages/s8/dashboard', dashboardOnly, true)).toBe(true);
- expect(canAccessUniPage('/pages/s8/list', dashboardOnly, true)).toBe(false);
- expect(canAccessUniPage('/pages/s8/detail?id=1', exceptionsOnly, true)).toBe(true);
- expect(canAccessUniPage('/pages/s8/dashboard', exceptionsOnly, true)).toBe(false);
- expect(getAuthorizedBusinessEntries(exceptionsOnly).find((entry) => entry.key === 's8')?.uniPage)
- .toBe('/pages/s8/list');
- });
- it('guards kanban deep links by the requested module', () => {
- const paths = buildMenuPathSet(menuTree);
- expect(canAccessUniPage('/pages/kanban/index?module=S3', paths, true)).toBe(true);
- expect(canAccessUniPage('/pages/kanban/index?module=S2', paths, true)).toBe(false);
- expect(canAccessUniPage('/pages/kanban/index', paths, true)).toBe(false);
- });
- it('treats an empty or missing buttons list as no permission', () => {
- expect(hasButtonPermission(undefined, 'sysTenant:changeTenant')).toBe(false);
- expect(hasButtonPermission([], 'sysTenant:changeTenant')).toBe(false);
- expect(hasButtonPermission(['sysTenant:changeTenant'], 'sysTenant:changeTenant')).toBe(true);
- });
- it('keeps a page-level guard on every business page for cold-start deep links', () => {
- const pages = [
- 'todo/index.vue',
- 'approval/detail.vue',
- 's8/dashboard.vue',
- 's8/list.vue',
- 's8/detail.vue',
- 'kanban/index.vue',
- 'query/stock.vue',
- 'query/workorder.vue',
- 'query/delivery.vue',
- 'query/fqc.vue',
- ];
- for (const page of pages) {
- const source = readFileSync(resolve(process.cwd(), 'src/pages', page), 'utf8');
- expect(source, page).toContain('requireMobilePageAccess');
- }
- });
- });
|