import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest'; import { GetRaceRegistrationsUseCase, type GetRaceRegistrationsInput, type GetRaceRegistrationsResult, type GetRaceRegistrationsErrorCode, } from './GetRaceRegistrationsUseCase'; import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository'; import type { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository'; import { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration'; import { Race } from '@core/racing/domain/entities/Race'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { Result } from '@core/shared/application/Result'; describe('GetRaceRegistrationsUseCase', () => { let useCase: GetRaceRegistrationsUseCase; let raceRepository: { findById: Mock }; let registrationRepository: { findByRaceId: Mock }; let output: UseCaseOutputPort & { present: Mock }; beforeEach(() => { raceRepository = { findById: vi.fn() }; registrationRepository = { findByRaceId: vi.fn() }; output = { present: vi.fn() } as unknown as UseCaseOutputPort & { present: Mock }; useCase = new GetRaceRegistrationsUseCase( raceRepository as unknown as IRaceRepository, registrationRepository as unknown as IRaceRegistrationRepository, output, ); }); it('should present race and registrations on success', async () => { const input: GetRaceRegistrationsInput = { raceId: 'race-1' }; const race = Race.create({ id: input.raceId, leagueId: 'league-1', scheduledAt: new Date(), track: 'Track', car: 'Car', }); const registrations = [ RaceRegistration.create({ raceId: input.raceId, driverId: 'driver-1' }), RaceRegistration.create({ raceId: input.raceId, driverId: 'driver-2' }), ]; raceRepository.findById.mockResolvedValue(race); registrationRepository.findByRaceId.mockResolvedValue(registrations); const result: Result> = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(result.unwrap()).toBeUndefined(); expect(output.present).toHaveBeenCalledTimes(1); const presentedRaw = output.present.mock.calls[0]?.[0]; expect(presentedRaw).toBeDefined(); const presented = presentedRaw as GetRaceRegistrationsResult; expect(presented.race).toEqual(race); expect(presented.registrations).toHaveLength(2); expect(presented.registrations[0]!.registration).toEqual(registrations[0]); expect(presented.registrations[1]!.registration).toEqual(registrations[1]); }); it('should return RACE_NOT_FOUND error when race does not exist', async () => { const input: GetRaceRegistrationsInput = { raceId: 'non-existent-race' }; raceRepository.findById.mockResolvedValue(null); const result: Result> = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode< GetRaceRegistrationsErrorCode, { message: string } >; expect(err.code).toBe('RACE_NOT_FOUND'); expect(err.details?.message).toBe('Race not found'); expect(output.present).not.toHaveBeenCalled(); }); it('should return REPOSITORY_ERROR when repository throws', async () => { const input: GetRaceRegistrationsInput = { raceId: 'race-1' }; raceRepository.findById.mockRejectedValue(new Error('DB failure')); const result: Result> = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode< GetRaceRegistrationsErrorCode, { message: string } >; expect(err.code).toBe('REPOSITORY_ERROR'); expect(err.details?.message).toBe('DB failure'); expect(output.present).not.toHaveBeenCalled(); }); });