94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||
|
||
// navigation → Taro 只透传最终参数,mock 记录调用
|
||
const mockNavigateTo = vi.hoisted(() => vi.fn())
|
||
const mockReLaunch = vi.hoisted(() => vi.fn())
|
||
const mockRedirectTo = vi.hoisted(() => vi.fn())
|
||
const mockSwitchTab = vi.hoisted(() => vi.fn())
|
||
vi.mock('@tarojs/taro', () => ({
|
||
default: {
|
||
navigateTo: mockNavigateTo,
|
||
reLaunch: mockReLaunch,
|
||
redirectTo: mockRedirectTo,
|
||
switchTab: mockSwitchTab,
|
||
navigateBack: vi.fn()
|
||
}
|
||
}))
|
||
|
||
// store mock:authState 可变,支持模拟已登录/未登录两种状态
|
||
const authState = vi.hoisted(() => ({ token: null as string | null }))
|
||
vi.mock('@/store', () => ({
|
||
store: {
|
||
getState: () => ({ auth: { token: authState.token } })
|
||
}
|
||
}))
|
||
|
||
// storage mock:内存 Map,用于验证 store 未恢复时的兜底读取
|
||
const mem = vi.hoisted(() => new Map<string, unknown>())
|
||
vi.mock('@/utils/storage', () => ({
|
||
storage: {
|
||
get: <T>(key: string): T | null => (mem.has(key) ? (mem.get(key) as T) : null),
|
||
set: <T>(key: string, value: T): void => { mem.set(key, value) },
|
||
remove: (key: string): void => { mem.delete(key) }
|
||
}
|
||
}))
|
||
|
||
import { navigateTo, reLaunch, redirectTo, switchTab } from '@/utils/navigation'
|
||
import { isProtectedPage } from '@/utils/auth'
|
||
import { ROUTES } from '@/constants/routes'
|
||
|
||
beforeEach(() => {
|
||
authState.token = null
|
||
mem.clear()
|
||
mockNavigateTo.mockClear()
|
||
mockReLaunch.mockClear()
|
||
mockRedirectTo.mockClear()
|
||
mockSwitchTab.mockClear()
|
||
})
|
||
|
||
describe('navigation 登录守卫', () => {
|
||
it('未登录 navigateTo 受保护页:url 被改写为登录页', () => {
|
||
navigateTo(ROUTES.FAMILY)
|
||
expect(mockNavigateTo).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
})
|
||
|
||
it('未登录 reLaunch/redirectTo/switchTab 同样被守卫', () => {
|
||
reLaunch(ROUTES.HOME)
|
||
redirectTo(ROUTES.DEVICE_ADD)
|
||
switchTab(ROUTES.EVENT)
|
||
expect(mockReLaunch).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
expect(mockRedirectTo).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
expect(mockSwitchTab).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
})
|
||
|
||
it('已登录 navigateTo:原样放行', () => {
|
||
authState.token = 'tk-1'
|
||
navigateTo(ROUTES.FAMILY)
|
||
expect(mockNavigateTo).toHaveBeenCalledWith({ url: ROUTES.FAMILY })
|
||
})
|
||
|
||
it('未登录访问登录页:放行(登录页在公开名单)', () => {
|
||
navigateTo(ROUTES.LOGIN)
|
||
expect(mockNavigateTo).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
})
|
||
|
||
it('带 query 的受保护页:跳登录页不带残留参数', () => {
|
||
navigateTo(`${ROUTES.FAMILY_DETAIL}?id=3`)
|
||
expect(mockNavigateTo).toHaveBeenCalledWith({ url: ROUTES.LOGIN })
|
||
})
|
||
|
||
it('store 无 token 但 storage 有(冷启动兜底):放行', () => {
|
||
mem.set('auth_token', 'tk-saved')
|
||
navigateTo(ROUTES.HOME)
|
||
expect(mockNavigateTo).toHaveBeenCalledWith({ url: ROUTES.HOME })
|
||
})
|
||
})
|
||
|
||
describe('isProtectedPage', () => {
|
||
it('登录页返回 false,其余页面返回 true', () => {
|
||
expect(isProtectedPage(ROUTES.LOGIN)).toBe(false)
|
||
expect(isProtectedPage(ROUTES.HOME)).toBe(true)
|
||
expect(isProtectedPage(`${ROUTES.LOGIN}?from=xxx`)).toBe(false)
|
||
})
|
||
})
|