# MSW (Mock Service Worker) Setup Guide ## FE-API-019: API Mocking for Development This guide explains how to use MSW (Mock Service Worker) for API mocking during development and testing. ## Overview MSW allows you to intercept and mock HTTP requests at the network level, making it perfect for: - Development without a running backend - Testing with consistent mock data - Simulating error scenarios - Testing offline behavior ## Configuration ### Environment Variable MSW is controlled by the `VITE_USE_MSW` environment variable: ```bash # Enable MSW VITE_USE_MSW=1 npm run dev # Or use the dedicated script npm run dev:mocks # Disable MSW (default) VITE_USE_MSW=0 npm run dev ``` ### Initialization MSW is automatically initialized in `main.tsx` when: - `VITE_USE_MSW` is set to `1` or `true` - Running in development mode (`import.meta.env.DEV`) The worker is started before the React app renders to ensure all requests are intercepted. ## File Structure ``` apps/web/src/mocks/ ├── handlers.ts # Mock request handlers ├── browser.ts # Browser worker setup ├── node.ts # Node.js server setup (for tests) ├── index.ts # Exports └── test-setup.ts # Test configuration ``` ## Adding New Handlers Edit `apps/web/src/mocks/handlers.ts` to add new mock handlers: ```typescript import { http, HttpResponse } from 'msw'; export const handlers = [ // GET request http.get('/api/v1/endpoint', () => { return HttpResponse.json({ data: { /* mock data */ }, }); }), // POST request with body http.post('/api/v1/endpoint', async ({ request }) => { const body = await request.json(); return HttpResponse.json( { data: { /* response */ }, }, { status: 201 }, ); }), // Request with parameters http.get('/api/v1/endpoint/:id', ({ params }) => { const { id } = params; return HttpResponse.json({ data: { id /* ... */ }, }); }), // Request with query parameters http.get('/api/v1/endpoint', ({ request }) => { const url = new URL(request.url); const param = url.searchParams.get('param'); return HttpResponse.json({ data: { param /* ... */ }, }); }), // Error response http.get('/api/v1/error', () => { return HttpResponse.json( { error: 'Something went wrong' }, { status: 500 }, ); }), ]; ``` ## URL Matching **Important**: MSW handlers must match the **full URL path** that the client sends. Since `apiClient` uses `baseURL: env.API_URL` (e.g., `http://127.0.0.1:8080/api/v1`), handlers should match: - ✅ `/api/v1/roles` (matches full path) - ✅ `http://127.0.0.1:8080/api/v1/roles` (matches full URL) - ❌ `/roles` (won't match if baseURL is set) However, MSW can match relative paths if configured correctly. The current setup uses relative paths like `/api/v1/*`. ## Current Handlers The following endpoints are currently mocked: ### Authentication - `POST /api/auth/login` - `POST /api/auth/register` - `POST /api/auth/refresh` - `GET /api/users/profile` - `PUT /api/users/profile` ### Chat - `GET /api/chat/conversations` - `GET /api/chat/conversations/:id/messages` - `POST /api/chat/conversations/:id/messages` ### Library - `GET /api/library/tracks` - `POST /api/library/tracks` ### Health & Errors - `GET /api/health` - `GET /api/error/500` - `GET /api/error/404` - `GET /api/error/timeout` ## Testing with MSW ### In Unit Tests ```typescript import { server } from '@/mocks/test-setup'; import { handlers, errorHandlers } from '@/mocks/handlers'; beforeAll(() => { server.listen(); }); afterEach(() => { server.resetHandlers(); }); afterAll(() => { server.close(); }); // Use error handlers for error scenarios test('handles error', () => { server.use(...errorHandlers); // Test error handling }); ``` ### In E2E Tests ```bash # Run E2E tests with MSW npm run test:e2e:msw ``` ## Best Practices 1. **Keep handlers realistic**: Mock data should match the real API structure 2. **Use variables**: Store mock data in constants for reusability 3. **Handle edge cases**: Add handlers for error scenarios (400, 401, 500, etc.) 4. **Document changes**: Update this guide when adding new handlers 5. **Test both paths**: Test with MSW enabled and disabled ## Troubleshooting ### MSW not intercepting requests 1. Check that `VITE_USE_MSW=1` is set 2. Verify `mockServiceWorker.js` exists in `public/` 3. Check browser console for MSW initialization messages 4. Ensure handlers match the exact URL path ### Handler not matching 1. Check the exact URL being sent (check Network tab) 2. Verify the handler path matches exactly 3. Use `onUnhandledRequest: 'warn'` to see unmatched requests ### Service Worker issues 1. Clear browser cache and service workers 2. Unregister old service workers in DevTools > Application > Service Workers 3. Restart the dev server ## Updating Mock Service Worker If MSW version is updated, regenerate the service worker: ```bash npx msw init public/ --save ``` ## Related Documentation - [MSW Documentation](https://mswjs.io/) - [MSW GitHub](https://github.com/mswjs/msw)