はじめに
こんにちは!POMです。
現在、JISOUの課題でデジタル名刺アプリを開発中なのですが、
vitestでテストを実装している際に表記のエラーが出ましたので、
その解決方法を残します。
問題
今回のアプリではreact-router-domを使ったルーティングをしており、
main.tsxとApp.tsxは下記のようにしていました。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import { Provider } from './components/ui/provider.tsx'
import { BrowserRouter } from 'react-router-dom'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<BrowserRouter>
<Provider>
<App />
</Provider>
</BrowserRouter>
</StrictMode>,
)
import { AppRouter } from './router/AppRouter'
function App() {
return (
<AppRouter />
);
}
export default App
[参考] AppRouter.tsx
AppRouter.tsxのコードも載せておきます。
import { Top } from "../components/pages/Top"
import { CardRegister } from "../components/pages/CardRegister"
import { Cards } from "../components/pages/Cards"
import { Route, Routes } from "react-router-dom"
import { Page404 } from "../components/pages/Page404"
export const AppRouter = () => {
return (
<Routes>
<Route path="/" element={<Top />} />
<Route path="/cards/:id" element={<Cards />} />
<Route path="/cards/register" element={<CardRegister />} />
<Route path="*" element={<Page404 />} />
</Routes>
);
}
ーーー
今回、Top画面に対してのテストを下記のように実装していました。
【修正前】
import { render } from "@/test-utils/render";
import { screen } from "@testing-library/dom";
import { BrowserRouter, } from "react-router-dom";
import { beforeEach, describe, expect, test, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { Top } from "@/components/pages/Top";
const mockNavigate = vi.fn();
vi.mock(import("react-router-dom"), async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
useNavigate: () => mockNavigate,
};
});
const user = userEvent.setup();
describe("Top", () => {
beforeEach(() => {
mockNavigate.mockClear();
render(<Top />);
});
test("タイトルが表示されていること", async () => {
const title = await screen.findByText("デジタル名刺アプリ");
expect(title).toBeInTheDocument();
});
(略)
});
今回はuseNavigateを使ってリンク遷移を行っている部分があり、
下記記事を参考にuseNavigateをモック化してたりもします。
いざ修正前のコードにてテストを動かしたところ、
表記のエラーが出ました。
FAIL src/__tests__/Top.spec.tsx > Top > タイトルが表示されていること
Error: useRoutes() may be used only in the context of a <Router> component.
解決方法
結論、テストファイルについてもmain.tsx同様に
<BrowserRouter>でラップする必要がありました。
【修正後】
import { render } from "@/test-utils/render";
import { screen } from "@testing-library/dom";
import { BrowserRouter, } from "react-router-dom";
import { beforeEach, describe, expect, test, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { Top } from "@/components/pages/Top";
const mockNavigate = vi.fn();
vi.mock(import("react-router-dom"), async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
useNavigate: () => mockNavigate,
};
});
const user = userEvent.setup();
describe("Top", () => {
beforeEach(() => {
mockNavigate.mockClear();
render(
<BrowserRouter>
<Top />
</BrowserRouter>
);
});
test("タイトルが表示されていること", async () => {
const title = await screen.findByText("デジタル名刺アプリ");
expect(title).toBeInTheDocument();
});
(略)
});
おわりに
ちなみに、今回はChakraUI(v3)も使用しているので、
main.tsxで<Provider>でもラップしていますが、
そういった場合のテストでrender()を使用する際の
注意点は下記記事が参考になりました。
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてくださ!
▼▼▼