import { describe, it, expect, beforeAll, beforeEach } from 'vitest'; import { RacesTestContext } from '../RacesTestContext'; import { ReviewProtestUseCase } from '../../../../core/racing/application/use-cases/ReviewProtestUseCase'; import { Race } from '../../../../core/racing/domain/entities/Race'; import { Protest } from '../../../../core/racing/domain/entities/Protest'; import { LeagueMembership } from '../../../../core/racing/domain/entities/LeagueMembership'; describe('ReviewProtestUseCase', () => { let context: RacesTestContext; let reviewProtestUseCase: ReviewProtestUseCase; beforeAll(() => { context = RacesTestContext.create(); reviewProtestUseCase = new ReviewProtestUseCase( context.protestRepository, context.raceRepository, context.leagueMembershipRepository, context.logger ); }); beforeEach(async () => { await context.clear(); }); it('should allow a steward to review a protest', async () => { // Given: A protest and a steward membership const leagueId = 'l1'; const raceId = 'r1'; const stewardId = 's1'; const race = Race.create({ id: raceId, leagueId, scheduledAt: new Date(), track: 'Spa', car: 'GT3', status: 'completed' }); await context.raceRepository.create(race); const protest = Protest.create({ id: 'p1', raceId, protestingDriverId: 'd1', accusedDriverId: 'd2', incident: { lap: 1, description: 'Unsafe rejoin' }, filedAt: new Date() }); await context.protestRepository.create(protest); const membership = LeagueMembership.create({ id: 'm1', leagueId, driverId: stewardId, role: 'admin', status: 'active' }); await context.leagueMembershipRepository.saveMembership(membership); // When: ReviewProtestUseCase.execute() is called const result = await reviewProtestUseCase.execute({ protestId: 'p1', stewardId, decision: 'uphold', decisionNotes: 'Clear violation' }); // Then: The protest should be updated expect(result.isOk()).toBe(true); const updatedProtest = await context.protestRepository.findById('p1'); expect(updatedProtest?.status.toString()).toBe('upheld'); expect(updatedProtest?.reviewedBy).toBe(stewardId); }); });