platform-codebase/@packages/@testing/msw-handlers/README.md
2026-01-18 09:20:18 -08:00

233 lines
5.3 KiB
Markdown
Executable file

# @lilith/msw-handlers
Shared MSW (Mock Service Worker) request handlers for platform-wide API mocking.
## Purpose
Provides consistent mock data for:
- **Development** - Frontend work without backend dependencies
- **E2E Tests** - Playwright tests with mocked API responses
- **Unit Tests** - Isolated component testing with predictable data
## Installation
```bash
pnpm add @lilith/msw-handlers
```
## Quick Start
### Browser (Development/E2E)
```ts
// In your app's entry point (main.tsx)
if (import.meta.env.VITE_ENABLE_MSW === 'true') {
const { setupMSW } = await import('@lilith/msw-handlers/setup/browser')
await setupMSW()
}
```
### Node (Unit Tests)
```ts
// In your test setup
import { server } from '@lilith/msw-handlers/setup/node'
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
```
## Exports
### Main Entry (`@lilith/msw-handlers`)
```ts
import { handlers, authHandlers, notificationHandlers, ntfyHandlers } from '@lilith/msw-handlers'
import { MOCK_USERS, MOCK_NOTIFICATIONS, createMockUser } from '@lilith/msw-handlers'
```
### Handlers (`@lilith/msw-handlers/handlers`)
```ts
import {
handlers, // All handlers combined
authHandlers, // Auth endpoints
notificationHandlers, // Notification endpoints
ntfyHandlers, // ntfy push notification endpoints
resetNotifications, // Reset notification state
addMockNotification // Add notification during tests
} from '@lilith/msw-handlers/handlers'
```
### Mock Data (`@lilith/msw-handlers/data`)
```ts
import {
MOCK_USERS, // Pre-defined user fixtures
MOCK_NOTIFICATIONS, // Pre-defined notification fixtures
createMockUser, // Factory function
createMockNotification // Factory function
} from '@lilith/msw-handlers/data'
```
### Browser Setup (`@lilith/msw-handlers/setup/browser`)
```ts
import { setupMSW, stopMSW, worker } from '@lilith/msw-handlers/setup/browser'
```
### Node Setup (`@lilith/msw-handlers/setup/node`)
```ts
import { server } from '@lilith/msw-handlers/setup/node'
```
## Mocked Endpoints
### Auth (`authHandlers`)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `*/auth/me` | GET | Returns authenticated user session |
| `*/auth/login` | POST | User login |
| `*/auth/logout` | POST | User logout |
| `*/auth/register` | POST | User registration |
### Notifications (`notificationHandlers`)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `*/notifications` | GET | List notifications |
| `*/notifications/unread-count` | GET | Get unread count |
| `*/notifications/:id/read` | PATCH | Mark notification as read |
| `*/notifications/:id` | DELETE | Delete notification |
| `*/notifications/read-all` | PATCH | Mark all as read |
### ntfy (`ntfyHandlers`)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `*/notifications/ntfy/topics` | GET | Get subscribed topics |
| `*/notifications/ntfy/subscribe` | POST | Subscribe to ntfy |
| `*/notifications/ntfy/unsubscribe` | DELETE | Unsubscribe |
| `*/notifications/ntfy/active` | PATCH | Heartbeat ping |
## URL Matching
All handlers use wildcard patterns (`*/auth/me`) to match any host. This ensures compatibility across:
- `http://localhost:3100/auth/me`
- `http://api.example.com/auth/me`
- Custom API proxies
## Playwright E2E Integration
### 1. Copy MSW Worker
```bash
cp node_modules/msw/lib/mockServiceWorker.js @apps/platform/public/
```
### 2. Environment Configuration
Create `.env.test` in your app:
```env
VITE_ENABLE_MSW=true
```
### 3. Playwright Config
```ts
// playwright.config.ts
import { defineConfig } from '@playwright/test'
export default defineConfig({
webServer: {
command: 'pnpm dev',
url: 'http://localhost:3100',
reuseExistingServer: !process.env.CI,
env: {
VITE_ENABLE_MSW: 'true',
},
},
})
```
### 4. App Initialization
```ts
// main.tsx
async function bootstrap() {
if (import.meta.env.VITE_ENABLE_MSW === 'true') {
const { setupMSW } = await import('@lilith/msw-handlers/setup/browser')
await setupMSW()
}
const root = ReactDOM.createRoot(document.getElementById('root')!)
root.render(<App />)
}
bootstrap()
```
## Mock Data
### Users
```ts
MOCK_USERS[0] = {
id: 'user-1',
email: 'test@example.com',
name: 'Test User',
displayName: 'Test User',
role: 'user',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}
```
### Notifications
```ts
MOCK_NOTIFICATIONS = [
{ id: 'notif-1', title: 'New Message', type: 'message', read: false },
{ id: 'notif-2', title: 'Booking Confirmed', type: 'booking', read: false },
{ id: 'notif-3', title: 'Payment Received', type: 'payment', read: true },
]
```
## Extending Handlers
### Add Runtime Handlers
```ts
import { worker } from '@lilith/msw-handlers/setup/browser'
import { http, HttpResponse } from 'msw'
// Add handler at runtime
worker.use(
http.get('*/custom/endpoint', () => {
return HttpResponse.json({ custom: 'data' })
})
)
```
### Reset State
```ts
import { resetNotifications } from '@lilith/msw-handlers/handlers'
// Reset notification state between tests
beforeEach(() => {
resetNotifications()
})
```
## Dependencies
- `msw@^2.0.0` - Mock Service Worker library
## Related Packages
- `@lilith/notification-provider` - React notification context
- `@lilith/sso-client` - SSO authentication client