git:20260202.b236384 to git:20260316.5d5dfc3

82 added, 107 removed. Audit A to A.

---
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.
---
# API Mocking with MSW
- > **Quick Guide:** Centralized mocks in `@repo/api-mocks`. Handlers with variant switching (default, empty, error). Shared between browser (dev) and Node (tests). Type-safe using generated types from `@repo/api/types`.
+ > **Quick Guide:** Handlers with variant switching (default, empty, error). Shared between browser (dev) and Node (tests). Separate mock data from handlers for reusability. Type-safe using your API's generated types. Use `setupWorker` (browser) and `setupServer` (Node) -- never swap them.
**Detailed Resources:**
- - For code examples, see [examples/](examples/) (core, browser, node, testing, advanced)
- - For decision frameworks and anti-patterns, see [reference.md](reference.md)
+ - [examples/core.md](examples/core.md) - Mock data, variant handlers, server worker, per-test overrides, runtime switching, network simulation
+ - [examples/browser.md](examples/browser.md) - Browser worker setup, SPA/SSR integration
+ - [reference.md](reference.md) - Decision frameworks, red flags, anti-patterns
---
<critical_requirements>
## CRITICAL: Before Using This Skill
**(You MUST separate mock data from handlers - handlers in `handlers/`, data in `mocks/`)**
**(You MUST use `setupWorker` for browser/development and `setupServer` for Node/tests - NEVER swap them)**
- **(You MUST reset handlers after each test with `serverWorker.resetHandlers()` in `afterEach`)**
-
- **(You MUST use generated types from `@repo/api/types` - NEVER manually define API response types)**
+ **(You MUST reset handlers after each test with `server.resetHandlers()` in `afterEach`)**
**(You MUST use named constants for HTTP status codes and delays - NO magic numbers)**
</critical_requirements>
---
- **Auto-detection:** MSW setup, mock handlers, mock data, API mocking, testing mocks, development mocks, setupWorker, setupServer
+ **Auto-detection:** MSW, msw, mock handlers, mock data, API mocking, setupWorker, setupServer, http.get, HttpResponse
**When to use:**
- - Setting up MSW for development and testing
- - Creating centralized mock handlers with variant switching
- - Sharing mocks between browser (dev) and Node (tests)
- - Testing different API scenarios (success, empty, error)
- - Simulating network latency and error conditions
+ - Mocking API responses during development before backend is ready
+ - Testing different API scenarios (success, empty, error states)
+ - Sharing the same mock definitions between browser dev and Node test environments
+ - Simulating network conditions (latency, timeouts)
+ - Per-test handler overrides for isolated test scenarios
**When NOT to use:**
- - Integration tests that need real backend validation (use test database instead)
+ - Integration tests needing real backend validation (use a test database)
- Production builds (MSW should never ship to production)
- - Simple unit tests of pure functions (no network calls to mock)
- - When you need to test actual network failure modes (use test containers)
+ - Pure function unit tests with no network calls
+ - Testing actual network failure modes (use test containers)
**Key patterns covered:**
- - Centralized mock package structure with handlers and data separation
+ - Handler/data separation for reusability and type safety
- Variant-based handlers (default, empty, error scenarios)
- Browser worker for development, server worker for tests
- - Per-test handler overrides for specific scenarios
+ - Per-test handler overrides with `server.use()`
- Runtime variant switching for UI development
---
<philosophy>
## Philosophy
- MSW (Mock Service Worker) intercepts network requests at the service worker level, providing realistic API mocking without changing application code. This skill enforces a centralized approach where mocks live in a dedicated package (`@repo/api-mocks`), enabling consistent behavior across development and testing environments.
-
- **When to use MSW:**
-
- - Developing frontend features before backend API is ready
- - Testing different API response scenarios (success, empty, error states)
- - Simulating network conditions (latency, timeouts)
- - Creating a consistent development environment across team
- - End-to-end testing with controlled API responses
-
- **When NOT to use MSW:**
-
- - Integration tests that need real backend validation (use test database)
- - Production builds (MSW should never ship to production)
- - Simple unit tests of pure functions (no network calls)
- - When you need to test actual network failure modes (use test containers)
+ MSW intercepts network requests at the service worker (browser) or class extension (Node) level, providing realistic API mocking without changing application code. Keep mock data separate from handlers for reusability, type handlers against your generated API types, and organize handlers by domain/feature.
</philosophy>
---
<patterns>
## Core Patterns
- ### Pattern 1: Centralized Mock Package Structure
-
- Organize all mocks in a dedicated workspace package with clear separation between handlers (MSW request handlers) and mock data (static response data).
-
- #### Package Structure
-
- ```
- packages/api-mocks/
- ├── src/
- │ ├── handlers/
- │ │ ├── index.ts # Export all handlers
- │ │ └── features/
- │ │ └── get-features.ts # MSW handlers with variants
- │ ├── mocks/
- │ │ ├── index.ts # Export all mock data
- │ │ └── features.ts # Mock data
- │ ├── browser-worker.ts # Browser MSW worker (development)
- │ ├── server-worker.ts # Node.js MSW server (tests)
- │ └── manage-mock-selection.ts # Variant switching logic
- └── package.json
- ```
+ ### Pattern 1: Separate Mock Data from Handlers
- For package configuration examples, see [examples/core.md](examples/core.md#package-configuration).
+ Define mock data as typed constants separate from MSW handlers. This enables type safety from your generated API types and reusability across handlers.
- ---
+ ```typescript
+ // mocks/features.ts
+ import type { GetFeaturesResponse } from "./api-types";
- ### Pattern 2: Separate Mock Data from Handlers
+ export const defaultFeatures: GetFeaturesResponse = {
+ features: [
+ { id: "1", name: "Dark mode", status: "done" },
+ { id: "2", name: "Auth", status: "in progress" },
+ ],
+ };
- Define mock data as typed constants in `mocks/` directory, completely separate from MSW handlers. This enables type safety from generated API types and reusability across handlers.
+ export const emptyFeatures: GetFeaturesResponse = { features: [] };
+ ```
- For code examples, see [examples/core.md](examples/core.md#mock-data-separation).
+ For full variant handler examples, see [examples/core.md](examples/core.md).
**When not to use:** When mock data is truly one-off and specific to a single test case (use inline data in the test instead).
---
- ### Pattern 3: Handlers with Variant Switching
+ ### Pattern 2: Handlers with Variant Switching
Create handlers that support multiple response scenarios (default, empty, error) with runtime switching for development and explicit overrides for testing.
- Key principles:
-
- - Named constants for HTTP status codes
- - Response factories for consistency
- - Variant switching via centralized state
- - Explicit handler exports for per-test overrides
-
- For implementation examples, see [examples/core.md](examples/core.md#variant-handlers).
-
- ---
-
- ### Pattern 4: Browser Worker for Development
+ ```typescript
+ import { http, HttpResponse } from "msw";
- Set up MSW browser worker to intercept requests during development. Key considerations:
+ const API_ENDPOINT = "api/v1/features";
+ const HTTP_STATUS_OK = 200;
+ const HTTP_STATUS_INTERNAL_SERVER_ERROR = 500;
- - Use `setupWorker` from `msw/browser`
- - Await worker start before rendering app
- - Configure `onUnhandledRequest: "bypass"` for unmocked requests
+ export const getFeaturesHandlers = {
+ defaultHandler: () =>
+ http.get(API_ENDPOINT, () =>
+ HttpResponse.json(defaultFeatures, { status: HTTP_STATUS_OK }),
+ ),
+ emptyHandler: () =>
+ http.get(API_ENDPOINT, () =>
+ HttpResponse.json(emptyFeatures, { status: HTTP_STATUS_OK }),
+ ),
+ errorHandler: () =>
+ http.get(
+ API_ENDPOINT,
+ () =>
+ new HttpResponse("Server error", {
+ status: HTTP_STATUS_INTERNAL_SERVER_ERROR,
+ }),
+ ),
+ };
+ ```
- For app integration examples, see [examples/browser.md](examples/browser.md).
+ For full implementation with runtime switching, see [examples/core.md](examples/core.md).
---
- ### Pattern 5: Server Worker for Tests
+ ### Pattern 3: Browser Worker (Development) vs Server Worker (Tests)
- Set up MSW server worker for Node.js test environment:
+ - Use `setupWorker` from `msw/browser` for browser/development
+ - Use `setupServer` from `msw/node` for Node/tests
+ - **Never swap them** -- `setupWorker` needs service worker APIs, `setupServer` needs Node APIs
- - Use `setupServer` from `msw/node`
- - Lifecycle: `beforeAll` listen, `afterEach` reset, `afterAll` close
- - Always reset handlers to prevent test pollution
+ ```typescript
+ // browser-worker.ts
+ import { setupWorker } from "msw/browser";
+ export const browserWorker = setupWorker(...handlers);
- For test setup examples, see [examples/node.md](examples/node.md).
+ // server-worker.ts
+ import { setupServer } from "msw/node";
+ export const server = setupServer(...handlers);
+ ```
- </patterns>
+ For browser app integration (SPA and SSR), see [examples/browser.md](examples/browser.md).
---
- <integration>
-
- ## Integration Guide
-
- **Works with any:**
-
- - **Data fetching solution**: MSW intercepts fetch calls at the network level - your data fetching library sees normal responses
- - **Test runner**: Server worker integrates via test setup file (lifecycle hooks)
- - **Testing utilities**: Works seamlessly with any component testing library
- - **Frontend framework**: Browser worker integrates via app entry point
+ ### Pattern 4: Test Lifecycle
- **Test runner configuration (generic):**
+ Always follow this lifecycle to prevent test pollution:
```typescript
- // test-setup.ts (configure in your test runner)
- import { serverWorker } from "@repo/api-mocks/serverWorker";
-
- // Use your test runner's lifecycle hooks
- beforeAll(() => serverWorker.listen());
- afterEach(() => serverWorker.resetHandlers());
- afterAll(() => serverWorker.close());
+ beforeAll(() => server.listen());
+ afterEach(() => server.resetHandlers());
+ afterAll(() => server.close());
```
- </integration>
+ Use `server.use()` for per-test overrides -- they are automatically cleaned up by `resetHandlers()`.
+ For per-test override examples, see [examples/core.md](examples/core.md).
+
+ </patterns>
+
---
<critical_reminders>
## CRITICAL REMINDERS
**(You MUST separate mock data from handlers - handlers in `handlers/`, data in `mocks/`)**
**(You MUST use `setupWorker` for browser/development and `setupServer` for Node/tests - NEVER swap them)**
- **(You MUST reset handlers after each test with `serverWorker.resetHandlers()` in `afterEach`)**
-
- **(You MUST use generated types from `@repo/api/types` - NEVER manually define API response types)**
+ **(You MUST reset handlers after each test with `server.resetHandlers()` in `afterEach`)**
**(You MUST use named constants for HTTP status codes and delays - NO magic numbers)**
- **Failure to follow these rules will cause test pollution, type drift from real API, environment-specific failures, and hard-to-debug race conditions.**
+ **Failure to follow these rules will cause test pollution, environment-specific failures, and hard-to-debug race conditions.**
</critical_reminders>