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