Files
workspace/code/fms/fms-vue/tests/router-auth.spec.js
T
2026-09-15 22:10:13 +08:00

109 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useAuthStore } from '@/stores/auth'
import { usePermissionStore } from '@/stores/permissions'
import { createTestPinia } from './helpers/app.js'
import router from '@/router'
// mock 后端数据接口
vi.mock('@/services/api', () => ({
loadDataApi: vi.fn(),
}))
import { loadDataApi } from '@/services/api'
const mockModules = [
{
b_id: '1',
b_code: 'm1',
b_name: 'M1',
b_canuse: 1,
b_canmenu: 1,
b_module_type: 'directory',
b_parent_id: null,
b_icon: '',
b_route: '',
},
]
beforeEach(() => {
localStorage.clear()
sessionStorage.clear()
setActivePinia(createPinia())
loadDataApi.mockReset()
loadDataApi.mockImplementation((view) =>
Promise.resolve({ data: view === 's_module' ? mockModules : [], code: 0, success: true }),
)
// 回到登录页,断开受保护路由状态
return router.push('/login').catch(() => {})
})
afterEach(() => {
if (router.hasRoute('biz')) router.removeRoute('biz')
})
describe('路由守卫 权限加载(三场景)', () => {
it('场景·未登录:访问受保护页 → 重定向 /login?redirect', async () => {
await router.push('/dashboard')
expect(router.currentRoute.value.path).toBe('/login')
expect(router.currentRoute.value.query.redirect).toBe('/dashboard')
})
it('场景·登录:访问受保护页 → 触发 load,菜单数据就绪(同主体不重复请求)', async () => {
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id: 123, account: 'u1', name: 'U' } }, 'ORG')
await router.push('/dashboard')
expect(loadDataApi).toHaveBeenCalled()
expect(usePermissionStore().modules.length).toBe(1)
// 再次进入另一受保护页(同主体)不应重复发请求
loadDataApi.mockClear()
await router.push('/demo')
expect(loadDataApi).not.toHaveBeenCalled()
})
it('场景·登录:访问无权限 moduleId 路由 → 重定向 /dashboard', async () => {
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id: 123, account: 'u1', name: 'U' } }, 'ORG')
router.addRoute({
path: '/biz',
name: 'biz',
component: { render: () => null },
meta: { requiresAuth: true, moduleId: 'm-no' },
})
await router.push('/biz')
expect(router.currentRoute.value.path).toBe('/dashboard')
})
it('场景·刷新已登录态:persist 恢复后守卫 load 成功,无 clear 竞态', async () => {
// 按 pinia-plugin-persistedstate v4 的实际存储格式写入(纯 state JSON,无 {state, version} 包装)
sessionStorage.setItem(
'fms-login',
JSON.stringify({ loginInfo: { token: 't', user: { id: 123, account: 'u1', name: 'U' } } }),
)
localStorage.setItem(
'fms-user',
JSON.stringify({ userInfo: { orgId: 'ORG', account: 'u1' } }),
)
// 用 createTestPinia(内部已 install,persist 插件真实注册),等价于刷新页面
createTestPinia()
const a = useAuthStore() // 首次创建
await a.$hydrate() // 显式从 localStorage 恢复(等价于刷新页面)
expect(useAuthStore().isAuthenticated).toBe(true)
await router.push('/dashboard')
expect(usePermissionStore().modules.length).toBe(1)
})
it('场景·切换账号:旧主体请求作废,新主体重新加载', async () => {
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id: 123, account: 'u1', name: 'U' } }, 'ORG')
await router.push('/dashboard')
expect(usePermissionStore().modules.length).toBe(1)
// 切换到另一账号
auth.setSession({ token: 't2', user: { id: 999, account: 'u2', name: 'U2' } }, 'ORG2')
loadDataApi.mockClear()
await router.push('/demo')
expect(loadDataApi).toHaveBeenCalled() // 新主体重新加载
expect(usePermissionStore().modules.length).toBe(1)
})
})