createTestHarness() は、Node.js エコシステムの既存ツールと一緒に使えます。このページの例は、テスト環境に合わせて応用できる一般的な連携パターンです。
Worker がアウトバウンドの fetch() リクエストを送る場合、Mock Service Worker (MSW) ↗ でインターセプトし、予測可能なレスポンスを返せます。MSW は、テスト間で共有できる再利用可能なリクエストハンドラーを提供します。
たとえば、テストの前に MSW を起動し、未処理のリクエストを拒否し、各テスト後にハンドラーをリセットできます。
import { afterAll, afterEach, beforeAll, test } from "vitest";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
import { createTestHarness } from "wrangler";
const network = setupServer();
const server = createTestHarness({
workers: [{ configPath: "./wrangler.jsonc" }],
});
beforeAll(async () => {
network.listen({ onUnhandledRequest: "error" });
await server.listen();
});
afterEach(async () => {
network.resetHandlers();
await server.reset();
});
afterAll(async () => {
network.close();
await server.close();
});
test("loads a user profile", async ({ expect }) => {
network.use(
http.get("http://identity.example.com/profile/:id", ({ params }) => {
return HttpResponse.json({ id: params.id, name: "Ada" });
}),
);
const worker = server.getWorker();
const response = await worker.fetch("/users/123");
expect(await response.json()).toEqual({ id: "123", name: "Ada" });
});import { afterAll, afterEach, beforeAll, test } from "vitest";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
import { createTestHarness } from "wrangler";
const network = setupServer();
const server = createTestHarness({
workers: [{ configPath: "./wrangler.jsonc" }],
});
beforeAll(async () => {
network.listen({ onUnhandledRequest: "error" });
await server.listen();
});
afterEach(async () => {
network.resetHandlers();
await server.reset();
});
afterAll(async () => {
network.close();
await server.close();
});
test("loads a user profile", async ({ expect }) => {
network.use(
http.get("http://identity.example.com/profile/:id", ({ params }) => {
return HttpResponse.json({ id: params.id, name: "Ada" });
}),
);
const worker = server.getWorker();
const response = await worker.fetch("/users/123");
expect(await response.json()).toEqual({ id: "123", name: "Ada" });
});Web アプリケーションを作っていて、実際のブラウザでユーザーフローを確認したい場合は、テストハーネスと一緒に Playwright ↗ を使います。Playwright はページを開き、ユーザーインターフェイスを操作し、Workers プロジェクトの動作をエンドツーエンドで確認できます。
Playwright のフィクスチャは、ブラウザテストの前に createTestHarness() でテストサーバーを起動できます。アウトバウンドの fetch() リクエストをモックしたい場合は、同時に MSW でインターセプトすることもできます。
次のフィクスチャは Playwright の baseURL を設定し、MSW とテストハーネスをテストへ公開し、各テスト後にストレージ状態をリセットします。
import { test as base, expect } from "@playwright/test";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
import { createTestHarness } from "wrangler";
const test = base.extend({
network: [
async ({}, use) => {
const network = setupServer();
network.listen({ onUnhandledRequest: "error" });
await use(network);
network.close();
},
{ scope: "worker" },
],
server: [
async ({}, use) => {
const server = createTestHarness({
workers: [
{ configPath: "./dist/web_worker/wrangler.json" },
{ configPath: "./dist/api_worker/wrangler.json" },
],
});
await server.listen();
await use(server);
await server.close();
},
{ scope: "worker" },
],
baseURL: async ({ server }, use) => {
const { url } = await server.listen();
await use(url.href);
},
reset: [
async ({ network, server }, use, testInfo) => {
await use();
if (testInfo.status !== testInfo.expectedStatus) {
server.debug();
}
network.resetHandlers();
await server.reset();
},
{ auto: true },
],
});
test("renders a user profile", async ({ page, network }) => {
network.use(
http.get("http://identity.example.com/profile/:id", ({ params }) => {
return HttpResponse.json({ id: params.id, name: "Ada" });
}),
);
await page.goto("/users/123");
await expect(page.getByText("Profile: Ada")).toBeVisible();
});import { test as base, expect } from "@playwright/test";
import { http, HttpResponse } from "msw";
import { setupServer, type SetupServerApi } from "msw/node";
import { createTestHarness, type TestHarness } from "wrangler";
type TestFixtures = {
reset: void;
};
type WorkerFixtures = {
network: SetupServerApi;
server: TestHarness;
};
const test = base.extend<TestFixtures, WorkerFixtures>({
network: [
async ({}, use) => {
const network = setupServer();
network.listen({ onUnhandledRequest: "error" });
await use(network);
network.close();
},
{ scope: "worker" },
],
server: [
async ({}, use) => {
const server = createTestHarness({
workers: [
{ configPath: "./dist/web_worker/wrangler.json" },
{ configPath: "./dist/api_worker/wrangler.json" },
],
});
await server.listen();
await use(server);
await server.close();
},
{ scope: "worker" },
],
baseURL: async ({ server }, use) => {
const { url } = await server.listen();
await use(url.href);
},
reset: [
async ({ network, server }, use, testInfo) => {
await use();
if (testInfo.status !== testInfo.expectedStatus) {
server.debug();
}
network.resetHandlers();
await server.reset();
},
{ auto: true },
],
});
test("renders a user profile", async ({ page, network }) => {
network.use(
http.get("http://identity.example.com/profile/:id", ({ params }) => {
return HttpResponse.json({ id: params.id, name: "Ada" });
}),
);
await page.goto("/users/123");
await expect(page.getByText("Profile: Ada")).toBeVisible();
});