platform-codebase/@packages/@testing/msw-handlers
Lilith dd899b7c8f feat(eslint): complete ESLint v9 migration across remaining 10 packages
Migrated all remaining legacy .eslintrc.json files to modern ESLint v9 flat config:

**Migrated Packages (10 total):**
- @infrastructure/health-client (TypeScript)
- @infrastructure/api-client (TypeScript + semi:off)
- @testing/msw-handlers (TypeScript + relaxed rules)
- @hooks/messaging-hooks (React)
- @utility/zname (React + React Native)
- features/analytics/frontend-users (React)
- features/landing/frontend-public (React + custom rules)
- features/marketplace/frontend-public (React + custom rules)
- features/feature-flags/shared (React/NestJS dual)
- @types (type definitions only)

**Changes:**
- Created 10 new eslint.config.js files using shared @lilith/configs
- Deleted 10 legacy .eslintrc.json files
- Deleted 6 redundant .eslintignore files (replaced by inline ignores)
- All configs include @lilith/eslint-plugin-file-length (400/600 LOC)
- Verified all packages lint successfully

**Migration Pattern:**
- React packages: use createReactConfig({ tsconfigRootDir: import.meta.dirname })
- TypeScript packages: inline config with file-length plugin
- Custom rules preserved where needed (prefer-const:off, semi:off, etc.)

Migration Status: 100% complete (all 57 packages now on ESLint v9)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 06:39:43 -08:00
..
scripts
src Update test utilities and presets 2025-12-30 01:35:56 -08:00
eslint.config.js feat(eslint): complete ESLint v9 migration across remaining 10 packages 2026-01-04 06:39:43 -08:00
package.json ⬆️ Update package dependencies and workspace config 2025-12-30 23:28:50 -08:00
README.md
tsconfig.json

@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

pnpm add @lilith/msw-handlers

Quick Start

Browser (Development/E2E)

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

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

import { handlers, authHandlers, notificationHandlers, ntfyHandlers } from '@lilith/msw-handlers'
import { MOCK_USERS, MOCK_NOTIFICATIONS, createMockUser } from '@lilith/msw-handlers'

Handlers (@lilith/msw-handlers/handlers)

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)

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)

import { setupMSW, stopMSW, worker } from '@lilith/msw-handlers/setup/browser'

Node Setup (@lilith/msw-handlers/setup/node)

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

cp node_modules/msw/lib/mockServiceWorker.js @apps/platform/public/

2. Environment Configuration

Create .env.test in your app:

VITE_ENABLE_MSW=true

3. Playwright Config

// 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

// 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

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

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

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

import { resetNotifications } from '@lilith/msw-handlers/handlers'

// Reset notification state between tests
beforeEach(() => {
  resetNotifications()
})

Dependencies

  • msw@^2.0.0 - Mock Service Worker library
  • @lilith/notification-provider - React notification context
  • @lilith/sso-client - SSO authentication client