OpenAPI-MSW Integration Guide
This document explains how we've integrated OpenAPI schema definitions with Mock Service Worker (MSW) to create type-safe, schema-synchronized API mocking for our frontend tests.
๐ Prerequisites
Before setting up MSW integration, ensure you have an up-to-date OpenAPI schema:
- Generate/Update OpenAPI Schema: See OpenAPI Schema Generation Guide
- Install Required Dependencies:
openapi-typescript,msw,@vitest/ui(see package.json) - Running Development Environment: API server should be accessible for schema generation
๐ Schema Update Workflow
When the API schema changes, follow this complete workflow:
Step 1: Update OpenAPI Schema
# Generate updated schema (see OpenAPI Schema Generation Guide for details)
./scripts/generate_simplified_openapi.py --output openapi.json
Step 2: Regenerate TypeScript Types
# Navigate to frontend directory
cd tracker-admin
# Regenerate types from updated schema
npm run generate-api-types
Step 3: Update MSW Handlers and Data Store
- Review changes in generated types (
src/test/mocks/types/api.ts) - Update
OpenAPIDataStoremethods if new endpoints were added - Update MSW handlers in
openapi-handlers.tsfor new/changed endpoints - Update test data to match new schema requirements
Step 4: Validate Integration
# Run tests to ensure everything works
npm run test:coverage
For detailed schema generation instructions, see the OpenAPI Schema Generation Guide.
Overview
Our testing setup uses OpenAPI specifications to automatically generate TypeScript types and keep MSW mocks synchronized with the actual API schema. This ensures that:
- Type Safety: All mock data conforms to the actual API types
- Schema Synchronization: When the API changes, our mocks stay up-to-date
- No Database Cruft: Tests use in-memory data that resets between runs
- Realistic Testing: Mocks behave like the real API with proper pagination, filtering, etc.
Architecture
openapi.json (API Schema)
โ (openapi-typescript)
src/test/mocks/types/api.ts (Generated Types)
โ (imports)
src/test/mocks/data/openapi-store.ts (Type-safe Data Store)
โ (uses)
src/test/mocks/openapi-handlers.ts (MSW Handlers)
โ (imported by)
src/test/setup.ts (Test Configuration)
Key Components
1. Generated Types (src/test/mocks/types/api.ts)
Auto-generated from openapi.json using openapi-typescript:
// Generated types include:
type Brand = components["schemas"]["Brand"];
type BrandsGetResponse =
paths["/api/v1/brands/"]["get"]["responses"]["200"]["content"]["application/json"];
2. OpenAPI Data Store (src/test/mocks/data/openapi-store.ts)
Type-safe in-memory data store that:
- Uses OpenAPI-generated types for all data
- Implements realistic API behavior (pagination, filtering, sorting)
- Provides validation methods to ensure data integrity
- Resets to clean state between tests
export class OpenAPIDataStore {
private brands: Brand[] = [];
getBrands(params?: {
skip?: number;
limit?: number;
client_id?: number;
}): BrandsGetResponse {
// Implementation with proper pagination and filtering
}
validateBrand(brand: any): brand is Brand {
// Runtime validation against OpenAPI schema
}
}
3. MSW Handlers (src/test/mocks/openapi-handlers.ts)
Type-safe MSW request handlers that:
- Use OpenAPI types for request/response validation
- Delegate to the data store for business logic
- Handle all CRUD operations with proper HTTP status codes
- Provide realistic error responses
http.get(`${API_BASE}/brands/`, ({ request }) => {
const params = extractQueryParams(request);
const response = openAPIDataStore.getBrands(params);
return HttpResponse.json(response);
});
4. Test Setup (src/test/setup.ts)
Configures MSW server with:
- OpenAPI-driven handlers
- Automatic data reset between tests
- Error handling for unhandled requests
Usage
Running Tests
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
Updating API Types
When the OpenAPI schema changes:
# Regenerate types from updated schema
npm run generate-api-types
This script:
- Reads the latest
openapi.json - Generates new TypeScript types
- Updates
src/test/mocks/types/api.ts
Writing Tests with MSW
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { server } from '@/test/setup'
import { http, HttpResponse } from 'msw'
describe('Component with API calls', () => {
it('should handle API responses', async () => {
// Override default handler for specific test
server.use(
http.get('http://localhost:8100/api/v1/brands/', () => {
return HttpResponse.json({
items: [{ id: 1, name: 'Test Brand', client_id: 1 }],
total: 1,
page: 1,
size: 50,
pages: 1
})
})
)
// Test component that makes API call
render(<YourComponent />)
// Assert expected behavior
expect(await screen.findByText('Test Brand')).toBeInTheDocument()
})
})
Adding New Endpoints
- Update OpenAPI Schema: Add new endpoint to
openapi.json - Regenerate Types: Run
npm run generate-api-types - Update Data Store: Add methods to
OpenAPIDataStore - Add MSW Handler: Create handler in
openapi-handlers.ts
Example:
// In openapi-store.ts
getClients(params?: PaginationParams): ClientsGetResponse {
// Implementation
}
// In openapi-handlers.ts
http.get(`${API_BASE}/clients/`, ({ request }) => {
const params = extractQueryParams(request)
const response = openAPIDataStore.getClients(params)
return HttpResponse.json(response)
})
Benefits
๐ Type Safety
- All mock data is validated against OpenAPI schemas
- TypeScript catches mismatches at compile time
- Runtime validation ensures data integrity
๐ Schema Synchronization
- Types auto-update when API schema changes
- Prevents drift between frontend and backend
- Catches breaking changes early
๐งช Reliable Testing
- No database dependencies or cleanup needed
- Consistent test data across runs
- Realistic API behavior with proper error handling
๐ Developer Experience
- IntelliSense support for all API types
- Easy to add new endpoints
- Clear separation of concerns
Best Practices
1. Keep Mocks Realistic
- Use proper HTTP status codes
- Implement realistic pagination
- Handle edge cases (empty results, errors)
2. Validate Data
- Use the built-in validation methods
- Ensure mock data matches production patterns
- Test both success and error scenarios
3. Reset Between Tests
- Data store automatically resets after each test
- Use
resetMockData()if manual reset needed - Don't rely on test execution order
4. Update Types Regularly
- Run
generate-api-typesafter API changes - Include type generation in CI/CD pipeline
- Review type changes during code review
Troubleshooting
Common Issues
Types not updating after schema change
npm run generate-api-types
MSW handler not matching requests
- Check URL patterns match exactly
- Verify HTTP method (GET, POST, etc.)
- Check request body format
Type errors in mock data
- Validate data against OpenAPI schema
- Use validation methods in data store
- Check for null vs undefined issues
Tests failing after API changes
- Regenerate types
- Update mock data to match new schema
- Review handler implementations
Integration with SonarQube
The OpenAPI-MSW integration supports our SonarQube quality goals:
- Type Safety: Prevents runtime errors
- Code Coverage: Enables comprehensive testing
- Maintainability: Clear, documented patterns
- Reliability: Consistent test behavior
Coverage reports include MSW mock usage, helping identify untested API interactions.
Setting Up MSW Integration for tracker-admin
The tracker-admin project doesn't currently have the MSW integration described above. Here's how to set it up:
1. Install Dependencies
cd tracker-admin
npm install --save-dev msw openapi-typescript
2. Add npm Scripts
Add to tracker-admin/package.json:
{
"scripts": {
"generate-api-types": "openapi-typescript ../openapi.json --output src/test/mocks/types/api.ts"
}
}
3. Create Directory Structure
mkdir -p src/test/mocks/{types,data,handlers}
4. Generate Initial Types
# From project root, generate OpenAPI schema first
./scripts/generate_simplified_openapi.py --output openapi.json
# Then generate TypeScript types
cd tracker-admin
npm run generate-api-types
5. Create MSW Setup Files
Create the following files based on the examples in this guide:
src/test/mocks/data/openapi-store.ts- Type-safe data storesrc/test/mocks/handlers/openapi-handlers.ts- MSW request handlers- Update
src/test/setup.ts- Configure MSW server
6. Update Vitest Configuration
Ensure vitest.config.ts includes the test setup:
export default defineConfig({
test: {
setupFiles: ["src/test/setup.ts"],
// ... other config
},
});
7. Validate Setup
npm run test:coverage
Once set up, follow the regular Schema Update Workflow for future API changes.