Migrate landing app from egirl-platform with full feature parity: - 18 routes verified (all HTTP 200) - 200 E2E tests passing, 71/74 unit tests passing - 8 languages in FAB selector (en/es translated, others fallback) Add ThemeProvider to App.tsx for styled-components theme context. Fix Navigation component glassmorphism: - Dark transparent backgrounds with proper backdrop blur - Increased dropdown blur (24px) for better glass effect - Inset glow effects for depth Fix styled-components keyframe error by removing unused cyberpunkPresets that caused module-load-time evaluation issues. Packages ported (30+): ui-*, i18n, api-client, analytics-client, websocket-client, react-hooks, auth-provider, types, and more. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
233 lines
5.3 KiB
Markdown
233 lines
5.3 KiB
Markdown
# @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
|