SEC_Warehouse/tests/unit/utils/auth.spec.ts

94 lines
3.1 KiB
TypeScript
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, 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)
})
})