はじめに
ReactのテストでLinkの画面遷移テストが上手くいかなかったため、解決方法について共有させていただきます。
バージョン
react v19.0.0
react-router v7.3.0
testing-library/react v16.2.0
jest v29.7.0
エラー内容
遷移できていないようです。
.tarminal
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: "/cards/register"
Number of calls: 0
Ignored nodes: comments, script, style
150 | // 新規名刺登録ページに遷移したことを期待する
151 | await waitFor(() => {
> 152 | expect(mockNavigate).toHaveBeenCalledWith("/cards/register");
| ^
153 | });
コード内容抜粋
.spec.tsx
const mockNavigate = jest.fn();
jest.mock('react-router', () => ({
...jest.requireActual('react-router'), // 元のモジュール内容を展開
useNavigate: () => mockNavigate, // useNavigate だけを上書き
}));
describe("Home Component", () => {
it("新規登録はこちらを押すと/cards/registerに遷移する", async () => {
render(
<BrowserRouter>
<Home />
<Register />
</BrowserRouter>
);
// Loading...が消えるのを待つ
await waitFor(() =>
expect(screen.queryByText("Loading...")).not.toBeInTheDocument()
);
// Linkを取得
const registerLink = screen.getByRole("link", { name: "新規登録はこちら" });
// Link先が正しいことを確認
expect(registerLink).toHaveAttribute('href', '/cards/register');
// リンクをクリック
await userEvent.click(registerLink);
// 新規名刺登録ページに遷移したことを期待する
await waitFor(() => {
expect(mockNavigate).toHaveBeenCalledWith("/cards/register");
});
});
});
解決方法
MemoryRouterを使用する
.spec.tsx
const mockNavigate = jest.fn();
jest.mock('react-router', () => ({
...jest.requireActual('react-router'), // 元のモジュール内容を展開
useNavigate: () => mockNavigate, // useNavigate だけを上書き
}));
describe("Home Component", () => {
it("新規登録はこちらを押すと/cards/registerに遷移する", async () => {
render(
<MemoryRouter initialEntries={['/']}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/cards/register" element={<Register />} />
</Routes>
</MemoryRouter>
)
// Loading...が消えるのを待つ
await waitFor(() =>
expect(screen.queryByText("Loading...")).not.toBeInTheDocument()
);
// Linkを取得
const registerLink = screen.getByRole("link", { name: "新規登録はこちら" });
// Link先が正しいことを確認
expect(registerLink).toHaveAttribute('href', '/cards/register');
// リンクをクリック
await userEvent.click(registerLink);
// 新規名刺登録ページに遷移したことを期待する
await waitFor(() => {
expect(screen.getByTestId('register-page')).toBeInTheDocument();
});
});
});
参考
おわりに
MemoryRouter便利ですね。