Skip to content
Development
Skill

/web-mocks-msw

MSW handlers, browser/server workers, test data. Use when setting up API mocking for development or testing, creating mock handlers with variants, or sharing mocks between browser and Node environments.

From plugin
agents-inc-skills
24200 skills
Install
$ npx -y skills add agents-inc/skills --skill web-mocks-msw --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/web-mocks-msw

Context preview

The summary Claude sees to decide when to auto-load this skill.

MSW handlers, browser/server workers, test data. Use when setting up API mocking for development or testing, creating mock handlers with variants, or sharing mocks between browser and Node environments.

SKILL.md

web-mocks-msw.SKILL.md
name: web-mocks-msw
description: MSW handlers, browser/server workers, test data. Use when setting up API mocking for development or testing, creating mock handlers with variants, or sharing mocks between browser and Node environments.

MSW Patterns

> **Quick Guide:** MSW intercepts requests at the network layer, so application code never learns it is mocked. One handler set serves both environments — `setupWorker` from `msw/browser` in development, `setupServer` from `msw/node` in tests — and the two are not interchangeable. Keep response bodies in their own module so each variant (default, empty, error) is reusable and typed against your API's generated types.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — mock data modules, variant handlers, server setup and test lifecycle, per-test overrides, runtime variant switching, simulated latency
  • [examples/browser.md](examples/browser.md) — browser worker setup and app integration for client-rendered and server-rendered entry points

---

Which path applies

Handlers are shared; only the setup module and the lifecycle differ.

  • **Browser, during development** — `setupWorker` from `msw/browser`, awaited before the app renders, with runtime variant switching to walk the UI through its states. Follow [examples/browser.md](examples/browser.md).
  • **Node, in tests** — `setupServer` from `msw/node`, listening for the suite and reset between tests, with `server.use()` for one-test overrides. Follow [examples/core.md](examples/core.md).

---

<critical_requirements>

Before writing MSW code

**Match the setup function to the environment.** `setupWorker` needs service worker APIs and `setupServer` patches Node's request layer, so each fails in the other with an error that names a missing global rather than the swap.

**Reset handlers in `afterEach` with `server.resetHandlers()`**, so a `server.use()` override cannot decide the outcome of the next test.

**Await `worker.start()` before rendering.** Requests fired before the worker is ready reach the real network, which makes the first render of a suite intermittently different from the rest.

**Keep response bodies in their own module**, typed against your API's generated types — one fixture then serves several handlers, and a schema change fails at compile time instead of inside an assertion.

</critical_requirements>

---

**Auto-detection:** msw, setupWorker, setupServer, msw/browser, msw/node, http.get, http.all, HttpResponse.json, server.use, resetHandlers, onUnhandledRequest, mockServiceWorker.js, delay()

**Applies to:**

  • Mocking HTTP responses in development before the backend exists
  • Exercising empty, error and slow responses without changing application code
  • Sharing one handler set between a dev server and a test suite
  • Overriding a single endpoint for a single test

**Handled elsewhere:**

  • Test runner configuration and lifecycle hooks — this skill says what goes inside `beforeAll` and `afterEach`, not which runner provides them
  • Rendering components and querying the result
  • Integration against a real backend, where the server's own behaviour is the thing under test

---

<philosophy>

MSW mocks the network, not the code that calls it. Nothing in the application is injected, wrapped or swapped, so what runs in a test is what runs in production — and the same handlers can drive a dev server, a test suite and a demo build.

That only holds while the handler set stays a description of the API rather than of one test's needs. Data lives in fixtures, handlers pick a fixture, and anything a single test needs differently arrives through an override that is thrown away afterwards.

</philosophy>

---

<decision_framework>

Which mechanism for changing a response

| You want | Use | | --------------------------------------- | -------------------------------------------------------- | | A scenario several tests share | A named variant handler exported beside the default | | One test to see something different | `server.use(variant())` — discarded by `resetHandlers()` | | To flip states by hand while developing | A variant map the default handler reads at request time | | A response the code under test waits on | `delay(ms)` with an explicit duration |

Runtime variant switching belongs to development only. In a test it is shared mutable state that survives the test that set it, where `server.use()` is scoped and self-cleaning.

</decision_framework>

---

<patterns>

Core patterns

Pattern 1: Response Bodies in Their Own Module

Fixtures live apart from handlers, typed against the API's generated types, so one body serves several handlers and a schema change surfaces as a type error.

// mocks/features.ts
import type { GetFeaturesResponse } from "./api-types";

export const defaultFeatures: GetFeaturesResponse = {
  features: [{ id: "1", name: "Dark mode", status: "done" }],
};

export const emptyFeatures: GetFeaturesResponse = { features: [] };

Data genuinely specific to one test stays inline in that test.

Full code: [examples/core.md](examples/core.md)

---

Pattern 2: Variant Handlers

Export the default handler and each alternative scenario from one module, so tests and the dev server pick a variant by name.

import { http, HttpResponse } from "msw";

export const getFeaturesHandlers = {
  defaultHandler: () =>
    http.get(ENDPOINT, () => HttpResponse.json(defaultFeatures)),
  emptyHandler: () =>
    http.get(ENDPOINT, () => HttpResponse.json(emptyFeatures)),
  errorHandler: () =>
    http.get(ENDPOINT, () => new HttpResponse("Server error", { status: 500 })),
};

`HttpResponse.json` sets the JSON content type and answers 200 unless `init.status` says otherwise, so only the error variant states a code. A non-JSON body — plain text, an empty error — goes through `new HttpResponse

Read more
Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin

Other skills on agents-inc-skills.