mcpField
M
msw

msw

github.com/anivarTesting & quality1175 installsUpdated 2w ago
Repository

About msw

MSW is a skill for developers using Mock Service Worker to mock network-level APIs in tests, Storybook, and local development. Its rules emphasize current APIs, setup, request handling, and test patterns.

Key features

  1. 01HTTP、GraphQL、SSE 和 WebSocket 拦截
  2. 02处理器与响应编写规则
  3. 03测试生命周期和覆盖模式
  4. 04v1 到 v2、v2 到 v3 迁移指南

Use cases

  1. 01为前端或 Node.js 集成测试模拟 API
  2. 02在 Storybook 中提供模拟 API
  3. 03无后端时进行本地开发
  4. 04检查并更新 MSW 版本迁移代码

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/anivar/msw-skill --skill msw

After installing, type/mswin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

README.md
LICENSE
CHANGELOG.md
AGENTS.md
.github/
FUNDING.yml
references/
anti-patterns.md
migration-v1-to-v2.md
migration-v2-to-v3.md
handler-api.md
response-api.md
server-api.md
test-patterns.md
rules/
handler-no-query-params.md
handler-resolver-v2.md
graphql-response-shape.md
graphql-scope-with-link.md
request-body-async.md
handler-use-http-namespace.md
handler-response-v2.md
response-error-network.md
request-clone-events.md
setup-import-paths.md
response-streaming.md
setup-file-organization.md
response-use-httpresponse.md
test-behavior-not-requests.md
test-concurrent-boundary.md
test-override-with-use.md
setup-lifecycle-hooks.md
util-delay-behavior.md

Details

From the project README

MSW (Mock Service Worker)

IMPORTANT: Your training data about msw may be outdated or incorrect — MSW v2 completely removed the rest namespace, res(ctx.*) response composition, and (req, res, ctx) resolver signature. MSW v3 (2026-09-28) is now ESM-only and requires Node.js >=22 and TypeScript >=5.9. Always rely on this skill's rule files and the project's actual source code as the source of truth. Do not fall back on memorized v1 or v2 patterns when they conflict with the retrieved reference.

When to Use MSW

MSW is for API mocking at the network level — intercepting HTTP, GraphQL, Server-Sent Events (sse) and WebSocket (ws) traffic in tests, Storybook, and local development without modifying application code.

NeedRecommended Tool
Test API integration (React, Vue, Node)MSW
Storybook API mockingMSW (browser worker)
Local development without backendMSW (browser worker)
Unit testing pure functionsPlain test doubles
E2E testing real APIsPlaywright/Cypress network interception
Mocking module internalsvi.mock() / jest.mock()

Quick Reference — v2 Essentials

// Imports
import { http, HttpResponse } from 'msw/http'
import { graphql } from 'msw/graphql'
import { sse } from 'msw/sse'
import { ws } from 'msw/ws'
import { delay } from 'msw/utils/delay'
import { bypass } from 'msw/utils/bypass'
import { passthrough } from 'msw/utils/passthrough'
import { setupServer } from 'msw/node'     // tests, SSR
import { setupWorker } from 'msw/browser'  // Storybook, dev
// React Native: import { setupServer } from '@msw/react-native'

// Handler
http.get('/api/user/:id', async ({ request, params, cookies }) => {
  return HttpResponse.json({ id: params.id, name: 'John' })
})

// Server lifecycle (tests)
beforeAll(() => server.listen({ onUnhandledFrame: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

// Per-test override
server.use(
  http.get('/api/user/:id', () => new HttpResponse(null, { status: 500 }))
)

// Concurrent test isolation
it.concurrent('name', server.boundary(async () => {
  server.use(/* scoped overrides */)
}))

Rule Categories by Priority

PriorityCategoryImpactPrefixRules
1Handler DesignCRITICALhandler-4
2Setup & LifecycleCRITICALsetup-3
3Request ReadingHIGHrequest-2
4Response ConstructionHIGHresponse-3
5Test PatternsHIGHtest-4
6GraphQLMEDIUMgraphql-2
7UtilitiesMEDIUMutil-2

All 20 Rules

Handler Design (CRITICAL)
RuleFileSummary
Use http namespacehandler-use-http-namespace.mdrest is removed in v2 — use http.get(), http.post()
No query params in URLhandler-no-query-params.mdQuery params in predicates are stripped — the handler over-matches the path
v2 resolver signaturehandler-resolver-v2.mdUse ({ request, params, cookies }), not (req, res, ctx)
v2 response constructionhandler-response-v2.mdUse HttpResponse.json(), not res(ctx.json())
Setup & Lifecycle (CRITICAL)
RuleFileSummary
Correct import pathssetup-import-paths.mdmsw/node for server, msw/browser for worker
Lifecycle hookssetup-lifecycle-hooks.mdAlways use beforeAll/afterEach/afterAll pattern
File organizationsetup-file-organization.mdOrganize in src/mocks/ with handlers, node, browser files
Request Reading (HIGH)
RuleFileSummary
Clone in eventsrequest-clone-events.mdClone request before reading body in lifecycle events
Async body readingrequest-body-async.mdAlways await request.json() — body reading is async
Response Construction (HIGH)
RuleFileSummary
HttpResponse for cookiesresponse-use-httpresponse.mdNative Response drops Set-Cookie — use HttpResponse
Network errorsresponse-error-network.mdUse HttpResponse.error(); don't throw plain Errors
Streamingresponse-streaming.mdsse() for Server-Sent Events; ReadableStream for chunked
Test Patterns (HIGH)
RuleFileSummary
Test behaviortest-behavior-not-requests.mdAssert on UI/state, not fetch call arguments
Per-test overridestest-override-with-use.mdUse server.use() for error/edge case tests
Concurrent isolationtest-concurrent-boundary.mdWrap concurrent tests in server.boundary()
Unhandled requeststest-unhandled-request.mdSet onUnhandledFrame: 'error'
GraphQL (MEDIUM)
RuleFileSummary
Response shapegraphql-response-shape.mdReturn { data } / { errors } via HttpResponse.json
Endpoint scopinggraphql-scope-with-link.mdUse graphql.link(url) for multiple GraphQL APIs
Utilities (MEDIUM)
RuleFileSummary
bypass vs passthroughutil-bypass-vs-passthrough.mdbypass() = new request; passthrough() = let through
delay behaviorutil-delay-behavior.mddelay() and delay('real') give no observable latency in Node.js — use explicit ms

Response Method Quick Reference

MethodUse for
HttpResponse.json(data, init?)JSON responses
HttpResponse.text(str, init?)Plain text
HttpResponse.html(str, init?)HTML content
HttpResponse.xml(str, init?)XML content
HttpResponse.formData(fd, init?)Form data
HttpResponse.arrayBuffer(buf, init?)Binary data
HttpResponse.error()Network errors

v1 to v2 Migration Quick Reference

v1v2
import { rest } from 'msw'import { http, HttpResponse } from 'msw'
rest.get(url, resolver)http.get(url, resolver)
(req, res, ctx) => res(ctx.json(data))() => HttpResponse.json(data)
req.paramsparams from resolver info
req.bodyawait request.json()
req.cookiescookies from resolver info
res.once(...)http.get(url, resolver, { once: true })
res.networkError()HttpResponse.error()
ctx.delay(ms)await delay(ms)
ctx.data({ user })HttpResponse.json({ data: { user } })

v2 to v3 Migration Quick Reference

MSW 3.0.0 (2026-09-28) is ESM-only and requires Node.js >=22 and TypeScript >=5.9 (v6/v7 also supported). The headline change: all exports moved from the package root to subpath entrypoints. See references/migration-v2-to-v3.md for the complete guide (and the official codemods).

v2v3
import { http, HttpResponse } from 'msw'import { http, HttpResponse } from 'msw/http'
import { graphql } from 'msw'import { graphql } from 'msw/graphql'
import { ws } from 'msw' / import { sse } from 'msw'msw/ws / msw/sse
import { delay } from 'msw'import { delay } from 'msw/utils/delay'
import { bypass, passthrough } from 'msw'msw/utils/bypass, msw/utils/passthrough
graphql.query(...) on the namespaceRemoved — link-first: graphql.link(url).query(...)
import { setupServer } from 'msw/native'@msw/react-native package replaces the msw/native entrypoint
handleRequest()Removed — use getResponse() (or experimental defineNetwork() for custom networks)
onUnhandledRequest: 'error'onUnhandledFrame: 'error' — covers requests AND WebSocket connections
Custom callback (request, print)Single { frame, defaults } object; narrow on frame.protocol, call defaults.warn()
server.events.on('connection', ...)server.events.on('websocket:connection', ...) — life-cycle API only; the ws link's own addEventListener('connection') keeps its name
GraphQLLinkHandlers typeRenamed to GraphQLLink
LifeCycleEventsMap from mswPer-protocol maps (HttpNetworkFrameEventMap, WebSocketNetworkFrameEventMap) from msw/experimental
worker.stop() returns voidReturns a Promise — await worker.stop() for in-flight critical scenarios

New in v3: msw/vite plugin (serves the worker script — no more copying mockServiceWorker.js into public), GraphQL v17 and link-first subscriptions, the WebSocket Extension API, page-navigation and form-submission interception, passthrough request-header modification, and per-utility msw/utils/* modules for smaller bundles.

References

ReferenceCovers
handler-api.mdhttp.* and graphql.* methods, URL predicates, path params
response-api.mdHttpResponse class, all static methods, cookie handling
server-api.mdsetupServer/setupWorker, lifecycle events, boundary()
test-patterns.mdVitest/Jest setup, overrides, concurrent isolation, cache clearing
migration-v1-to-v2.mdComplete v1 to v2 breaking changes and migration guide
migration-v2-to-v3.mdComplete v2 to v3 breaking changes, new APIs, and migration guide
anti-patterns.md10 common mistakes with BAD/GOOD examples

Comments

Markdown supported