Next.js 14 Server Componentのユニットテストについて。
Testing-library
以下を参考にServer Componentのユニットテストを作成します。 ただし、簡単なコンポーネントでしか確認していないので、コンポーネントによってはエラーになるかもしれません。
Server componentのテストでは、Server componentを関数として扱います。 以下の例ではrsc関数がServer Componentになります。
describe("Server Component Test", () => {
test("Sample", async () => {
const { asFragment } = render(await rsc(props));
expect(asFragment()).toMatchSnapshot();
});
});
テストでは Server component の関数にpropsを渡してasync関数として実行し、その結果をrenderに渡すことで、要素テストや
スナップショップテストが行えます。
ただし、テストするServer Componentに子コンポーネントがある場合、子コンポーネントをMock化しないとエラーになる場合があります。 その場合は、jest.mockなどでMockにします。
jest.mock("子コンポーネントのパス", () => ({
子コンポーネント関数名: () => <div>子コンポーネント</div>
}));
describe("Server Component Test", () => {
test("Sample", async () => {
const { asFragment } = render(await rsc(props));
expect(asFragment()).toMatchSnapshot();
});
});
サンプル・パラメータあり
URLクエリ ストリングが必要なServer Componentなページのサンプル。 これはURLクエリ ストリングのkeyに指定された文字列により表示する文字列が変わるページになります。
例 サンプルコンポーネント
注 import 'server-only' を "use server" にしてもテストは正常に実行できます。
import 'server-only'; import fs from "fs/promises"; export default async function FileTextPage(props: { searchParams: { key: string } }) { const { searchParams } = props; const list: Record<string, string> = { "dev": "src/app/sample/rsc/file-text/dev.txt", "stg": "src/app/sample/rsc/file-text/stg.txt", }; const filePath = list[searchParams.key]; let content = "Not exist key"; if (filePath) { const buffer = await fs.readFile(filePath); content = buffer.toString(); } return ( <main className="w-full p-2 flex flex-col items-center"> <div> <h1>サンプル・RSC・ファイルテキスト</h1> </div> <div className="p-4"> <div> <div>テキストファイル</div> <textarea data-testid="text-file-content" className="bg-slate-100" defaultValue={content} readOnly /> </div> </div> <div> <ul> <li><a className="underline" href="../">戻る</a></li> </ul> </div> </main> ) }
例 ユニットテストのサンプル
import FileTextPage from '@/app/sample/rsc/file-text/page'; import { render } from '@testing-library/react'; describe("FileTextPage test", () => { test("Test key dev", async () => { const { asFragment, findByTestId } = render(await FileTextPage({ searchParams: { key: "dev" }})); const element = await findByTestId("text-file-content") as HTMLTextAreaElement; expect(element.defaultValue).toBe("Test dev"); expect(asFragment()).toMatchSnapshot(); }); test("Test key stg", async () => { const { asFragment, findByTestId } = render(await FileTextPage({ searchParams: { key: "stg" }})); const element = await findByTestId("text-file-content") as HTMLTextAreaElement; expect(element.defaultValue).toBe("Test stg"); expect(asFragment()).toMatchSnapshot(); }); });