@playwright-backend-mocks/node
v0.1.3
Published
Node.js interception agent for Playwright Backend Mocks
Readme
@playwright-backend-mocks/node
Node.js interception agent for Playwright Backend Mocks — one startup call so Playwright can mock outbound HTTP (and globalThis.WebSocket) from your real app process.
Documentation · Getting started · Node API · GitHub
Run the real app. Mock only the outside world.
Good e2e tests cover your UI and your server — then fake Stripe, email, and every other third party at the boundary. Playwright can do the browser half. This library makes the server half just as easy.
Your UI and server stay real. Tests use backendMocks.route() for the outbound HTTP your Node process makes — the calls that never show up in the browser Network tab.
test("declined card shows an error", async ({ page, backendMocks }) => {
await backendMocks.route("https://api.stripe.com/**", async (route) => {
await route.fulfill({
status: 402,
json: { error: "card_declined" },
});
});
await page.goto("/checkout");
await page.getByRole("button", { name: "Pay" }).click();
await expect(page.getByText("Your card was declined")).toBeVisible();
});Role in the system
This package runs inside your Node app. Call startBackendMocks() once at startup. Under the hood it uses @mswjs/interceptors to pause outbound HTTP (and globalThis.WebSocket), then asks the proxy what to do. You configure mocks in Playwright — no test-only branches, wrappers, or dependency-injection seams in application code.
| Process | Package | Responsibility |
| --- | --- | --- |
| Playwright worker | @playwright-backend-mocks/playwright | backendMocks.route(), matching, settle |
| Proxy coordinator | @playwright-backend-mocks/proxy | Claims, decisions, history, REST |
| Node app | @playwright-backend-mocks/node | Installs interceptors, applies proxy decisions |
When no proxy URL is set, the agent is a no-op — safe to leave in normal app startup.
Install
npm install -D @playwright-backend-mocks/node \
@playwright-backend-mocks/playwright \
@playwright-backend-mocks/proxyKeep the @playwright-backend-mocks/* packages on the same version.
Enable the agent
import { startBackendMocks } from "@playwright-backend-mocks/node";
if (process.env.PLAYWRIGHT_BACKEND_MOCKS_PROXY_URL !== undefined) {
await startBackendMocks({
proxyUrl: process.env.PLAYWRIGHT_BACKEND_MOCKS_PROXY_URL,
clientId: "api-server",
});
}
// The rest of your app is unchanged — keep using fetch, http, axios, etc.Because interception happens at the lowest level through @mswjs/interceptors, this works with virtually every Node HTTP client and the frameworks and SDKs built on top of them.
How it works
- Start a proxy — a small local process between your Node app and Playwright.
- Route Node HTTP through it — this package catches outbound
fetch/http/https(and WebSocket) calls. - Control it from Playwright —
backendMocks.route(...)handlers decide fulfill / continue / abort.
When your app makes an outbound call:
@mswjs/interceptorspauses the request inside the Node process.- This agent forwards it to the proxy.
- The proxy matches it against the owning test’s
backendMocks.route()handlers. - The Playwright handler settles with
fulfill,continue, orabort. - The decision returns to the app as a mocked or real response.
Unmatched requests pass through to the real network.
Related packages
| Package | Role |
| --- | --- |
| @playwright-backend-mocks/playwright | Playwright backendMocks fixture |
| @playwright-backend-mocks/proxy | Coordinator + REST history API |
| @playwright-backend-mocks/dashboard | Optional read-only traffic UI |
| @playwright-backend-mocks/protocol | Shared wire types (usually a transitive dependency) |
License
MIT
