問題
React × Jestで、ページ遷移時に入力元の値が遷移先の入力欄に正しく入っていることをテストしたい。
解決方法
MemoryRouter と Routes を使い、render の対象に「遷移元」と「遷移先」両方のパスを含めてルーティング環境を再現する。
test.tsx
import SourcePage from "../SourcePage";
import DestinationPage from "../DestinationPage";
// 省略
test("ボタンを押すとページ遷移し、入力値が遷移先のテキストボックスに反映されること", async () => {
// 1. SourcePageをMemoryRouterでレンダリング(ルーティングのテスト用)
// MemoryRouterは、React Routerが提供する「メモリ上で履歴(history)を管理するルーター」
// テストやStorybookなど、実際のブラウザ環境を使わない場面でルーティング(ページ遷移)の動作を再現したいときに使う
// ブラウザのアドレスバー(URL)は変わらないが、React Routerのルーティング機能はそのまま使える
render(
// MemoryRouter + Routesでルーティング環境を作成
// 初期パスをinitialEntriesで/sourceに設定し、SourcePageを表示、/destinationにDestinationPageが表示される設定
<MemoryRouter initialEntries={["/source"]}>
<Routes>
<Route path="/source" element={<SourcePage user={mockDummyUser} />} />
<Route path="/destination" element={<DestinationPage user={mockDummyUser} />} />
</Routes>
</MemoryRouter>
);
const itemElements = await screen.findAllByTestId("item-name");
expect(itemElements[0]).toHaveTextContent("itemA");
expect(itemElements[1]).toHaveTextContent("itemB");
const moveButtons = screen.getAllByRole("button", { name: /Move/i });
expect(moveButtons[0]).toBeInTheDocument();
// 2. Moveボタンをクリック
await userEvent.click(moveButtons[0]);
// URLが、/destination に変わっていることは確認できない
// Jest + React Testing Library + MemoryRouterの環境では、window.location.pathname は実際のブラウザのように自動で書き換わらない
// MemoryRouterは内部で履歴管理をしているため、window.location には反映されない
// expect(window.location.pathname).toBe("/destination"); // NG
// 3. テキストボックスに「itemA」が入力されていることを確認
const input = screen.getByRole("textbox");
expect(input).toHaveValue("itemA");
});
終わりに
意外と難しかったです。
MemoryRouterとRoutesを使ってルーティング全体をテスト内で再現することで、
ページ遷移や値の受け渡しのテストも簡単に書けるようになります。