platform-codebase/@packages/@testing/test-utils/src/mocks/msw.ts
2026-01-18 09:20:18 -08:00

118 lines
3.1 KiB
TypeScript
Executable file

/**
* MSW (Mock Service Worker) Utilities
*
* Helper functions for setting up Mock Service Worker in tests.
* MSW intercepts network requests at the network level, providing
* more realistic mocking than vi.mock() or manual fetch mocks.
*/
import { beforeAll, afterEach, afterAll } from 'vitest'
import { http, HttpResponse, type HttpHandler } from 'msw'
import { setupServer, type SetupServer } from 'msw/node'
/**
* Create a generic API fallback handler
* Useful as a default that can be overridden in specific tests
*/
export function createFallbackHandlers(): HttpHandler[] {
return [
http.get('/api/*', () => HttpResponse.json({ message: 'Mock API response' })),
http.post('/api/*', () => HttpResponse.json({ success: true })),
http.put('/api/*', () => HttpResponse.json({ success: true })),
http.patch('/api/*', () => HttpResponse.json({ success: true })),
http.delete('/api/*', () => HttpResponse.json({ success: true })),
]
}
/**
* Create an MSW server with optional custom handlers
*
* @example
* // With fallback handlers
* const server = createMSWServer()
*
* @example
* // With custom handlers
* const server = createMSWServer([
* http.get('/api/users', () => HttpResponse.json({ users: [] }))
* ])
*/
export function createMSWServer(handlers: HttpHandler[] = []): SetupServer {
const defaultHandlers = handlers.length > 0 ? handlers : createFallbackHandlers()
return setupServer(...defaultHandlers)
}
/**
* Setup MSW in test lifecycle (to be used in vitest.setup.ts or describe blocks)
*
* @example
* // In vitest.setup.ts
* import { setupMSW } from '@lilith/test-utils'
* import { server } from './msw-server'
*
* setupMSW(server)
*
* @example
* // In test file
* import { setupMSW, createMSWServer } from '@lilith/test-utils'
*
* const server = createMSWServer()
*
* describe('my feature', () => {
* setupMSW(server)
*
* it('should work', () => {
* // server is active
* })
* })
*/
export function setupMSW(server: SetupServer): void {
// Start server before all tests
beforeAll(() => {
server.listen({ onUnhandledRequest: 'warn' })
})
// Reset handlers after each test
afterEach(() => {
server.resetHandlers()
})
// Stop server after all tests
afterAll(() => {
server.close()
})
}
/**
* Create a success response helper
*/
export function mswSuccess<T = any>(data: T, status = 200): ReturnType<typeof HttpResponse.json> {
return HttpResponse.json(data as any, { status })
}
/**
* Create an error response helper
*/
export function mswError(message: string, status = 400): ReturnType<typeof HttpResponse.json> {
return HttpResponse.json({ error: message }, { status })
}
/**
* Create a delay response helper (for testing loading states)
*/
export function mswDelay<T = any>(
data: T,
delayMs: number,
status = 200
): Promise<ReturnType<typeof HttpResponse.json>> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(HttpResponse.json(data as any, { status }))
}, delayMs)
})
}
// Re-export commonly used MSW utilities
export { http, HttpResponse } from 'msw'
export { setupServer } from 'msw/node'
export type { SetupServer } from 'msw/node'