🐥

react-route-dom v6を使ってリダイレクトテストしたらひっかかった[createReactRouter使ってみよう]

2022/12/27に公開約2,600字

はじめに

// 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使ったらできた!
https://reactrouter.com/en/main/routers/create-memory-router

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");
    });
  });
})

解説

https://reactrouter.com/en/main/routers/create-memory-router

ブラウザの履歴を使用する代わりに、メモリルーターはメモリ内の履歴スタックを独自に管理します。主にテストや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を紐付けることができます。
https://reactrouter.com/en/main/routers/router-provider#routerprovider
第二引数はoptionalなので適宜追加でOKです。
initialEntriesは最初の状態で履歴に残したいルーティングを指定します。今回は/hogeにアクセスした時の挙動を確かめたいので、initialEntriesには/hogeを指定します。
initialEntriesは複数指定することもできて、その場合は配列の最後がスタート位置になります。

createMemoryRouter(routes, {
  initialEntries: ["/hoge", "/"], // この場合は"/"からスタートする
});

今回は使ってないですが、initialIndexでスタート位置を指定することもできます。

createMemoryRouter(routes, {
  initialEntries: ["/hoge", "/"], // この場合は"/hoge"からスタートする
  initialIndex: 0
});

おわりに🐥

参考になったら幸いです!

GitHubで編集を提案

Discussion

ログインするとコメントできます