268 lines
7.3 KiB
TypeScript
268 lines
7.3 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { setActivePinia, createPinia } from 'pinia'
|
|
|
|
// Mock 导航加载状态
|
|
vi.mock('@/composables/useNavigationLoading', () => {
|
|
const mockStart = vi.fn()
|
|
const mockEnd = vi.fn()
|
|
return {
|
|
useNavigationLoadingState: () => ({
|
|
startNavigation: mockStart,
|
|
endNavigation: mockEnd,
|
|
isLoading: { value: false },
|
|
}),
|
|
useNavigationLoading: () => ({
|
|
startNavigation: mockStart,
|
|
endNavigation: mockEnd,
|
|
isLoading: { value: false },
|
|
}),
|
|
}
|
|
})
|
|
|
|
// Mock 路由预加载
|
|
vi.mock('@/composables/useRoutePrefetch', () => ({
|
|
useRoutePrefetch: () => ({
|
|
triggerPrefetch: vi.fn(),
|
|
cancelPendingPrefetch: vi.fn(),
|
|
resetPrefetchState: vi.fn(),
|
|
}),
|
|
}))
|
|
|
|
// Mock API 相关模块
|
|
vi.mock('@/api', () => ({
|
|
authAPI: {
|
|
getCurrentUser: vi.fn().mockResolvedValue({ data: {} }),
|
|
logout: vi.fn(),
|
|
},
|
|
isTotp2FARequired: () => false,
|
|
}))
|
|
|
|
vi.mock('@/api/admin/system', () => ({
|
|
checkUpdates: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/api/auth', () => ({
|
|
getPublicSettings: vi.fn(),
|
|
}))
|
|
|
|
|
|
// 用于测试的 auth 状态
|
|
interface MockAuthState {
|
|
isAuthenticated: boolean
|
|
isAdmin: boolean
|
|
isSimpleMode: boolean
|
|
}
|
|
|
|
/**
|
|
* 将 router/index.ts 中 beforeEach 守卫的核心逻辑提取为可测试的函数
|
|
*/
|
|
function simulateGuard(
|
|
toPath: string,
|
|
toMeta: Record<string, any>,
|
|
authState: MockAuthState
|
|
): string | null {
|
|
const requiresAuth = toMeta.requiresAuth !== false
|
|
const requiresAdmin = toMeta.requiresAdmin === true
|
|
|
|
// 不需要认证的路由
|
|
if (!requiresAuth) {
|
|
if (
|
|
authState.isAuthenticated &&
|
|
(toPath === '/login' || toPath === '/register')
|
|
) {
|
|
return authState.isAdmin ? '/admin/dashboard' : '/dashboard'
|
|
}
|
|
return null // 允许通过
|
|
}
|
|
|
|
// 需要认证但未登录
|
|
if (!authState.isAuthenticated) {
|
|
return '/login'
|
|
}
|
|
|
|
// 需要管理员但不是管理员
|
|
if (requiresAdmin && !authState.isAdmin) {
|
|
return '/dashboard'
|
|
}
|
|
|
|
// 简易模式限制
|
|
if (authState.isSimpleMode) {
|
|
const restrictedPaths = [
|
|
'/admin/groups',
|
|
'/admin/subscriptions',
|
|
'/admin/redeem',
|
|
'/subscriptions',
|
|
'/redeem',
|
|
]
|
|
if (restrictedPaths.some((path) => toPath.startsWith(path))) {
|
|
return authState.isAdmin ? '/admin/dashboard' : '/dashboard'
|
|
}
|
|
}
|
|
|
|
return null // 允许通过
|
|
}
|
|
|
|
describe('路由守卫逻辑', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia())
|
|
})
|
|
|
|
// --- 未认证用户 ---
|
|
|
|
describe('未认证用户', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: false,
|
|
isAdmin: false,
|
|
isSimpleMode: false,
|
|
}
|
|
|
|
it('访问需要认证的页面重定向到 /login', () => {
|
|
const redirect = simulateGuard('/dashboard', {}, authState)
|
|
expect(redirect).toBe('/login')
|
|
})
|
|
|
|
it('访问管理页面重定向到 /login', () => {
|
|
const redirect = simulateGuard('/admin/dashboard', { requiresAdmin: true }, authState)
|
|
expect(redirect).toBe('/login')
|
|
})
|
|
|
|
it('访问公开页面允许通过', () => {
|
|
const redirect = simulateGuard('/login', { requiresAuth: false }, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
|
|
it('访问 /home 公开页面允许通过', () => {
|
|
const redirect = simulateGuard('/home', { requiresAuth: false }, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
})
|
|
|
|
// --- 已认证普通用户 ---
|
|
|
|
describe('已认证普通用户', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: false,
|
|
isSimpleMode: false,
|
|
}
|
|
|
|
it('访问 /login 重定向到 /dashboard', () => {
|
|
const redirect = simulateGuard('/login', { requiresAuth: false }, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
|
|
it('访问 /register 重定向到 /dashboard', () => {
|
|
const redirect = simulateGuard('/register', { requiresAuth: false }, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
|
|
it('访问 /dashboard 允许通过', () => {
|
|
const redirect = simulateGuard('/dashboard', {}, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
|
|
it('访问管理页面被拒绝,重定向到 /dashboard', () => {
|
|
const redirect = simulateGuard('/admin/dashboard', { requiresAdmin: true }, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
|
|
it('访问 /admin/users 被拒绝', () => {
|
|
const redirect = simulateGuard('/admin/users', { requiresAdmin: true }, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
})
|
|
|
|
// --- 已认证管理员 ---
|
|
|
|
describe('已认证管理员', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: true,
|
|
isSimpleMode: false,
|
|
}
|
|
|
|
it('访问 /login 重定向到 /admin/dashboard', () => {
|
|
const redirect = simulateGuard('/login', { requiresAuth: false }, authState)
|
|
expect(redirect).toBe('/admin/dashboard')
|
|
})
|
|
|
|
it('访问管理页面允许通过', () => {
|
|
const redirect = simulateGuard('/admin/dashboard', { requiresAdmin: true }, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
|
|
it('访问用户页面允许通过', () => {
|
|
const redirect = simulateGuard('/dashboard', {}, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
})
|
|
|
|
// --- 简易模式 ---
|
|
|
|
describe('简易模式受限路由', () => {
|
|
it('普通用户简易模式访问 /subscriptions 重定向到 /dashboard', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: false,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard('/subscriptions', {}, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
|
|
it('普通用户简易模式访问 /redeem 重定向到 /dashboard', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: false,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard('/redeem', {}, authState)
|
|
expect(redirect).toBe('/dashboard')
|
|
})
|
|
|
|
it('管理员简易模式访问 /admin/groups 重定向到 /admin/dashboard', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: true,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard('/admin/groups', { requiresAdmin: true }, authState)
|
|
expect(redirect).toBe('/admin/dashboard')
|
|
})
|
|
|
|
it('管理员简易模式访问 /admin/subscriptions 重定向', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: true,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard(
|
|
'/admin/subscriptions',
|
|
{ requiresAdmin: true },
|
|
authState
|
|
)
|
|
expect(redirect).toBe('/admin/dashboard')
|
|
})
|
|
|
|
it('简易模式下非受限页面正常访问', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: false,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard('/dashboard', {}, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
|
|
it('简易模式下 /keys 正常访问', () => {
|
|
const authState: MockAuthState = {
|
|
isAuthenticated: true,
|
|
isAdmin: false,
|
|
isSimpleMode: true,
|
|
}
|
|
const redirect = simulateGuard('/keys', {}, authState)
|
|
expect(redirect).toBeNull()
|
|
})
|
|
})
|
|
})
|