From harness-claude
Intercepts HTTP requests in tests using Mock Service Worker (MSW) handlers at the network level. Useful for mocking API responses, simulating errors or delays, and sharing mocks between tests and development.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:test-msw-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Intercept HTTP requests in tests using Mock Service Worker handlers at the network level
Intercept HTTP requests in tests using Mock Service Worker handlers at the network level
npm install -D msw
// test/mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/users', () => {
return HttpResponse.json([
{ id: '1', name: 'Alice', email: '[email protected]' },
{ id: '2', name: 'Bob', email: '[email protected]' },
]);
}),
http.get('/api/users/:id', ({ params }) => {
return HttpResponse.json({
id: params.id,
name: 'Alice',
email: '[email protected]',
});
}),
http.post('/api/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ id: 'new-id', ...body }, { status: 201 });
}),
];
// test/mocks/server.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
// test/setup.ts
import { server } from './mocks/server';
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
import { http, HttpResponse } from 'msw';
import { server } from './mocks/server';
it('shows error state when API fails', async () => {
server.use(
http.get('/api/users', () => {
return HttpResponse.json(
{ message: 'Internal server error' },
{ status: 500 },
);
}),
);
render(<UserList />);
expect(await screen.findByText('Failed to load users')).toBeInTheDocument();
});
import { delay, http, HttpResponse } from 'msw';
server.use(
http.get('/api/users', async () => {
await delay(2000);
return HttpResponse.json([]);
})
);
http.post('/api/users', async ({ request, params, cookies }) => {
const body = await request.json();
const authHeader = request.headers.get('Authorization');
if (!authHeader) {
return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
return HttpResponse.json({ id: 'new', ...body }, { status: 201 });
}),
it('sends correct headers', async () => {
let capturedHeaders: Headers;
server.use(
http.get('/api/users', ({ request }) => {
capturedHeaders = request.headers;
return HttpResponse.json([]);
})
);
await fetchUsers();
expect(capturedHeaders!.get('Accept')).toBe('application/json');
});
MSW intercepts requests at the network level, below fetch and XMLHttpRequest. This means your application code is completely unmodified — no dependency injection, no mock modules, no test-specific code paths.
MSW v2 (current): Uses standard Request/Response objects from the Fetch API. Handlers use http.get(), http.post(), etc. Response construction uses HttpResponse.json(), HttpResponse.text(), etc.
onUnhandledRequest: 'error': Causes tests to fail if the code makes an HTTP request that no handler matches. This catches missing mocks and unintended API calls.
Handler precedence: Handlers added with server.use() (per-test overrides) take priority over handlers passed to setupServer() (defaults). server.resetHandlers() removes per-test overrides, restoring defaults.
Browser vs Node: MSW has two modes:
setupServer() — for Node.js test environments (Vitest, Jest)setupWorker() — for browser environments (development server, Storybook)Same handlers work in both modes.
Trade-offs:
onUnhandledRequest: 'error' catches missing mocks — but requires handlers for every request, including static assets in browser modenpx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeMocks APIs with MSW for testing Umbraco backoffice extensions, enabling error handling, loading states, and edge cases without a running Umbraco instance.
Provides Vitest testing patterns with MSW for API mocking and typed mocks for dependency injection. Includes snapshot testing and spy utilities for TypeScript projects.
Tests Next.js App Router components, Server Actions, and Route Handlers using Jest, Vitest, and MSW. Covers mocking next/navigation, next/headers, and direct handler invocation.