# Contract Testing Documentation ## Overview This document describes the contract testing strategy for ensuring compatibility between the API (`apps/api`) and the website (`apps/website`) in the GridPilot monorepo. ## Architecture The contract testing system consists of several layers: ### 1. API Contract Validation - **Location**: `apps/api/src/shared/testing/contractValidation.test.ts` - **Purpose**: Validates that API DTOs are consistent and generate valid OpenAPI specs - **Tests**: - OpenAPI spec integrity - DTO consistency - Type generation integrity - Contract compatibility ### 2. Type Generation - **Scripts**: - `npm run api:generate-spec` - Generates OpenAPI spec from DTOs - `npm run api:generate-types` - Generates TypeScript types for website - `npm run api:sync-types` - Runs both in sequence - **Output**: `apps/website/lib/types/generated/` ### 3. Website Contract Consumption - **Location**: `apps/website/lib/types/contractConsumption.test.ts` - **Purpose**: Validates that website can properly consume generated types - **Tests**: - Generated types availability - Type compatibility - Service integration - Error handling ### 4. Compatibility Verification - **Location**: `scripts/contract-compatibility.ts` - **Purpose**: Detects breaking changes between type versions - **Features**: - Backup current types - Generate new types - Compare and detect changes - Report breaking changes ## Workflow ### Local Development ```bash # Run full contract testing suite npm run test:contracts # Or run individual steps: npm run test:api:contracts # Validate API contracts npm run api:generate-spec # Generate OpenAPI spec npm run api:generate-types # Generate types npm run test:contract:compatibility # Check compatibility npm run website:type-check # Verify website types ``` ### CI/CD Pipeline The GitHub Actions workflow (`.github/workflows/contract-testing.yml`) automatically: 1. **On Pull Requests**: - Runs all contract tests - Validates API contracts - Generates types - Checks for breaking changes - Verifies website type checking - Uploads generated types as artifacts - Comments results on PR 2. **On Main Branch Push**: - Runs all tests - Generates and commits updated types ## Breaking Change Detection The system detects several types of changes: ### Breaking Changes (❌ Fails CI) - **Property Removal**: Required properties removed from DTOs - **Type Changes**: Property types changed (e.g., `string` → `number`) - **Required Field Addition**: New required fields added to existing DTOs ### Non-Breaking Changes (⚠️ Warning) - **Property Addition**: Optional properties added - **New DTOs**: New DTO types added - **Documentation Changes**: Description updates ### Removed Changes (❌ Fails CI) - **DTO Removal**: Entire DTO types removed - **Property Removal**: Optional properties removed ## Generated Types Structure The generated types follow this pattern: ```typescript /** * Auto-generated DTO from OpenAPI spec * This file is generated by scripts/generate-api-types.ts * Do not edit manually - regenerate using: npm run api:sync-types */ import type { RelatedDTO } from './RelatedDTO'; export interface MyDTO { id: string; name: string; optionalField?: string; related?: RelatedDTO; } ``` ## Testing Strategy ### API Layer Tests ```typescript // apps/api/src/shared/testing/contractValidation.test.ts describe('API Contract Validation', () => { it('should have valid OpenAPI spec', async () => { // Validates spec structure }); it('should have no circular references', async () => { // Prevents infinite loops }); it('should maintain backward compatibility', async () => { // Ensures critical DTOs exist }); }); ``` ### Website Layer Tests ```typescript // apps/website/lib/types/contractConsumption.test.ts describe('Website Contract Consumption', () => { it('should allow creating valid DTO objects', () => { // Type-safe object creation }); it('should work with service layer patterns', () => { // Integration with services }); it('should handle error cases', () => { // Error handling patterns }); }); ``` ## Integration Points ### Service Layer Integration Services in the website can import and use generated types: ```typescript import type { RequestAvatarGenerationInputDTO } from '@/lib/types/generated/RequestAvatarGenerationInputDTO'; import type { RequestAvatarGenerationOutputDTO } from '@/lib/types/generated/RequestAvatarGenerationOutputDTO'; class AvatarService { async generateAvatar(input: RequestAvatarGenerationInputDTO): Promise { const response = await apiClient.post('/avatar/generate', input); return response.data; // Type-safe } } ``` ### View Model Integration View models can transform DTOs for UI consumption: ```typescript import type { RaceDTO } from '@/lib/types/generated/RaceDTO'; class RaceViewModel { constructor(private dto: RaceDTO) {} get displayDate(): string { return new Date(this.dto.startTime).toLocaleDateString(); } } ``` ## Troubleshooting ### Common Issues 1. **Type Generation Fails** - Check that DTOs have proper `@ApiProperty` decorators - Verify OpenAPI spec is valid JSON - Ensure all referenced types exist 2. **Breaking Changes Detected** - Review the change report - Update website code to handle new types - Consider versioning strategy for major changes 3. **Website Type Errors** - Run `npm run api:sync-types` to regenerate - Check import paths in website code - Verify TypeScript configuration ### Debugging Steps 1. **Check OpenAPI Spec**: ```bash npm run api:generate-spec cat apps/api/openapi.json | jq '.components.schemas' ``` 2. **Compare Generated Types**: ```bash # Backup current types cp -r apps/website/lib/types/generated /tmp/types-backup # Regenerate npm run api:generate-types # Compare diff -r /tmp/types-backup apps/website/lib/types/generated ``` 3. **Run Individual Tests**: ```bash # API tests npm run test:api:contracts # Website type checking npm run website:type-check ``` ## Best Practices ### For API Developers 1. **Always use `@ApiProperty` decorators** with proper types 2. **Mark optional fields explicitly** with `required: false` 3. **Use proper TypeScript types** (avoid `any`) 4. **Add descriptions** to DTO properties 5. **Test DTOs** with contract validation tests ### For Website Developers 1. **Import from generated types**, not manual types 2. **Use type assertions** when consuming API responses 3. **Handle optional fields** properly 4. **Run contract tests** before committing type changes 5. **Update view models** when DTOs change ### For CI/CD 1. **Run contract tests on every PR** 2. **Block merges on breaking changes** 3. **Generate types on main branch pushes** 4. **Upload artifacts for debugging** 5. **Comment results on PRs** ## Future Enhancements - [ ] Add API versioning support - [ ] Generate client SDKs from OpenAPI - [ ] Add contract testing for WebSocket events - [ ] Implement schema registry - [ ] Add automated migration scripts for breaking changes