diff --git a/core/racing/application/use-cases/GetDriverLiveriesUseCase.test.ts b/core/racing/application/use-cases/GetDriverLiveriesUseCase.test.ts new file mode 100644 index 000000000..6de746914 --- /dev/null +++ b/core/racing/application/use-cases/GetDriverLiveriesUseCase.test.ts @@ -0,0 +1,101 @@ +import { describe, it, expect, vi } from 'vitest'; +import { GetDriverLiveriesUseCase, type GetDriverLiveriesInput } from './GetDriverLiveriesUseCase'; +import type { ILiveryRepository } from '../../domain/repositories/ILiveryRepository'; +import type { DriverLivery } from '../../domain/entities/DriverLivery'; +import type { Logger } from '@core/shared/application'; + +describe('GetDriverLiveriesUseCase', () => { + const mockLiveryRepository: ILiveryRepository = { + findDriverLiveryById: vi.fn(), + findDriverLiveriesByDriverId: vi.fn(), + findDriverLiveryByDriverAndCar: vi.fn(), + findDriverLiveriesByGameId: vi.fn(), + findDriverLiveryByDriverAndGame: vi.fn(), + createDriverLivery: vi.fn(), + updateDriverLivery: vi.fn(), + deleteDriverLivery: vi.fn(), + findTemplateById: vi.fn(), + findTemplatesBySeasonId: vi.fn(), + findTemplateBySeasonAndCar: vi.fn(), + createTemplate: vi.fn(), + updateTemplate: vi.fn(), + deleteTemplate: vi.fn(), + }; + + const mockLogger: Logger = { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }; + + it('should return driver liveries successfully', async () => { + const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger); + + const mockLiveries: DriverLivery[] = [ + { + id: 'livery1', + driverId: { value: 'driver1' }, + gameId: { value: 'game1' }, + carId: { value: 'car1' }, + uploadedImageUrl: { value: 'http://example.com/livery1.png' }, + userDecals: [], + leagueOverrides: [], + createdAt: new Date('2023-01-01'), + updatedAt: undefined, + validatedAt: undefined, + } as DriverLivery, + { + id: 'livery2', + driverId: { value: 'driver1' }, + gameId: { value: 'game1' }, + carId: { value: 'car2' }, + uploadedImageUrl: { value: 'http://example.com/livery2.png' }, + userDecals: [], + leagueOverrides: [], + createdAt: new Date('2023-01-02'), + updatedAt: undefined, + validatedAt: undefined, + } as DriverLivery, + ]; + + mockLiveryRepository.findDriverLiveriesByDriverId.mockResolvedValue(mockLiveries); + + const input: GetDriverLiveriesInput = { driverId: 'driver1' }; + + const result = await useCase.execute(input); + + expect(result.isOk()).toBe(true); + expect(result.unwrap()).toEqual(mockLiveries); + expect(mockLiveryRepository.findDriverLiveriesByDriverId).toHaveBeenCalledWith('driver1'); + }); + + it('should return empty array when no liveries found', async () => { + const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger); + + mockLiveryRepository.findDriverLiveriesByDriverId.mockResolvedValue([]); + + const input: GetDriverLiveriesInput = { driverId: 'driver1' }; + + const result = await useCase.execute(input); + + expect(result.isOk()).toBe(true); + expect(result.unwrap()).toEqual([]); + }); + + it('should return error when repository throws', async () => { + const useCase = new GetDriverLiveriesUseCase(mockLiveryRepository, mockLogger); + + const error = new Error('Repository error'); + mockLiveryRepository.findDriverLiveriesByDriverId.mockRejectedValue(error); + + const input: GetDriverLiveriesInput = { driverId: 'driver1' }; + + const result = await useCase.execute(input); + + expect(result.isErr()).toBe(true); + const err = result.unwrapErr(); + expect(err.code).toBe('REPOSITORY_ERROR'); + expect(err.details.message).toBe('Repository error'); + }); +}); \ No newline at end of file diff --git a/core/racing/application/use-cases/GetDriverLiveriesUseCase.ts b/core/racing/application/use-cases/GetDriverLiveriesUseCase.ts new file mode 100644 index 000000000..28503451c --- /dev/null +++ b/core/racing/application/use-cases/GetDriverLiveriesUseCase.ts @@ -0,0 +1,44 @@ +/** + * Use Case: GetDriverLiveriesUseCase + * + * Retrieves all liveries for a specific driver. + */ + +import { Result } from '@core/shared/application/Result'; +import { UseCase } from '@core/shared/application/UseCase'; +import type { Logger } from '@core/shared/application'; +import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; +import type { ILiveryRepository } from '../../domain/repositories/ILiveryRepository'; +import type { DriverLivery } from '../../domain/entities/DriverLivery'; + +export interface GetDriverLiveriesInput { + driverId: string; +} + +export type GetDriverLiveriesOutput = DriverLivery[]; + +export type GetDriverLiveriesErrorCode = 'REPOSITORY_ERROR'; + +export class GetDriverLiveriesUseCase implements UseCase { + constructor( + private readonly liveryRepository: ILiveryRepository, + private readonly logger: Logger, + ) {} + + async execute(input: GetDriverLiveriesInput): Promise>> { + this.logger.debug(`[GetDriverLiveriesUseCase] Fetching liveries for driver: ${input.driverId}`); + + try { + const liveries = await this.liveryRepository.findDriverLiveriesByDriverId(input.driverId); + this.logger.info(`[GetDriverLiveriesUseCase] Found ${liveries.length} liveries for driver: ${input.driverId}`); + return Result.ok(liveries); + } catch (error) { + const err = error instanceof Error ? error : new Error(String(error)); + this.logger.error(`[GetDriverLiveriesUseCase] Error fetching liveries for driver ${input.driverId}:`, err); + return Result.err({ + code: 'REPOSITORY_ERROR', + details: { message: err.message }, + }); + } + } +} \ No newline at end of file