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