Files
gridpilot.gg/core/rating/application/use-cases/CalculateTeamContributionUseCase.test.ts
Marc Mintel afef777961
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
code quality
2026-01-26 02:27:37 +01:00

135 lines
4.1 KiB
TypeScript

/**
* Unit tests for CalculateTeamContributionUseCase
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CalculateTeamContributionUseCase } from './CalculateTeamContributionUseCase';
import { Driver } from '../../../racing/domain/entities/Driver';
import { Race } from '../../../racing/domain/entities/Race';
import { Result } from '../../../racing/domain/entities/result/Result';
import { Rating } from '../../domain/Rating';
import { DriverId } from '../../../racing/domain/entities/DriverId';
import { RaceId } from '../../../racing/domain/entities/RaceId';
const mockRatingRepository = {
findByDriverAndRace: vi.fn(),
save: vi.fn(),
};
const mockDriverRepository = {
findById: vi.fn(),
};
const mockRaceRepository = {
findById: vi.fn(),
};
const mockResultRepository = {
findByRaceId: vi.fn(),
};
describe('CalculateTeamContributionUseCase', () => {
let useCase: CalculateTeamContributionUseCase;
beforeEach(() => {
vi.clearAllMocks();
useCase = new CalculateTeamContributionUseCase({
ratingRepository: mockRatingRepository as any,
driverRepository: mockDriverRepository as any,
raceRepository: mockRaceRepository as any,
resultRepository: mockResultRepository as any,
});
});
describe('Scenario 8: Creates rating when missing', () => {
it('should create and save a new rating when none exists', async () => {
// Given
const driverId = 'driver-1';
const raceId = 'race-1';
const points = 25;
mockDriverRepository.findById.mockResolvedValue(Driver.create({
id: driverId,
iracingId: 'ir-1',
name: 'Driver 1',
country: 'US'
}));
mockRaceRepository.findById.mockResolvedValue(Race.create({
id: raceId,
leagueId: 'l-1',
scheduledAt: new Date(),
track: 'Track',
car: 'Car'
}));
mockResultRepository.findByRaceId.mockResolvedValue([
Result.create({
id: 'res-1',
raceId,
driverId,
position: 1,
points,
incidents: 0,
startPosition: 1,
fastestLap: 0
})
]);
mockRatingRepository.findByDriverAndRace.mockResolvedValue(null);
// When
const result = await useCase.execute({ driverId, raceId });
// Then
expect(mockRatingRepository.save).toHaveBeenCalled();
const savedRating = mockRatingRepository.save.mock.calls[0][0] as Rating;
expect(savedRating.components.teamContribution).toBe(100); // 25/25 * 100
expect(result.teamContribution).toBe(100);
});
});
describe('Scenario 9: Updates existing rating', () => {
it('should preserve other fields and only update teamContribution', async () => {
// Given
const driverId = 'driver-1';
const raceId = 'race-1';
const points = 12.5; // 50% contribution
const existingRating = Rating.create({
driverId: DriverId.create('driver-1'),
raceId: RaceId.create('race-1'),
rating: 1500,
components: {
resultsStrength: 80,
consistency: 70,
cleanDriving: 90,
racecraft: 75,
reliability: 85,
teamContribution: 10, // Old value
},
timestamp: new Date('2023-01-01')
});
mockDriverRepository.findById.mockResolvedValue({ id: driverId });
mockRaceRepository.findById.mockResolvedValue({ id: raceId });
mockResultRepository.findByRaceId.mockResolvedValue([
{ driverId: { toString: () => driverId }, points }
]);
mockRatingRepository.findByDriverAndRace.mockResolvedValue(existingRating);
// When
const result = await useCase.execute({ driverId, raceId });
// Then
expect(mockRatingRepository.save).toHaveBeenCalled();
const savedRating = mockRatingRepository.save.mock.calls[0][0] as Rating;
// Check preserved fields
expect(savedRating.rating).toBe(1500);
expect(savedRating.components.resultsStrength).toBe(80);
// Check updated field
expect(savedRating.components.teamContribution).toBe(50); // 12.5/25 * 100
expect(result.teamContribution).toBe(50);
});
});
});