test(auth): 锁住"已在 /login 时 401 不再重载"的回归(登录页死循环)
CI / Backend (go vet + test) (push) Waiting to run
CI / Frontend (lint + build + test) (push) Waiting to run

补一条前端单测:处于 /login 且无 refreshToken 时发起鉴权请求 → 401 →
不得重新赋值 window.location.href。

背景:redirectToLogin 曾对已在 /login 的情况也赋值 href='/login',
赋同值同样触发整页重载 → App 重新挂载 → LicenseProvider 再请求 →
再 401 → 再重载,形成死循环(线上 10 分钟 1566 次 401、登录页闪屏)。

vitest: 4 个用例全绿。
This commit is contained in:
opsx committed 2026-11-03 03:26:45 +00:00
1 parent f91078f814
commit 0ebb2b86bd
1 file changed
+16
+16
View File
@@ -70,4 +70,20 @@ describe('http 401 单飞刷新', () => {
await expect(http.get('/x', { silent: true })).rejects.toThrow()
expect(vi.mocked(fetch).mock.calls.filter(([u]) => String(u).includes('/auth/refresh'))).toHaveLength(0)
})
// 回归:登录页死循环。曾经 redirectToLogin 在已处于 /login 时仍赋值
// location.href='/login' —— 赋同值同样会整页重载,重载后 LicenseProvider
// 再次请求鉴权接口 → 401 → 再重载,用户看到的是登录页一直转圈+闪屏
// (线上实测 10 分钟 1566 次 401)。这里锁住"在 /login 上不再导航"的行为。
it('已在 /login 时 401 不再重载页面', async () => {
const loginLocation = { href: 'http://localhost/login', pathname: '/login', search: '' }
Object.defineProperty(window, 'location', { value: loginLocation, writable: true, configurable: true })
const state = { access: null as string | null, refresh: null as string | null }
const { http } = await freshHttp(state)
vi.mocked(fetch).mockImplementation(async () => jsonResponse({ code: 401, message: 'unauthorized' }, 401))
await expect(http.get('/system/license')).rejects.toThrow()
// 关键断言:href 没有被重新赋值(保持原值,不触发重载)
expect(loginLocation.href).toBe('http://localhost/login')
})
})