import { describe, it, expect, beforeEach, vi, Mock } from 'vitest'; import { CompleteRaceUseCase } from './CompleteRaceUseCase'; import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { IRaceRegistrationRepository } from '../../domain/repositories/IRaceRegistrationRepository'; import type { IResultRepository } from '../../domain/repositories/IResultRepository'; import type { IStandingRepository } from '../../domain/repositories/IStandingRepository'; import type { CompleteRaceCommandDTO } from '../dto/CompleteRaceCommandDTO'; describe('CompleteRaceUseCase', () => { let useCase: CompleteRaceUseCase; let raceRepository: { findById: Mock; update: Mock; }; let raceRegistrationRepository: { getRegisteredDrivers: Mock; }; let resultRepository: { create: Mock; }; let standingRepository: { findByDriverIdAndLeagueId: Mock; save: Mock; }; let getDriverRating: Mock; beforeEach(() => { raceRepository = { findById: vi.fn(), update: vi.fn(), }; raceRegistrationRepository = { getRegisteredDrivers: vi.fn(), }; resultRepository = { create: vi.fn(), }; standingRepository = { findByDriverIdAndLeagueId: vi.fn(), save: vi.fn(), }; getDriverRating = vi.fn(); useCase = new CompleteRaceUseCase( raceRepository as unknown as IRaceRepository, raceRegistrationRepository as unknown as IRaceRegistrationRepository, resultRepository as unknown as IResultRepository, standingRepository as unknown as IStandingRepository, getDriverRating, ); }); it('should complete race successfully when race exists and has registered drivers', async () => { const command: CompleteRaceCommandDTO = { raceId: 'race-1', }; const mockRace = { id: 'race-1', leagueId: 'league-1', status: 'scheduled', complete: vi.fn().mockReturnValue({ id: 'race-1', status: 'completed' }), }; raceRepository.findById.mockResolvedValue(mockRace); raceRegistrationRepository.getRegisteredDrivers.mockResolvedValue(['driver-1', 'driver-2']); getDriverRating.mockImplementation((input) => { if (input.driverId === 'driver-1') return Promise.resolve({ rating: 1600, ratingChange: null }); if (input.driverId === 'driver-2') return Promise.resolve({ rating: 1500, ratingChange: null }); return Promise.resolve({ rating: null, ratingChange: null }); }); resultRepository.create.mockResolvedValue(undefined); standingRepository.findByDriverIdAndLeagueId.mockResolvedValue(null); standingRepository.save.mockResolvedValue(undefined); raceRepository.update.mockResolvedValue(undefined); const result = await useCase.execute(command); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual({}); expect(raceRepository.findById).toHaveBeenCalledWith('race-1'); expect(raceRegistrationRepository.getRegisteredDrivers).toHaveBeenCalledWith('race-1'); expect(getDriverRating).toHaveBeenCalledTimes(2); expect(resultRepository.create).toHaveBeenCalledTimes(2); expect(standingRepository.save).toHaveBeenCalledTimes(2); expect(mockRace.complete).toHaveBeenCalled(); expect(raceRepository.update).toHaveBeenCalledWith({ id: 'race-1', status: 'completed' }); }); it('should return error when race does not exist', async () => { const command: CompleteRaceCommandDTO = { raceId: 'race-1', }; raceRepository.findById.mockResolvedValue(null); const result = await useCase.execute(command); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND'); }); it('should return error when no registered drivers', async () => { const command: CompleteRaceCommandDTO = { raceId: 'race-1', }; const mockRace = { id: 'race-1', leagueId: 'league-1', status: 'scheduled', complete: vi.fn(), }; raceRepository.findById.mockResolvedValue(mockRace); raceRegistrationRepository.getRegisteredDrivers.mockResolvedValue([]); const result = await useCase.execute(command); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('NO_REGISTERED_DRIVERS'); }); it('should return error when repository throws', async () => { const command: CompleteRaceCommandDTO = { raceId: 'race-1', }; const mockRace = { id: 'race-1', leagueId: 'league-1', status: 'scheduled', complete: vi.fn().mockReturnValue({ id: 'race-1', status: 'completed' }), }; raceRepository.findById.mockResolvedValue(mockRace); raceRegistrationRepository.getRegisteredDrivers.mockResolvedValue(['driver-1']); getDriverRating.mockResolvedValue({ rating: 1600, ratingChange: null }); resultRepository.create.mockRejectedValue(new Error('DB error')); const result = await useCase.execute(command); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('UNKNOWN_ERROR'); }); });