Skip to content

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:

  1. Generate/Update OpenAPI Schema: See OpenAPI Schema Generation Guide
  2. Install Required Dependencies: openapi-typescript, msw, @vitest/ui (see package.json)
  3. 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 OpenAPIDataStore methods if new endpoints were added
  • Update MSW handlers in openapi-handlers.ts for 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:

  1. Type Safety: All mock data conforms to the actual API types
  2. Schema Synchronization: When the API changes, our mocks stay up-to-date
  3. No Database Cruft: Tests use in-memory data that resets between runs
  4. 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:

  1. Reads the latest openapi.json
  2. Generates new TypeScript types
  3. 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

  1. Update OpenAPI Schema: Add new endpoint to openapi.json
  2. Regenerate Types: Run npm run generate-api-types
  3. Update Data Store: Add methods to OpenAPIDataStore
  4. 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-types after 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 store
  • src/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.