integration tests
This commit is contained in:
@@ -3,767 +3,143 @@
|
||||
*
|
||||
* Tests the orchestration logic of race detail page-related Use Cases:
|
||||
* - GetRaceDetailUseCase: Retrieves comprehensive race details
|
||||
* - GetRaceParticipantsUseCase: Retrieves race participants count
|
||||
* - GetRaceWinnerUseCase: Retrieves race winner and podium
|
||||
* - GetRaceStatisticsUseCase: Retrieves race statistics
|
||||
* - GetRaceLapTimesUseCase: Retrieves race lap times
|
||||
* - GetRaceQualifyingUseCase: Retrieves race qualifying results
|
||||
* - GetRacePointsUseCase: Retrieves race points distribution
|
||||
* - GetRaceHighlightsUseCase: Retrieves race highlights
|
||||
* - Validates that Use Cases correctly interact with their Ports (Repositories, Event Publishers)
|
||||
* - Uses In-Memory adapters for fast, deterministic testing
|
||||
*
|
||||
* Adheres to Clean Architecture:
|
||||
* - Tests Core Use Cases directly
|
||||
* - Uses In-Memory adapters for repositories
|
||||
* - Follows Given/When/Then pattern
|
||||
*
|
||||
* Focus: Business logic orchestration, NOT UI rendering
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import { InMemoryRaceRepository } from '../../../adapters/races/persistence/inmemory/InMemoryRaceRepository';
|
||||
import { InMemoryEventPublisher } from '../../../adapters/events/InMemoryEventPublisher';
|
||||
import { GetRaceDetailUseCase } from '../../../core/races/use-cases/GetRaceDetailUseCase';
|
||||
import { GetRaceParticipantsUseCase } from '../../../core/races/use-cases/GetRaceParticipantsUseCase';
|
||||
import { GetRaceWinnerUseCase } from '../../../core/races/use-cases/GetRaceWinnerUseCase';
|
||||
import { GetRaceStatisticsUseCase } from '../../../core/races/use-cases/GetRaceStatisticsUseCase';
|
||||
import { GetRaceLapTimesUseCase } from '../../../core/races/use-cases/GetRaceLapTimesUseCase';
|
||||
import { GetRaceQualifyingUseCase } from '../../../core/races/use-cases/GetRaceQualifyingUseCase';
|
||||
import { GetRacePointsUseCase } from '../../../core/races/use-cases/GetRacePointsUseCase';
|
||||
import { GetRaceHighlightsUseCase } from '../../../core/races/use-cases/GetRaceHighlightsUseCase';
|
||||
import { RaceDetailQuery } from '../../../core/races/ports/RaceDetailQuery';
|
||||
import { RaceParticipantsQuery } from '../../../core/races/ports/RaceParticipantsQuery';
|
||||
import { RaceWinnerQuery } from '../../../core/races/ports/RaceWinnerQuery';
|
||||
import { RaceStatisticsQuery } from '../../../core/races/ports/RaceStatisticsQuery';
|
||||
import { RaceLapTimesQuery } from '../../../core/races/ports/RaceLapTimesQuery';
|
||||
import { RaceQualifyingQuery } from '../../../core/races/ports/RaceQualifyingQuery';
|
||||
import { RacePointsQuery } from '../../../core/races/ports/RacePointsQuery';
|
||||
import { RaceHighlightsQuery } from '../../../core/races/ports/RaceHighlightsQuery';
|
||||
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
|
||||
import { InMemoryRaceRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryRaceRepository';
|
||||
import { InMemoryLeagueRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
|
||||
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
|
||||
import { InMemoryRaceRegistrationRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
|
||||
import { InMemoryResultRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryResultRepository';
|
||||
import { InMemoryLeagueMembershipRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
|
||||
import { GetRaceDetailUseCase } from '../../../core/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import { Race } from '../../../core/racing/domain/entities/Race';
|
||||
import { League } from '../../../core/racing/domain/entities/League';
|
||||
import { Driver } from '../../../core/racing/domain/entities/Driver';
|
||||
import { Logger } from '../../../core/shared/domain/Logger';
|
||||
|
||||
describe('Race Detail Use Case Orchestration', () => {
|
||||
let raceRepository: InMemoryRaceRepository;
|
||||
let eventPublisher: InMemoryEventPublisher;
|
||||
let leagueRepository: InMemoryLeagueRepository;
|
||||
let driverRepository: InMemoryDriverRepository;
|
||||
let raceRegistrationRepository: InMemoryRaceRegistrationRepository;
|
||||
let resultRepository: InMemoryResultRepository;
|
||||
let leagueMembershipRepository: InMemoryLeagueMembershipRepository;
|
||||
let getRaceDetailUseCase: GetRaceDetailUseCase;
|
||||
let getRaceParticipantsUseCase: GetRaceParticipantsUseCase;
|
||||
let getRaceWinnerUseCase: GetRaceWinnerUseCase;
|
||||
let getRaceStatisticsUseCase: GetRaceStatisticsUseCase;
|
||||
let getRaceLapTimesUseCase: GetRaceLapTimesUseCase;
|
||||
let getRaceQualifyingUseCase: GetRaceQualifyingUseCase;
|
||||
let getRacePointsUseCase: GetRacePointsUseCase;
|
||||
let getRaceHighlightsUseCase: GetRaceHighlightsUseCase;
|
||||
let mockLogger: Logger;
|
||||
|
||||
beforeAll(() => {
|
||||
// TODO: Initialize In-Memory repositories and event publisher
|
||||
// raceRepository = new InMemoryRaceRepository();
|
||||
// eventPublisher = new InMemoryEventPublisher();
|
||||
// getRaceDetailUseCase = new GetRaceDetailUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceParticipantsUseCase = new GetRaceParticipantsUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceWinnerUseCase = new GetRaceWinnerUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceStatisticsUseCase = new GetRaceStatisticsUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceLapTimesUseCase = new GetRaceLapTimesUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceQualifyingUseCase = new GetRaceQualifyingUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRacePointsUseCase = new GetRacePointsUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
// getRaceHighlightsUseCase = new GetRaceHighlightsUseCase({
|
||||
// raceRepository,
|
||||
// eventPublisher,
|
||||
// });
|
||||
mockLogger = {
|
||||
info: () => {},
|
||||
debug: () => {},
|
||||
warn: () => {},
|
||||
error: () => {},
|
||||
} as unknown as Logger;
|
||||
|
||||
raceRepository = new InMemoryRaceRepository(mockLogger);
|
||||
leagueRepository = new InMemoryLeagueRepository(mockLogger);
|
||||
driverRepository = new InMemoryDriverRepository(mockLogger);
|
||||
raceRegistrationRepository = new InMemoryRaceRegistrationRepository(mockLogger);
|
||||
resultRepository = new InMemoryResultRepository(mockLogger, raceRepository);
|
||||
leagueMembershipRepository = new InMemoryLeagueMembershipRepository(mockLogger);
|
||||
|
||||
getRaceDetailUseCase = new GetRaceDetailUseCase(
|
||||
raceRepository,
|
||||
leagueRepository,
|
||||
driverRepository,
|
||||
raceRegistrationRepository,
|
||||
resultRepository,
|
||||
leagueMembershipRepository
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// TODO: Clear all In-Memory repositories before each test
|
||||
// raceRepository.clear();
|
||||
// eventPublisher.clear();
|
||||
beforeEach(async () => {
|
||||
// Clear repositories
|
||||
(raceRepository as any).races.clear();
|
||||
leagueRepository.clear();
|
||||
await driverRepository.clear();
|
||||
(raceRegistrationRepository as any).registrations.clear();
|
||||
(resultRepository as any).results.clear();
|
||||
leagueMembershipRepository.clear();
|
||||
});
|
||||
|
||||
describe('GetRaceDetailUseCase - Success Path', () => {
|
||||
describe('GetRaceDetailUseCase', () => {
|
||||
it('should retrieve race detail with complete information', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Driver views race detail
|
||||
// Given: A race exists with complete information
|
||||
// And: The race has track, car, league, date, time, duration, status
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should contain complete race information
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
// Given: A race and league exist
|
||||
const leagueId = 'l1';
|
||||
const league = League.create({ id: leagueId, name: 'Pro League', description: 'Desc', ownerId: 'o1' });
|
||||
await leagueRepository.create(league);
|
||||
|
||||
const raceId = 'r1';
|
||||
const race = Race.create({
|
||||
id: raceId,
|
||||
leagueId,
|
||||
scheduledAt: new Date(Date.now() + 86400000),
|
||||
track: 'Spa',
|
||||
car: 'GT3',
|
||||
status: 'scheduled'
|
||||
});
|
||||
await raceRepository.create(race);
|
||||
|
||||
// When: GetRaceDetailUseCase.execute() is called
|
||||
const result = await getRaceDetailUseCase.execute({ raceId });
|
||||
|
||||
// Then: The result should contain race and league information
|
||||
expect(result.isOk()).toBe(true);
|
||||
const data = result.unwrap();
|
||||
expect(data.race.id).toBe(raceId);
|
||||
expect(data.league?.id).toBe(leagueId);
|
||||
expect(data.isUserRegistered).toBe(false);
|
||||
});
|
||||
|
||||
it('should retrieve race detail with track layout', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with track layout
|
||||
// Given: A race exists with track layout
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show track layout
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with weather information', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with weather information
|
||||
// Given: A race exists with weather information
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show weather information
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with race conditions', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with conditions
|
||||
// Given: A race exists with conditions
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show race conditions
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with description', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with description
|
||||
// Given: A race exists with description
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show description
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with rules', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with rules
|
||||
// Given: A race exists with rules
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show rules
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with requirements', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with requirements
|
||||
// Given: A race exists with requirements
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show requirements
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with page title', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with page title
|
||||
// Given: A race exists
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should include page title
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race detail with page description', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with page description
|
||||
// Given: A race exists
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should include page description
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceDetailUseCase - Edge Cases', () => {
|
||||
it('should handle race with missing track information', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with missing track data
|
||||
// Given: A race exists with missing track information
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should contain race with available information
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should handle race with missing car information', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with missing car data
|
||||
// Given: A race exists with missing car information
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should contain race with available information
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should handle race with missing league information', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with missing league data
|
||||
// Given: A race exists with missing league information
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should contain race with available information
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should handle race with no description', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no description
|
||||
// Given: A race exists with no description
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default description
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should handle race with no rules', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no rules
|
||||
// Given: A race exists with no rules
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default rules
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should handle race with no requirements', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no requirements
|
||||
// Given: A race exists with no requirements
|
||||
// When: GetRaceDetailUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default requirements
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceDetailUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceDetailUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
const result = await getRaceDetailUseCase.execute({ raceId: 'non-existent' });
|
||||
|
||||
// Then: Should return RACE_NOT_FOUND error
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND');
|
||||
});
|
||||
|
||||
it('should throw error when race ID is invalid', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Invalid race ID
|
||||
// Given: An invalid race ID (e.g., empty string, null, undefined)
|
||||
// When: GetRaceDetailUseCase.execute() is called with invalid race ID
|
||||
// Then: Should throw ValidationError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
it('should identify if a driver is registered', async () => {
|
||||
// Given: A race and a registered driver
|
||||
const leagueId = 'l1';
|
||||
const raceId = 'r1';
|
||||
const driverId = 'd1';
|
||||
|
||||
const race = Race.create({
|
||||
id: raceId,
|
||||
leagueId,
|
||||
scheduledAt: new Date(Date.now() + 86400000),
|
||||
track: 'Spa',
|
||||
car: 'GT3',
|
||||
status: 'scheduled'
|
||||
});
|
||||
await raceRepository.create(race);
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: A race exists
|
||||
// And: RaceRepository throws an error during query
|
||||
// When: GetRaceDetailUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
const driver = Driver.create({ id: driverId, iracingId: '100', name: 'John Doe', country: 'US' });
|
||||
await driverRepository.create(driver);
|
||||
|
||||
describe('GetRaceParticipantsUseCase - Success Path', () => {
|
||||
it('should retrieve race participants count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with participants
|
||||
// Given: A race exists with participants
|
||||
// When: GetRaceParticipantsUseCase.execute() is called with race ID
|
||||
// Then: The result should show participants count
|
||||
// And: EventPublisher should emit RaceParticipantsAccessedEvent
|
||||
});
|
||||
// Mock registration (using any to bypass private access if needed, but InMemoryRaceRegistrationRepository has register method)
|
||||
await raceRegistrationRepository.register({
|
||||
raceId: raceId as any,
|
||||
driverId: driverId as any,
|
||||
registeredAt: new Date()
|
||||
} as any);
|
||||
|
||||
it('should retrieve race participants count for race with no participants', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no participants
|
||||
// Given: A race exists with no participants
|
||||
// When: GetRaceParticipantsUseCase.execute() is called with race ID
|
||||
// Then: The result should show 0 participants
|
||||
// And: EventPublisher should emit RaceParticipantsAccessedEvent
|
||||
});
|
||||
// When: GetRaceDetailUseCase.execute() is called with driverId
|
||||
const result = await getRaceDetailUseCase.execute({ raceId, driverId });
|
||||
|
||||
it('should retrieve race participants count for upcoming race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Upcoming race with participants
|
||||
// Given: An upcoming race exists with participants
|
||||
// When: GetRaceParticipantsUseCase.execute() is called with race ID
|
||||
// Then: The result should show participants count
|
||||
// And: EventPublisher should emit RaceParticipantsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race participants count for completed race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Completed race with participants
|
||||
// Given: A completed race exists with participants
|
||||
// When: GetRaceParticipantsUseCase.execute() is called with race ID
|
||||
// Then: The result should show participants count
|
||||
// And: EventPublisher should emit RaceParticipantsAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceParticipantsUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceParticipantsUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceParticipantsUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceWinnerUseCase - Success Path', () => {
|
||||
it('should retrieve race winner for completed race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Completed race with winner
|
||||
// Given: A completed race exists with winner
|
||||
// When: GetRaceWinnerUseCase.execute() is called with race ID
|
||||
// Then: The result should show race winner
|
||||
// And: EventPublisher should emit RaceWinnerAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race podium for completed race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Completed race with podium
|
||||
// Given: A completed race exists with podium
|
||||
// When: GetRaceWinnerUseCase.execute() is called with race ID
|
||||
// Then: The result should show top 3 finishers
|
||||
// And: EventPublisher should emit RaceWinnerAccessedEvent
|
||||
});
|
||||
|
||||
it('should not retrieve winner for upcoming race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Upcoming race without winner
|
||||
// Given: An upcoming race exists
|
||||
// When: GetRaceWinnerUseCase.execute() is called with race ID
|
||||
// Then: The result should not show winner or podium
|
||||
// And: EventPublisher should emit RaceWinnerAccessedEvent
|
||||
});
|
||||
|
||||
it('should not retrieve winner for in-progress race', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: In-progress race without winner
|
||||
// Given: An in-progress race exists
|
||||
// When: GetRaceWinnerUseCase.execute() is called with race ID
|
||||
// Then: The result should not show winner or podium
|
||||
// And: EventPublisher should emit RaceWinnerAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceWinnerUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceWinnerUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceWinnerUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceStatisticsUseCase - Success Path', () => {
|
||||
it('should retrieve race statistics with lap count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with lap count
|
||||
// Given: A race exists with lap count
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show lap count
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with incidents count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with incidents count
|
||||
// Given: A race exists with incidents count
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show incidents count
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with penalties count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with penalties count
|
||||
// Given: A race exists with penalties count
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show penalties count
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with protests count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with protests count
|
||||
// Given: A race exists with protests count
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show protests count
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with stewarding actions count', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with stewarding actions count
|
||||
// Given: A race exists with stewarding actions count
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show stewarding actions count
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with all metrics', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with all statistics
|
||||
// Given: A race exists with all statistics
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show all statistics
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race statistics with empty metrics', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no statistics
|
||||
// Given: A race exists with no statistics
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default statistics
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceStatisticsUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceStatisticsUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceStatisticsUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceLapTimesUseCase - Success Path', () => {
|
||||
it('should retrieve race lap times with average lap time', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with average lap time
|
||||
// Given: A race exists with average lap time
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with race ID
|
||||
// Then: The result should show average lap time
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race lap times with fastest lap', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with fastest lap
|
||||
// Given: A race exists with fastest lap
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with race ID
|
||||
// Then: The result should show fastest lap
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race lap times with best sector times', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with best sector times
|
||||
// Given: A race exists with best sector times
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with race ID
|
||||
// Then: The result should show best sector times
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race lap times with all metrics', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with all lap time metrics
|
||||
// Given: A race exists with all lap time metrics
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with race ID
|
||||
// Then: The result should show all lap time metrics
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race lap times with empty metrics', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no lap times
|
||||
// Given: A race exists with no lap times
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default lap times
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceLapTimesUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceLapTimesUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceLapTimesUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceQualifyingUseCase - Success Path', () => {
|
||||
it('should retrieve race qualifying results', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with qualifying results
|
||||
// Given: A race exists with qualifying results
|
||||
// When: GetRaceQualifyingUseCase.execute() is called with race ID
|
||||
// Then: The result should show qualifying results
|
||||
// And: EventPublisher should emit RaceQualifyingAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race starting grid', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with starting grid
|
||||
// Given: A race exists with starting grid
|
||||
// When: GetRaceQualifyingUseCase.execute() is called with race ID
|
||||
// Then: The result should show starting grid
|
||||
// And: EventPublisher should emit RaceQualifyingAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race qualifying results with pole position', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with pole position
|
||||
// Given: A race exists with pole position
|
||||
// When: GetRaceQualifyingUseCase.execute() is called with race ID
|
||||
// Then: The result should show pole position
|
||||
// And: EventPublisher should emit RaceQualifyingAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race qualifying results with empty results', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no qualifying results
|
||||
// Given: A race exists with no qualifying results
|
||||
// When: GetRaceQualifyingUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default qualifying results
|
||||
// And: EventPublisher should emit RaceQualifyingAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceQualifyingUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceQualifyingUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceQualifyingUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRacePointsUseCase - Success Path', () => {
|
||||
it('should retrieve race points distribution', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with points distribution
|
||||
// Given: A race exists with points distribution
|
||||
// When: GetRacePointsUseCase.execute() is called with race ID
|
||||
// Then: The result should show points distribution
|
||||
// And: EventPublisher should emit RacePointsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race championship implications', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with championship implications
|
||||
// Given: A race exists with championship implications
|
||||
// When: GetRacePointsUseCase.execute() is called with race ID
|
||||
// Then: The result should show championship implications
|
||||
// And: EventPublisher should emit RacePointsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race points with empty distribution', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no points distribution
|
||||
// Given: A race exists with no points distribution
|
||||
// When: GetRacePointsUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default points distribution
|
||||
// And: EventPublisher should emit RacePointsAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRacePointsUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRacePointsUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRacePointsUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceHighlightsUseCase - Success Path', () => {
|
||||
it('should retrieve race highlights', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with highlights
|
||||
// Given: A race exists with highlights
|
||||
// When: GetRaceHighlightsUseCase.execute() is called with race ID
|
||||
// Then: The result should show highlights
|
||||
// And: EventPublisher should emit RaceHighlightsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race video link', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with video link
|
||||
// Given: A race exists with video link
|
||||
// When: GetRaceHighlightsUseCase.execute() is called with race ID
|
||||
// Then: The result should show video link
|
||||
// And: EventPublisher should emit RaceHighlightsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race gallery', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with gallery
|
||||
// Given: A race exists with gallery
|
||||
// When: GetRaceHighlightsUseCase.execute() is called with race ID
|
||||
// Then: The result should show gallery
|
||||
// And: EventPublisher should emit RaceHighlightsAccessedEvent
|
||||
});
|
||||
|
||||
it('should retrieve race highlights with empty results', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no highlights
|
||||
// Given: A race exists with no highlights
|
||||
// When: GetRaceHighlightsUseCase.execute() is called with race ID
|
||||
// Then: The result should show empty or default highlights
|
||||
// And: EventPublisher should emit RaceHighlightsAccessedEvent
|
||||
});
|
||||
});
|
||||
|
||||
describe('GetRaceHighlightsUseCase - Error Handling', () => {
|
||||
it('should throw error when race does not exist', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Non-existent race
|
||||
// Given: No race exists with the given ID
|
||||
// When: GetRaceHighlightsUseCase.execute() is called with non-existent race ID
|
||||
// Then: Should throw RaceNotFoundError
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
|
||||
it('should handle repository errors gracefully', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Repository throws error
|
||||
// Given: RaceRepository throws an error during query
|
||||
// When: GetRaceHighlightsUseCase.execute() is called
|
||||
// Then: Should propagate the error appropriately
|
||||
// And: EventPublisher should NOT emit any events
|
||||
});
|
||||
});
|
||||
|
||||
describe('Race Detail Page Data Orchestration', () => {
|
||||
it('should correctly orchestrate data for race detail page', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race detail page data orchestration
|
||||
// Given: A race exists with all information
|
||||
// When: Multiple use cases are executed for the same race
|
||||
// Then: Each use case should return its respective data
|
||||
// And: EventPublisher should emit appropriate events for each use case
|
||||
});
|
||||
|
||||
it('should correctly format race information for display', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race information formatting
|
||||
// Given: A race exists with all information
|
||||
// When: GetRaceDetailUseCase.execute() is called
|
||||
// Then: The result should format:
|
||||
// - Track name: Clearly displayed
|
||||
// - Car: Clearly displayed
|
||||
// - League: Clearly displayed
|
||||
// - Date: Formatted correctly
|
||||
// - Time: Formatted correctly
|
||||
// - Duration: Formatted correctly
|
||||
// - Status: Clearly indicated (Upcoming, In Progress, Completed)
|
||||
});
|
||||
|
||||
it('should correctly handle race status transitions', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race status transitions
|
||||
// Given: A race exists with status "Upcoming"
|
||||
// When: Race status changes to "In Progress"
|
||||
// And: GetRaceDetailUseCase.execute() is called
|
||||
// Then: The result should show the updated status
|
||||
// And: EventPublisher should emit RaceDetailAccessedEvent
|
||||
});
|
||||
|
||||
it('should correctly handle race with no statistics', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no statistics
|
||||
// Given: A race exists with no statistics
|
||||
// When: GetRaceStatisticsUseCase.execute() is called
|
||||
// Then: The result should show empty or default statistics
|
||||
// And: EventPublisher should emit RaceStatisticsAccessedEvent
|
||||
});
|
||||
|
||||
it('should correctly handle race with no lap times', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no lap times
|
||||
// Given: A race exists with no lap times
|
||||
// When: GetRaceLapTimesUseCase.execute() is called
|
||||
// Then: The result should show empty or default lap times
|
||||
// And: EventPublisher should emit RaceLapTimesAccessedEvent
|
||||
});
|
||||
|
||||
it('should correctly handle race with no qualifying results', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no qualifying results
|
||||
// Given: A race exists with no qualifying results
|
||||
// When: GetRaceQualifyingUseCase.execute() is called
|
||||
// Then: The result should show empty or default qualifying results
|
||||
// And: EventPublisher should emit RaceQualifyingAccessedEvent
|
||||
});
|
||||
|
||||
it('should correctly handle race with no highlights', async () => {
|
||||
// TODO: Implement test
|
||||
// Scenario: Race with no highlights
|
||||
// Given: A race exists with no highlights
|
||||
// When: GetRaceHighlightsUseCase.execute() is called
|
||||
// Then: The result should show empty or default highlights
|
||||
// And: EventPublisher should emit RaceHighlightsAccessedEvent
|
||||
// Then: isUserRegistered should be true
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap().isUserRegistered).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user