React Router v7のルートモジュールコンポーネントをテストする
loader/actionを使わない場合
Section titled “loader/actionを使わない場合”createRoutesStub でモック用のルーターを作ってテストをする。
import { createRoutesStub } from "react-router";import { Sidebar } from ".";import { render } from "@testing-library/react";
const Stub = createRoutesStub([ { path: "/orgs/:orgId", Component: Sidebar, },]);const { container } = render(<Stub initialEntries={["/orgs/test-org"]} />);expect(container.childNodes).toMatchSnapshot();loader/actionが必要な場合
Section titled “loader/actionが必要な場合”ここではルートモジュールのコンポーネントで loader や action が必要な場合を説明する。loader と action それ自体のテストはReact Router v7でルートモジュールのloaderやactionをテストするに書いた。
createRoutesStub に渡す routes 引数は、v7.1.1 時点では以下の定義となっており、loaderData などといった Route.LoaderArgs プロパティを渡せない。
Component?: React.ComponentType | null;この問題はcreateRoutesStub fails type checkingで挙がっているけれど、今の時点では回避策として useLoaderData フックを使うといいらしい。
import Merchants, { loader } from "./merchants.js";import { createRoutesStub, useLoaderData } from "react-router";import { render, waitFor } from "@testing-library/react";
const Stub = createRoutesStub([ { path: "/orgs/:orgId/merchants", HydrateFallback: () => null, Component: (): JSX.Element => { const loaderData = useLoaderData<typeof loader>(); // @ts-expect-error return <Merchants loaderData={loaderData} />; }, loader(): Awaited<ReturnType<typeof loader>> { return { ... }; }, },]);const { container, getByText } = render( <Stub initialEntries={["/orgs/test-org/merchants"]} />,);await waitFor(() => { expect(getByText("Shop1")).toBeVisible(); expect(container).toMatchSnapshot();});Vitestで toBeVisible などのDOMマッチャーが使えない場合はVitestで@testing-libraryのDOMマッチャーを使うを参考に設定する。