Integrations (4)

Last updated Jul 27, 2026 You can use createTestHarness() with existing tools in the Node.js ecosystem. The examples on this page show common integration patterns that you can adapt to your test setup.

Mock Service Worker

If your Worker makes outbound fetch() requests, you can use Mock Service Worker (MSW) ↗︎ to intercept them and return predictable responses. MSW provides reusable request handlers that can be shared across tests.

For example, you can start MSW before the tests, reject unhandled requests, and reset handlers after each test:

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

Playwright

If you are building a web application and want to verify user flows in a real browser, use Playwright ↗︎ with the test harness. Playwright can navigate pages, interact with the user interface, and verify the behavior of your Workers project end to end.

A Playwright fixture can start a test server with createTestHarness() before browser tests. If you want to mock outbound fetch() requests, you can also use MSW to intercept them at the same time.

The following fixture sets the Playwright baseURL, exposes MSW and the test harness to tests, and resets storage state after each test.

tests/playwright.test.jsjs

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

tests/playwright.test.tsts

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

Was this helpful?

YesNo

On this page

Integrations (4) - 图1Docs

{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workers/testing/test-harness/integrations/#page","headline":"Integrations","description":"Use createTestHarness with Mock Service Worker and Playwright.","url":"https://developers.cloudflare.com/workers/testing/test-harness/integrations/","inLanguage":"en","image":"https://developers.cloudflare.com/workers/testing/test-harness/integrations/og.png?v=d180095af1637ae1","dateModified":"2026-07-27","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}


description: Test routes, dispatch events, control Workflows, and assert logged behavior with createTestHarness. title: Interact with Workers image: https://developers.cloudflare.com/workers/testing/test-harness/interact-with-workers/og.png?v=844c9e592ff561a9


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt
Use this file to discover all available pages before exploring further.