# Rating Integration Tests This directory contains integration tests for the GridPilot Rating system, following the clean integration strategy defined in [`plans/clean_integration_strategy.md`](../../plans/clean_integration_strategy.md). ## Testing Philosophy These tests focus on **Use Case orchestration** - verifying that Use Cases correctly interact with their Ports (Repositories, Event Publishers, etc.) using In-Memory adapters for fast, deterministic testing. ### Key Principles 1. **Business Logic Only**: Tests verify business logic orchestration, NOT UI rendering 2. **In-Memory Adapters**: Use In-Memory adapters for speed and determinism 3. **Zero Implementation**: These are placeholders - no actual test logic implemented 4. **Use Case Focus**: Tests verify Use Case interactions with Ports 5. **Orchestration Patterns**: Tests follow Given/When/Then patterns for business logic ## Test Files ### Core Rating Functionality - **[`rating-calculation-use-cases.integration.test.ts`](./rating-calculation-use-cases.integration.test.ts)** - Tests for rating calculation use cases - Covers: `CalculateRatingUseCase`, `UpdateRatingUseCase`, `GetRatingUseCase`, etc. - Focus: Verifies rating calculation logic with In-Memory adapters - **[`rating-persistence-use-cases.integration.test.ts`](./rating-persistence-use-cases.integration.test.ts)** - Tests for rating persistence use cases - Covers: `SaveRatingUseCase`, `GetRatingHistoryUseCase`, `GetRatingTrendUseCase`, etc. - Focus: Verifies rating data persistence and retrieval - **[`rating-leaderboard-use-cases.integration.test.ts`](./rating-leaderboard-use-cases.integration.test.ts)** - Tests for rating-based leaderboard use cases - Covers: `GetRatingLeaderboardUseCase`, `GetRatingPercentileUseCase`, `GetRatingComparisonUseCase`, etc. - Focus: Verifies leaderboard orchestration with In-Memory adapters ### Advanced Rating Functionality - **[`rating-team-contribution-use-cases.integration.test.ts`](./rating-team-contribution-use-cases.integration.test.ts)** - Tests for team contribution rating use cases - Covers: `CalculateTeamContributionUseCase`, `GetTeamRatingUseCase`, `GetTeamContributionBreakdownUseCase`, etc. - Focus: Verifies team rating logic and contribution calculations - **[`rating-consistency-use-cases.integration.test.ts`](./rating-consistency-use-cases.integration.test.ts)** - Tests for consistency rating use cases - Covers: `CalculateConsistencyUseCase`, `GetConsistencyScoreUseCase`, `GetConsistencyTrendUseCase`, etc. - Focus: Verifies consistency calculation logic - **[`rating-reliability-use-cases.integration.test.ts`](./rating-reliability-use-cases.integration.test.ts)** - Tests for reliability rating use cases - Covers: `CalculateReliabilityUseCase`, `GetReliabilityScoreUseCase`, `GetReliabilityTrendUseCase`, etc. - Focus: Verifies reliability calculation logic (attendance, DNFs, DNSs) ## Test Structure Each test file follows the same structure: ```typescript describe('Use Case Orchestration', () => { let repositories: InMemoryAdapters; let useCase: UseCase; let eventPublisher: InMemoryEventPublisher; beforeAll(() => { // Initialize In-Memory repositories and event publisher }); beforeEach(() => { // Clear all In-Memory repositories before each test }); describe('UseCase - Success Path', () => { it('should [expected outcome]', async () => { // TODO: Implement test // Scenario: [description] // Given: [setup] // When: [action] // Then: [expected result] // And: [event emission] }); }); describe('UseCase - Edge Cases', () => { it('should handle [edge case]', async () => { // TODO: Implement test // Scenario: [description] // Given: [setup] // When: [action] // Then: [expected result] // And: [event emission] }); }); describe('UseCase - Error Handling', () => { it('should handle [error case]', async () => { // TODO: Implement test // Scenario: [description] // Given: [setup] // When: [action] // Then: [expected error] // And: [event emission] }); }); describe('UseCase - Data Orchestration', () => { it('should correctly format [data type]', async () => { // TODO: Implement test // Scenario: [description] // Given: [setup] // When: [action] // Then: [expected data format] }); }); }); ``` ## Implementation Guidelines ### When Implementing Tests 1. **Initialize In-Memory Adapters**: ```typescript repository = new InMemoryRatingRepository(); eventPublisher = new InMemoryEventPublisher(); useCase = new UseCase({ repository, eventPublisher }); ``` 2. **Clear Repositories Before Each Test**: ```typescript beforeEach(() => { repository.clear(); eventPublisher.clear(); }); ``` 3. **Test Orchestration**: - Verify Use Case calls the correct repository methods - Verify Use Case publishes correct events - Verify Use Case returns correct data structure - Verify Use Case handles errors appropriately 4. **Test Data Format**: - Verify rating is calculated correctly - Verify rating breakdown is accurate - Verify rating updates are applied correctly - Verify rating history is maintained ### Example Implementation ```typescript it('should calculate rating after race completion', async () => { // Given: A driver with baseline rating const driver = Driver.create({ id: 'd1', iracingId: '100', name: 'John Doe', country: 'US' }); await driverRepository.create(driver); // Given: A completed race with results const race = Race.create({ id: 'r1', leagueId: 'l1', scheduledAt: new Date(Date.now() - 86400000), track: 'Spa', car: 'GT3', status: 'completed' }); await raceRepository.create(race); const result = Result.create({ id: 'res1', raceId: 'r1', driverId: 'd1', position: 1, lapsCompleted: 20, totalTime: 3600, fastestLap: 105, points: 25, incidents: 0, startPosition: 1 }); await resultRepository.create(result); // When: CalculateRatingUseCase.execute() is called const ratingResult = await calculateRatingUseCase.execute({ driverId: 'd1', raceId: 'r1' }); // Then: The rating should be calculated expect(ratingResult.isOk()).toBe(true); const rating = ratingResult.unwrap(); expect(rating.driverId.toString()).toBe('d1'); expect(rating.rating).toBeGreaterThan(0); expect(rating.components).toBeDefined(); expect(rating.components.resultsStrength).toBeGreaterThan(0); expect(rating.components.consistency).toBeGreaterThan(0); expect(rating.components.cleanDriving).toBeGreaterThan(0); expect(rating.components.racecraft).toBeGreaterThan(0); expect(rating.components.reliability).toBeGreaterThan(0); expect(rating.components.teamContribution).toBeGreaterThan(0); // And: EventPublisher should emit RatingCalculatedEvent expect(eventPublisher.events).toContainEqual( expect.objectContaining({ type: 'RatingCalculatedEvent' }) ); }); ``` ## Observations Based on the concept documentation, the rating system is complex with many components: 1. **Rating Components**: Results Strength, Consistency, Clean Driving, Racecraft, Reliability, Team Contribution 2. **Calculation Logic**: Weighted scoring based on multiple factors 3. **Persistence**: Rating history and trend tracking 4. **Leaderboards**: Rating-based rankings and comparisons 5. **Team Integration**: Team contribution scoring 6. **Transparency**: Clear explanation of rating changes Each test file contains comprehensive test scenarios covering: - Success paths - Edge cases (small fields, DNFs, DNSs, penalties) - Error handling - Data orchestration patterns - Calculation accuracy - Persistence verification ## Next Steps 1. **Implement Test Logic**: Replace TODO comments with actual test implementations 2. **Add In-Memory Adapters**: Create In-Memory adapters for all required repositories 3. **Create Use Cases**: Implement the Use Cases referenced in the tests 4. **Create Ports**: Implement the Ports (Repositories, Event Publishers, etc.) 5. **Run Tests**: Execute tests to verify Use Case orchestration 6. **Refine Tests**: Update tests based on actual implementation details ## Related Documentation - [Clean Integration Strategy](../../plans/clean_integration_strategy.md) - [Testing Layers](../../docs/TESTING_LAYERS.md) - [BDD E2E Tests](../e2e/bdd/rating/) - [Rating Concept](../../docs/concept/RATING.md)