67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { createPinia, setActivePinia } from 'pinia'
|
|
import { request, ApiError } from './request'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
/** happy-dom 提供的当前页 URL 控制入口(标准 DOM 无此能力) */
|
|
function setPageURL(url: string) {
|
|
;(window as unknown as { happyDOM: { setURL: (u: string) => void } }).happyDOM.setURL(url)
|
|
}
|
|
|
|
/** 构造最小 401 响应;rotate 在响应返回前换发新会话,模拟 OAuth 绑定回跳 */
|
|
function stub401(rotateTo?: string) {
|
|
vi.stubGlobal('fetch', async () => {
|
|
if (rotateTo !== undefined) useAuthStore().setSession(rotateTo, '')
|
|
return {
|
|
ok: false,
|
|
status: 401,
|
|
url: '/api/v1/x',
|
|
json: async () => ({ error: '未认证' }),
|
|
} as unknown as Response
|
|
})
|
|
}
|
|
|
|
let assignSpy: ReturnType<typeof vi.spyOn>
|
|
|
|
beforeEach(() => {
|
|
localStorage.clear()
|
|
setActivePinia(createPinia())
|
|
assignSpy = vi.spyOn(location, 'assign').mockImplementation(() => {})
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals()
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
describe('401 令牌快照', () => {
|
|
it('当前 token 收到 401:登出并带 redirect 跳登录', async () => {
|
|
setPageURL('http://localhost/instances?tab=list')
|
|
useAuthStore().setSession('tokA', '')
|
|
stub401()
|
|
await expect(request('/x')).rejects.toMatchObject({ status: 401, message: '未认证' })
|
|
expect(useAuthStore().token).toBe('')
|
|
expect(assignSpy).toHaveBeenCalledWith(
|
|
`/login?redirect=${encodeURIComponent('/instances?tab=list')}`,
|
|
)
|
|
})
|
|
|
|
it('响应到达前会话已换新:旧 token 的迟到 401 不得清掉新会话', async () => {
|
|
setPageURL('http://localhost/settings')
|
|
useAuthStore().setSession('tokA', '')
|
|
stub401('tokB')
|
|
await expect(request('/x')).rejects.toBeInstanceOf(ApiError)
|
|
expect(useAuthStore().token).toBe('tokB')
|
|
expect(assignSpy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('登录页密码错误的 401:不跳转,错误留在表单内提示', async () => {
|
|
setPageURL('http://localhost/login')
|
|
stub401()
|
|
await expect(request('/auth/login', { method: 'POST', body: {} })).rejects.toMatchObject({
|
|
message: '未认证',
|
|
})
|
|
expect(assignSpy).not.toHaveBeenCalled()
|
|
})
|
|
})
|