【Next.js, Vitest】テストコード書きたくなったのでVitestに入門する
実装進めてたらついにテストコードがないと不安になったのでVitestで書きます。
テストコードが必要だと思った理由
microCMSの投稿画面にオリジナルボタンを設置したい。
↓
iframe連携をする必要がある
↓
Next.jsでページを作ってiframeで読み込ませる(microCMSの拡張フィールドを使う)
↓
middleware.tsでアクセスを制御
ローカル環境(localhost)とmicrCMSの投稿画面だけアクセスさせたい
↓
これで網羅できとるんか(不安...)
↓
そうだ、テスト、書こう
Vitestとは? Jestデビューするつもりでした
chatGPTにVitestのが良い。と言われたので軽く調べる。
・Jest互換性がある
・jsx、Typescriptに対応
・高速
・Viteなくても使える
とりあえず使ってみる。
セッティング
インストール
npm install -D vitest
scriptsにtestを追加
{
"scripts": {
"test": "vitest"
}
}
※ JSX、import alias(@/)などをテストする場合はvite.config.tsを追加する必要があるっぽい。今回テストするのはmiddleware.tsだけで、サーバーサイドで処理されるので必要なさそう。
試してみる
ファイルの置き場所の指定はないらしいので、
今回はmiddleware.test.tsをmiddleware.tsと同階層に設置。
公式のサンプルコードをコピペ。
middleware.ts
export function sum(a: number, b: number) {
return a + b;
}
middleware.test.ts
import { expect, test } from "vitest";
import { sum } from "./middleware"; // 足し算関数を一次的に書いてます。
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});
で、npm run test...

とりあえず動いたぞ。おもろい。
middleware.ts、どこをテストしたら良い?
テストしたいコードがこちら。
middlreware.tsでアクセス制御。
↓
通常のアクセスは403(閲覧禁止)。
ローカル環境(localhost)とmicrCMSの投稿画面だけ許可。
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function isAllowed(request: NextRequest) {
// ローカルからのアクセスを許可
const { hostname } = request.nextUrl;
const isLocal = hostname.includes("localhost");
// microCMSからのアクセスを許可
const referer = request.headers.get("referer") || "";
const isMicroCMS =
referer.includes("microcms.io") || referer.includes("microcms.app");
return isLocal || isMicroCMS;
}
export function middleware(request: NextRequest) {
if (!isAllowed(request)) {
return new NextResponse("Forbidden", { status: 403 });
}
return NextResponse.next();
}
export const config = {
matcher: ["/custom-field/:path*"],
};
テスト項目
chatGPTにも聞いたので大丈夫だろう。肝心のテストコードは間違ってたけど。
要するにisAllowed()をテストしたい。
-
ローカル開発環境(ホストがlocalhost)からのアクセス
→ 通す⭕️ -
microCMS画面からのアクセス(リファラにmicrocms.ioが含まれている)
→ 通す⭕️ -
この2つ以外
→ 通さない❌
この結果になればおkってことね。
テスト実装
やります。
...。
middleware.tsってどうやってテストするんだ?
神。
書いた。
import { describe, expect, it } from "vitest";
import { isAllowed } from "./middleware";
import { NextRequest } from "next/server";
describe("middlewareのアクセス制御", () => {
it("ローカル環境(localhost)を許可", () => {
const request = new NextRequest(
"http://localhost:3000/custom-field/button"
);
expect(isAllowed(request)).toBe(true);
});
it("refererにmicroCMSが含まれていたら許可", () => {
const request = new NextRequest(
"https://hoge-fuga.microcms.io/apis/testurl/create",
{
headers: {
referer: "microcms.io",
},
}
);
expect(isAllowed(request)).toBe(true);
});
it("それ以外はNG", () => {
const request = new NextRequest("http://hogefugapiyo.com");
expect(isAllowed(request)).toBe(false);
});
});
「動いた!!!!」

無駄なコミットが減りそうなので積極的に書く。
引き続き勉強します。
Discussion