veza/apps/web/src/docs/MSW_SETUP.md

227 lines
5.1 KiB
Markdown
Raw Normal View History

# 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)