Files
gridpilot.gg/tests/integration/sponsor/sponsor-league-detail-use-cases.integration.test.ts

346 lines
16 KiB
TypeScript

/**
* Integration Test: Sponsor League Detail Use Case Orchestration
*
* Tests the orchestration logic of sponsor league detail-related Use Cases:
* - GetLeagueDetailUseCase: Retrieves detailed league information
* - GetLeagueStatisticsUseCase: Retrieves league statistics
* - GetSponsorshipSlotsUseCase: Retrieves sponsorship slots information
* - GetLeagueScheduleUseCase: Retrieves league schedule
* - Validates that Use Cases correctly interact with their Ports (Repositories, Event Publishers)
* - Uses In-Memory adapters for fast, deterministic testing
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
import { InMemorySponsorRepository } from '../../../adapters/sponsors/persistence/inmemory/InMemorySponsorRepository';
import { InMemoryLeagueRepository } from '../../../adapters/leagues/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryEventPublisher } from '../../../adapters/events/InMemoryEventPublisher';
import { GetLeagueDetailUseCase } from '../../../core/sponsors/use-cases/GetLeagueDetailUseCase';
import { GetLeagueStatisticsUseCase } from '../../../core/sponsors/use-cases/GetLeagueStatisticsUseCase';
import { GetSponsorshipSlotsUseCase } from '../../../core/sponsors/use-cases/GetSponsorshipSlotsUseCase';
import { GetLeagueScheduleUseCase } from '../../../core/sponsors/use-cases/GetLeagueScheduleUseCase';
import { GetLeagueDetailQuery } from '../../../core/sponsors/ports/GetLeagueDetailQuery';
import { GetLeagueStatisticsQuery } from '../../../core/sponsors/ports/GetLeagueStatisticsQuery';
import { GetSponsorshipSlotsQuery } from '../../../core/sponsors/ports/GetSponsorshipSlotsQuery';
import { GetLeagueScheduleQuery } from '../../../core/sponsors/ports/GetLeagueScheduleQuery';
describe('Sponsor League Detail Use Case Orchestration', () => {
let sponsorRepository: InMemorySponsorRepository;
let leagueRepository: InMemoryLeagueRepository;
let eventPublisher: InMemoryEventPublisher;
let getLeagueDetailUseCase: GetLeagueDetailUseCase;
let getLeagueStatisticsUseCase: GetLeagueStatisticsUseCase;
let getSponsorshipSlotsUseCase: GetSponsorshipSlotsUseCase;
let getLeagueScheduleUseCase: GetLeagueScheduleUseCase;
beforeAll(() => {
// TODO: Initialize In-Memory repositories and event publisher
// sponsorRepository = new InMemorySponsorRepository();
// leagueRepository = new InMemoryLeagueRepository();
// eventPublisher = new InMemoryEventPublisher();
// getLeagueDetailUseCase = new GetLeagueDetailUseCase({
// sponsorRepository,
// leagueRepository,
// eventPublisher,
// });
// getLeagueStatisticsUseCase = new GetLeagueStatisticsUseCase({
// sponsorRepository,
// leagueRepository,
// eventPublisher,
// });
// getSponsorshipSlotsUseCase = new GetSponsorshipSlotsUseCase({
// sponsorRepository,
// leagueRepository,
// eventPublisher,
// });
// getLeagueScheduleUseCase = new GetLeagueScheduleUseCase({
// sponsorRepository,
// leagueRepository,
// eventPublisher,
// });
});
beforeEach(() => {
// TODO: Clear all In-Memory repositories before each test
// sponsorRepository.clear();
// leagueRepository.clear();
// eventPublisher.clear();
});
describe('GetLeagueDetailUseCase - Success Path', () => {
it('should retrieve detailed league information', async () => {
// TODO: Implement test
// Scenario: Sponsor views league detail
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has name "Premier League"
// And: The league has description "Top tier racing league"
// And: The league has logo URL
// And: The league has category "Professional"
// When: GetLeagueDetailUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show league name
// And: The result should show league description
// And: The result should show league logo
// And: The result should show league category
// And: EventPublisher should emit LeagueDetailAccessedEvent
});
it('should retrieve league detail with minimal data', async () => {
// TODO: Implement test
// Scenario: League with minimal data
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has name "Test League"
// When: GetLeagueDetailUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show league name
// And: EventPublisher should emit LeagueDetailAccessedEvent
});
});
describe('GetLeagueDetailUseCase - Error Handling', () => {
it('should throw error when sponsor does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent sponsor
// Given: No sponsor exists with the given ID
// And: A league exists with ID "league-456"
// When: GetLeagueDetailUseCase.execute() is called with non-existent sponsor ID
// Then: Should throw SponsorNotFoundError
// And: EventPublisher should NOT emit any events
});
it('should throw error when league does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent league
// Given: A sponsor exists with ID "sponsor-123"
// And: No league exists with the given ID
// When: GetLeagueDetailUseCase.execute() is called with non-existent league ID
// Then: Should throw LeagueNotFoundError
// And: EventPublisher should NOT emit any events
});
it('should throw error when league ID is invalid', async () => {
// TODO: Implement test
// Scenario: Invalid league ID
// Given: A sponsor exists with ID "sponsor-123"
// And: An invalid league ID (e.g., empty string, null, undefined)
// When: GetLeagueDetailUseCase.execute() is called with invalid league ID
// Then: Should throw ValidationError
// And: EventPublisher should NOT emit any events
});
});
describe('GetLeagueStatisticsUseCase - Success Path', () => {
it('should retrieve league statistics', async () => {
// TODO: Implement test
// Scenario: League with statistics
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has 500 total drivers
// And: The league has 300 active drivers
// And: The league has 100 total races
// And: The league has average race duration of 45 minutes
// And: The league has popularity score of 85
// When: GetLeagueStatisticsUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show total drivers: 500
// And: The result should show active drivers: 300
// And: The result should show total races: 100
// And: The result should show average race duration: 45 minutes
// And: The result should show popularity score: 85
// And: EventPublisher should emit LeagueStatisticsAccessedEvent
});
it('should retrieve statistics with zero values', async () => {
// TODO: Implement test
// Scenario: League with no statistics
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has no drivers
// And: The league has no races
// When: GetLeagueStatisticsUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show total drivers: 0
// And: The result should show active drivers: 0
// And: The result should show total races: 0
// And: The result should show average race duration: 0
// And: The result should show popularity score: 0
// And: EventPublisher should emit LeagueStatisticsAccessedEvent
});
});
describe('GetLeagueStatisticsUseCase - Error Handling', () => {
it('should throw error when sponsor does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent sponsor
// Given: No sponsor exists with the given ID
// And: A league exists with ID "league-456"
// When: GetLeagueStatisticsUseCase.execute() is called with non-existent sponsor ID
// Then: Should throw SponsorNotFoundError
// And: EventPublisher should NOT emit any events
});
it('should throw error when league does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent league
// Given: A sponsor exists with ID "sponsor-123"
// And: No league exists with the given ID
// When: GetLeagueStatisticsUseCase.execute() is called with non-existent league ID
// Then: Should throw LeagueNotFoundError
// And: EventPublisher should NOT emit any events
});
});
describe('GetSponsorshipSlotsUseCase - Success Path', () => {
it('should retrieve sponsorship slots information', async () => {
// TODO: Implement test
// Scenario: League with sponsorship slots
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has main sponsor slot available
// And: The league has 5 secondary sponsor slots available
// And: The main slot has pricing of $10000
// And: The secondary slots have pricing of $2000 each
// When: GetSponsorshipSlotsUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show main sponsor slot details
// And: The result should show secondary sponsor slots details
// And: The result should show available slots count
// And: EventPublisher should emit SponsorshipSlotsAccessedEvent
});
it('should retrieve slots with no available slots', async () => {
// TODO: Implement test
// Scenario: League with no available slots
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has no available sponsorship slots
// When: GetSponsorshipSlotsUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show no available slots
// And: EventPublisher should emit SponsorshipSlotsAccessedEvent
});
});
describe('GetSponsorshipSlotsUseCase - Error Handling', () => {
it('should throw error when sponsor does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent sponsor
// Given: No sponsor exists with the given ID
// And: A league exists with ID "league-456"
// When: GetSponsorshipSlotsUseCase.execute() is called with non-existent sponsor ID
// Then: Should throw SponsorNotFoundError
// And: EventPublisher should NOT emit any events
});
it('should throw error when league does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent league
// Given: A sponsor exists with ID "sponsor-123"
// And: No league exists with the given ID
// When: GetSponsorshipSlotsUseCase.execute() is called with non-existent league ID
// Then: Should throw LeagueNotFoundError
// And: EventPublisher should NOT emit any events
});
});
describe('GetLeagueScheduleUseCase - Success Path', () => {
it('should retrieve league schedule', async () => {
// TODO: Implement test
// Scenario: League with schedule
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has 5 upcoming races
// When: GetLeagueScheduleUseCase.execute() is called with sponsor ID and league ID
// Then: The result should show upcoming races
// And: Each race should show race date
// And: Each race should show race location
// And: Each race should show race type
// And: EventPublisher should emit LeagueScheduleAccessedEvent
});
it('should retrieve schedule with no upcoming races', async () => {
// TODO: Implement test
// Scenario: League with no upcoming races
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has no upcoming races
// When: GetLeagueScheduleUseCase.execute() is called with sponsor ID and league ID
// Then: The result should be empty
// And: EventPublisher should emit LeagueScheduleAccessedEvent
});
});
describe('GetLeagueScheduleUseCase - Error Handling', () => {
it('should throw error when sponsor does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent sponsor
// Given: No sponsor exists with the given ID
// And: A league exists with ID "league-456"
// When: GetLeagueScheduleUseCase.execute() is called with non-existent sponsor ID
// Then: Should throw SponsorNotFoundError
// And: EventPublisher should NOT emit any events
});
it('should throw error when league does not exist', async () => {
// TODO: Implement test
// Scenario: Non-existent league
// Given: A sponsor exists with ID "sponsor-123"
// And: No league exists with the given ID
// When: GetLeagueScheduleUseCase.execute() is called with non-existent league ID
// Then: Should throw LeagueNotFoundError
// And: EventPublisher should NOT emit any events
});
});
describe('League Detail Data Orchestration', () => {
it('should correctly retrieve league detail with all information', async () => {
// TODO: Implement test
// Scenario: League detail orchestration
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has complete information
// When: GetLeagueDetailUseCase.execute() is called
// Then: The result should contain all league information
// And: Each field should be populated correctly
// And: EventPublisher should emit LeagueDetailAccessedEvent
});
it('should correctly aggregate league statistics', async () => {
// TODO: Implement test
// Scenario: League statistics aggregation
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has 500 total drivers
// And: The league has 300 active drivers
// And: The league has 100 total races
// When: GetLeagueStatisticsUseCase.execute() is called
// Then: Total drivers should be 500
// And: Active drivers should be 300
// And: Total races should be 100
// And: EventPublisher should emit LeagueStatisticsAccessedEvent
});
it('should correctly retrieve sponsorship slots', async () => {
// TODO: Implement test
// Scenario: Sponsorship slots retrieval
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has main sponsor slot available
// And: The league has 5 secondary sponsor slots available
// When: GetSponsorshipSlotsUseCase.execute() is called
// Then: Main sponsor slot should be available
// And: Secondary sponsor slots count should be 5
// And: EventPublisher should emit SponsorshipSlotsAccessedEvent
});
it('should correctly retrieve league schedule', async () => {
// TODO: Implement test
// Scenario: League schedule retrieval
// Given: A sponsor exists with ID "sponsor-123"
// And: A league exists with ID "league-456"
// And: The league has 5 upcoming races
// When: GetLeagueScheduleUseCase.execute() is called
// Then: All 5 races should be returned
// And: Each race should have correct details
// And: EventPublisher should emit LeagueScheduleAccessedEvent
});
});
});