refactor: 前端登录/权限/界面状态迁移至 zustand
This commit is contained in:
96
apps/admin/src/components/RouteKeeper.integration.test.tsx
Normal file
96
apps/admin/src/components/RouteKeeper.integration.test.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { act } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { MemoryRouter, Route, Routes, useNavigate } from 'react-router-dom';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { RouteKeeper } from './RouteKeeper';
|
||||
|
||||
let container: HTMLDivElement | null = null;
|
||||
let root: ReturnType<typeof createRoot> | null = null;
|
||||
|
||||
afterEach(async () => {
|
||||
if (root) await act(async () => root?.unmount());
|
||||
container?.remove();
|
||||
root = null;
|
||||
container = null;
|
||||
});
|
||||
|
||||
function PageA() {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div>
|
||||
<input data-testid="input-a" aria-label="A 输入" />
|
||||
<button data-testid="go-b" onClick={() => navigate('/b')}>
|
||||
去B
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PageB() {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div>
|
||||
<input data-testid="input-b" aria-label="B 输入" />
|
||||
<button data-testid="go-a" onClick={() => navigate('/')}>
|
||||
去A
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Harness() {
|
||||
return (
|
||||
<MemoryRouter initialEntries={['/']}>
|
||||
<Routes>
|
||||
<Route path="/" element={<RouteKeeper />}>
|
||||
<Route index element={<PageA />} />
|
||||
<Route path="b" element={<PageB />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
);
|
||||
}
|
||||
|
||||
function type(target: HTMLInputElement, value: string) {
|
||||
const setter = Object.getOwnPropertyDescriptor(
|
||||
window.HTMLInputElement.prototype,
|
||||
'value',
|
||||
)?.set;
|
||||
setter?.call(target, value);
|
||||
target.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}
|
||||
|
||||
describe('RouteKeeper', () => {
|
||||
it('keeps page instances and input values alive across navigation', async () => {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
await act(async () => root?.render(<Harness />));
|
||||
|
||||
const inputA = document.querySelector('[data-testid="input-a"]') as HTMLInputElement;
|
||||
expect(inputA).not.toBeNull();
|
||||
await act(async () => type(inputA, '待保存的学生姓名'));
|
||||
|
||||
await act(async () => {
|
||||
(document.querySelector('[data-testid="go-b"]') as HTMLButtonElement).click();
|
||||
});
|
||||
const inputB = document.querySelector('[data-testid="input-b"]') as HTMLInputElement;
|
||||
expect(inputB).not.toBeNull();
|
||||
await act(async () => type(inputB, '待保存的宿舍号'));
|
||||
|
||||
await act(async () => {
|
||||
(document.querySelector('[data-testid="go-a"]') as HTMLButtonElement).click();
|
||||
});
|
||||
|
||||
const keptA = document.querySelector('[data-testid="input-a"]') as HTMLInputElement;
|
||||
expect(keptA).not.toBeNull();
|
||||
expect(keptA.value).toBe('待保存的学生姓名');
|
||||
const keptB = document.querySelector('[data-testid="input-b"]') as HTMLInputElement;
|
||||
expect(keptB.value).toBe('待保存的宿舍号');
|
||||
|
||||
const pages = document.querySelectorAll('.route-keeper-page');
|
||||
expect(pages.length).toBe(2);
|
||||
const hidden = pages[1] as HTMLElement;
|
||||
expect(hidden.style.display).toBe('none');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user