🐥
react-route-dom v6を使ってリダイレクトテストしたらひっかかった[createReactRouter使ってみよう]
はじめに
// App.tsx
function App() {
return (
<Routes>
<Route path="hoge" element={<Hoge />} />
<Route path="piyo" element={<Piyo />} />
</Routes>
);
}
export default App;
// Hoge.tsx
export const Hoge = () => {
let isPiyo: boolean = false;
if(isPiyo) return <Navigate to="/piyo" />;
return <>isHoge</>
}
このようなコードでisPiyo
がtrueの場合、リダイレクトするかテストしたいときにどのようにすればよいでしょうか。
環境
"react": "^18.1.0"
"react-router-dom": "6.4.4"
"jest": "29.3.1"
"jest-environment-jsdom": "29.3.1"
結論
createMemoryRouter使ったらできた!
const router = createMemoryRouter(
[
{
path: "/hoge",
element: <Hoge />,
},
],
{ initialEntries: ["/hoge"] }
);
describe("Hoge.tsx", () => {
test("isPiyoがtrueの場合、Piyo.tsxにリダイレクトされる", async() => {
render(<RouterProvider router={router} />);
await waitFor(() => {
expect(router.state.location.pathname).toEqual("/piyo");
});
});
})
解説
ブラウザの履歴を使用する代わりに、メモリルーターはメモリ内の履歴スタックを独自に管理します。主にテストやStorybookのようなコンポーネント開発ツールに有用ですが、ブラウザ以外の環境でReact Routerを動作させる場合にも使用できます。
リダイレクトの処理を行う場合、本来はブラウザでリダイレクトの履歴が保持されます。
Jestなどのテスト環境でNodeやjsdom環境で行うことになるケースがあり、その場合ルーティング履歴を手動で作成することができる機能のようです。
https://reactrouter.com/en/main/routers/create-browser-router#routes
const router = createMemoryRouter(
[
{
path: "/hoge",
element: <Hoge />,
},
],
{ initialEntries: ["/hoge"] }
);
export declare function createMemoryRouter(routes: {
path?: string, // "/"
element?: string, // <Root />
loader?: LoaderFunction // rootLoader
children?: [
{
path?: string, // "events/:id",
element?: string, // <Event />,
loader?: LoaderFunction // eventLoader
},
],
}[],
opts?: {
basename?: string;
hydrationData?: HydrationState;
initialEntries?: InitialEntry[];
initialIndex?: number;
}): RemixRouter;
第一引数routesに配列でルーティング情報を渡します。routesを指定してあげることでRouterPrivider
はpathとelementを紐付けることができます。
第二引数はoptionalなので適宜追加でOKです。
initialEntries
は最初の状態で履歴に残したいルーティングを指定します。今回は/hoge
にアクセスした時の挙動を確かめたいので、initialEntries
には/hoge
を指定します。
initialEntries
は複数指定することもできて、その場合は配列の最後がスタート位置になります。
createMemoryRouter(routes, {
initialEntries: ["/hoge", "/"], // この場合は"/"からスタートする
});
今回は使ってないですが、initialIndex
でスタート位置を指定することもできます。
createMemoryRouter(routes, {
initialEntries: ["/hoge", "/"], // この場合は"/hoge"からスタートする
initialIndex: 0
});
おわりに🐥
参考になったら幸いです!
Discussion