Files
workspace/code/g3soft-erp/web/tests/views/module/menu-management/menuRouteOptions.spec.ts
T
2026-10-15 17:31:35 +08:00

74 lines
2.6 KiB
TypeScript

/**
* menuRouteOptions:菜单管理「路由地址」下拉候选。
*
* 关键口径(对照 fms-vue 的 collectMenuRoutes):
* - meta.adminOnly 的超管专用页(模块中心 /module/*)必须整体排除 ——
* 菜单管理自己的入口若落进 s_menu,误删后就没有修复入口了;
* - 403 / 500 兜底页排除;
* - 含动态段(:id)/ 通配(*)的路由不能作为固定菜单入口。
*/
import { describe, expect, it } from 'vitest'
import { collectMenuRoutes, menuRouteOptions } from '@/router/index'
describe('collectMenuRoutes', () => {
it('排除 adminOnly 的模块中心页面', () => {
const paths = menuRouteOptions.map((option) => option.value)
expect(paths).not.toContain('/module/module-management')
expect(paths).not.toContain('/module/menu-management')
expect(paths).not.toContain('/module/i18n-type')
})
it('排除 403 / 500 兜底页', () => {
const paths = menuRouteOptions.map((option) => option.value)
expect(paths).not.toContain('/403')
expect(paths).not.toContain('/500')
})
it('保留普通业务页面,label 同时含路径与标题', () => {
const byValue = new Map(menuRouteOptions.map((option) => [option.value, option.label]))
expect(byValue.get('/dashboard')).toBe('/dashboard(首页)')
expect(byValue.get('/base/contact')).toBe('/base/contact(联系人)')
})
it('按路径排序', () => {
const paths = menuRouteOptions.map((option) => option.value)
const sorted = [...paths].toSorted((a, b) => a.localeCompare(b, 'zh-Hans-CN'))
expect(paths).toEqual(sorted)
})
it('过滤掉动态段与通配路由', () => {
const list = collectMenuRoutes([
{ path: '/ok', meta: { title: '正常' } },
{ path: '/detail/:id', meta: { title: '详情' } },
{ path: '/any/*', meta: { title: '通配' } },
{ path: '/admin', meta: { title: '超管', adminOnly: true } },
] as never)
expect(list.map((option) => option.value)).toEqual(['/ok'])
})
it('含 children 的容器节点只向下递归、自身不作为候选', () => {
const list = collectMenuRoutes([
{
path: '/group',
meta: { title: '分组' },
children: [{ path: 'child', meta: { title: '子页' } }],
},
] as never)
expect(list).toEqual([{ value: '/group/child', label: '/group/child(子页)' }])
})
it('每个候选都是完整绝对路径,且无重复', () => {
const paths = menuRouteOptions.map((option) => option.value)
for (const path of paths) expect(path.startsWith('/')).toBe(true)
expect(new Set(paths).size).toBe(paths.length)
})
})