70 lines
3.3 KiB
JavaScript
70 lines
3.3 KiB
JavaScript
import { describe, expect, it } from 'vitest'
|
||
import { createMemoryHistory, createRouter } from 'vue-router'
|
||
import { menuRouteOptions, routes } from '@/router/routes'
|
||
|
||
/**
|
||
* 路由分组(/module)的契约测试。两条分组节点的硬约束:
|
||
*
|
||
* 1. 分组节点必须保持「无 component」:一旦给它配容器组件(内部再放 router-view),
|
||
* 页面会下沉一层、脱离 DefaultLayout 的 keep-alive,缓存静默失效。
|
||
*
|
||
* 2. 分组节点也不配 redirect:分组只是归类,不该自带「默认落地页」语义。
|
||
* 直接访问 /base、/module 这类裸前缀时,交给表尾的 /:pathMatch(.*)* 渲染 404 缺省页
|
||
* —— 业务入口一律由 s_menu + 路由地址维护,避免出现「菜单上没配、却能落在某个页面」
|
||
* 的第二入口。
|
||
*/
|
||
function createTestRouter() {
|
||
return createRouter({ history: createMemoryHistory(), routes })
|
||
}
|
||
|
||
describe('路由分组(嵌套结构)', () => {
|
||
it('分组内子路由解析出完整路径,分组节点不带可渲染组件', async () => {
|
||
const router = createTestRouter()
|
||
await router.push('/module/i18n-type')
|
||
const matched = router.currentRoute.value.matched
|
||
|
||
expect(matched.map((record) => record.path)).toEqual(['/', '/module', '/module/i18n-type'])
|
||
// 分组节点无 components:RouterView 会跳过它,子页仍渲染在 DefaultLayout 的 router-view 上
|
||
expect(matched[1].components).toBeFalsy()
|
||
// meta 由父到子合并,子记录的 componentName 决定 keep-alive 的 include 名
|
||
expect(router.currentRoute.value.meta.componentName).toBe('I18nTypeManagement')
|
||
})
|
||
|
||
it('分组节点既无 component 也无 redirect:只是归类,不自带默认落地页', async () => {
|
||
const router = createTestRouter()
|
||
await router.push('/module/i18n-type')
|
||
const group = router.currentRoute.value.matched[1]
|
||
|
||
expect(group.path).toBe('/module')
|
||
expect(group.components).toBeFalsy()
|
||
expect(group.redirect).toBeFalsy()
|
||
})
|
||
|
||
it('访问分组裸前缀时落入 404 缺省页,不白屏也不落业务页', async () => {
|
||
const router = createTestRouter()
|
||
await router.push('/module')
|
||
|
||
// 分组无 component、无 redirect,裸前缀由表尾 /:pathMatch(.*)* 渲染 404 缺省页;
|
||
// 地址保留原样不重定向,用户能看到自己输错的是什么
|
||
expect(router.currentRoute.value.name).toBe('fallback-404')
|
||
expect(router.currentRoute.value.path).toBe('/module')
|
||
})
|
||
|
||
it('菜单路由选项:排除模块中心(adminOnly)整组与分组节点/动态/通配路由', () => {
|
||
const values = menuRouteOptions.map((option) => option.value)
|
||
|
||
// 模块中心是系统管理员专用页(meta.adminOnly):整组排除,
|
||
// 「菜单管理」的路由下拉配不出第二入口
|
||
expect(values).not.toContain('/module/module-management')
|
||
expect(values).not.toContain('/module/menu-management')
|
||
expect(values).not.toContain('/module/i18n-type')
|
||
expect(values).toContain('/dashboard')
|
||
// 分组节点本身、详情页(:id)、404 通配、登录页与缺省页都不是菜单入口
|
||
expect(values).not.toContain('/module')
|
||
expect(values).not.toContain('/detail/:id')
|
||
expect(values).not.toContain('/login')
|
||
expect(values).not.toContain('/403')
|
||
expect(values).not.toContain('/500')
|
||
})
|
||
})
|