AppLayout.unauthorized.test.tsx
2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// REQ-USR-004: AppLayout 注册 401 登出处理(壳层接线,BR10)
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { screen, act } from '@testing-library/react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { renderShell } from './renderShell';
import AppLayout from '../../src/layouts/AppLayout/AppLayout';
import {
registerUnauthorizedHandler,
TOKEN_STORAGE_KEY,
} from '../../src/api/request';
import { SESSION_EXPIRED_TEXT } from '../../src/layouts/AppLayout/shellMessages';
import type { AuthUser } from '../../src/api/types';
const ADMIN: AuthUser = { id: 1, sUserName: '朱子纯', sUserType: '超级管理员', sLanguage: '中文' };
function LocProbe() {
const loc = useLocation();
return <div data-testid="loc">{loc.pathname}</div>;
}
describe('AppLayout 401 登出接线', () => {
let captured: (() => void) | null = null;
beforeEach(() => {
captured = null;
});
afterEach(() => {
registerUnauthorizedHandler(null);
vi.restoreAllMocks();
});
it('registers onUnauthorized on mount; invoking it clears auth + warns + navigates /login', async () => {
localStorage.setItem(TOKEN_STORAGE_KEY, 't');
// 拦截真实注册:把回调存进 captured,同时透传给真实单例
const origRegister = registerUnauthorizedHandler;
const restore = vi
.spyOn(await import('../../src/api/request'), 'registerUnauthorizedHandler')
.mockImplementation((fn) => {
if (fn) captured = fn as () => void;
origRegister(fn);
});
const { getState } = renderShell(
<Routes>
<Route element={<AppLayout />}>
<Route path="/" element={<LocProbe />} />
</Route>
<Route path="/login" element={<LocProbe />} />
</Routes>,
{ initialEntries: ['/'], preloadedAuth: { token: 't', user: ADMIN } },
);
expect(captured).toBeTypeOf('function');
await act(async () => {
captured!();
});
expect(getState().auth.token).toBeNull();
expect(localStorage.getItem(TOKEN_STORAGE_KEY)).toBeNull();
expect(await screen.findByText(SESSION_EXPIRED_TEXT)).toBeInTheDocument();
expect(screen.getByTestId('loc').textContent).toBe('/login');
restore.mockRestore();
});
});