Files
gridpilot.gg/tests/integration/sponsor/sponsor-league-detail-use-cases.integration.test.ts
Marc Mintel 2fba80da57
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 4m46s
Contract Testing / contract-snapshot (pull_request) Has been skipped
integration tests
2026-01-22 19:16:43 +01:00

340 lines
13 KiB
TypeScript

/**
* Integration Test: Sponsor League Detail Use Case Orchestration
*
* Tests the orchestration logic of sponsor league detail-related Use Cases:
* - GetEntitySponsorshipPricingUseCase: Retrieves sponsorship pricing for leagues
* - Validates that Use Cases correctly interact with their Ports (Repositories)
* - Uses In-Memory adapters for fast, deterministic testing
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemorySponsorshipPricingRepository } from '../../../adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
import { GetEntitySponsorshipPricingUseCase } from '../../../core/racing/application/use-cases/GetEntitySponsorshipPricingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';
describe('Sponsor League Detail Use Case Orchestration', () => {
let sponsorshipPricingRepository: InMemorySponsorshipPricingRepository;
let getEntitySponsorshipPricingUseCase: GetEntitySponsorshipPricingUseCase;
let mockLogger: Logger;
beforeAll(() => {
mockLogger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
sponsorshipPricingRepository = new InMemorySponsorshipPricingRepository(mockLogger);
getEntitySponsorshipPricingUseCase = new GetEntitySponsorshipPricingUseCase(
sponsorshipPricingRepository,
mockLogger,
);
});
beforeEach(() => {
sponsorshipPricingRepository.clear();
});
describe('GetEntitySponsorshipPricingUseCase - Success Path', () => {
it('should retrieve sponsorship pricing for a league', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured
const pricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: true,
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: ['Primary logo placement', 'League page header banner'],
},
secondarySlots: {
price: { amount: 2000, currency: 'USD' },
benefits: ['Secondary logo on liveries', 'League page sidebar placement'],
},
};
await sponsorshipPricingRepository.create(pricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The result should contain sponsorship pricing
expect(result.isOk()).toBe(true);
const pricingResult = result.unwrap();
// And: The entity type should be correct
expect(pricingResult.entityType).toBe('league');
// And: The entity ID should be correct
expect(pricingResult.entityId).toBe(leagueId);
// And: The league should be accepting applications
expect(pricingResult.acceptingApplications).toBe(true);
// And: The tiers should contain main slot
expect(pricingResult.tiers).toHaveLength(2);
expect(pricingResult.tiers[0].name).toBe('main');
expect(pricingResult.tiers[0].price.amount).toBe(10000);
expect(pricingResult.tiers[0].price.currency).toBe('USD');
expect(pricingResult.tiers[0].benefits).toContain('Primary logo placement');
// And: The tiers should contain secondary slot
expect(pricingResult.tiers[1].name).toBe('secondary');
expect(pricingResult.tiers[1].price.amount).toBe(2000);
expect(pricingResult.tiers[1].price.currency).toBe('USD');
expect(pricingResult.tiers[1].benefits).toContain('Secondary logo on liveries');
});
it('should retrieve sponsorship pricing with only main slot', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured with only main slot
const pricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: true,
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: ['Primary logo placement', 'League page header banner'],
},
};
await sponsorshipPricingRepository.create(pricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The result should contain sponsorship pricing
expect(result.isOk()).toBe(true);
const pricingResult = result.unwrap();
// And: The tiers should contain only main slot
expect(pricingResult.tiers).toHaveLength(1);
expect(pricingResult.tiers[0].name).toBe('main');
expect(pricingResult.tiers[0].price.amount).toBe(10000);
});
it('should retrieve sponsorship pricing with custom requirements', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured with custom requirements
const pricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: true,
customRequirements: 'Must have racing experience',
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: ['Primary logo placement'],
},
};
await sponsorshipPricingRepository.create(pricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The result should contain sponsorship pricing
expect(result.isOk()).toBe(true);
const pricingResult = result.unwrap();
// And: The custom requirements should be included
expect(pricingResult.customRequirements).toBe('Must have racing experience');
});
it('should retrieve sponsorship pricing with not accepting applications', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured but not accepting applications
const pricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: false,
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: ['Primary logo placement'],
},
};
await sponsorshipPricingRepository.create(pricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The result should contain sponsorship pricing
expect(result.isOk()).toBe(true);
const pricingResult = result.unwrap();
// And: The league should not be accepting applications
expect(pricingResult.acceptingApplications).toBe(false);
});
});
describe('GetEntitySponsorshipPricingUseCase - Error Handling', () => {
it('should return error when pricing is not configured', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has no sponsorship pricing configured
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: Should return an error
expect(result.isErr()).toBe(true);
const error = result.unwrapErr();
expect(error.code).toBe('PRICING_NOT_CONFIGURED');
});
});
describe('Sponsor League Detail Data Orchestration', () => {
it('should correctly retrieve sponsorship pricing with all tiers', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured with both main and secondary slots
const pricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: true,
customRequirements: 'Must have racing experience',
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: [
'Primary logo placement on all liveries',
'League page header banner',
'Race results page branding',
'Social media feature posts',
'Newsletter sponsor spot',
],
},
secondarySlots: {
price: { amount: 2000, currency: 'USD' },
benefits: [
'Secondary logo on liveries',
'League page sidebar placement',
'Race results mention',
'Social media mentions',
],
},
};
await sponsorshipPricingRepository.create(pricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called
const result = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The sponsorship pricing should be correctly retrieved
expect(result.isOk()).toBe(true);
const pricingResult = result.unwrap();
// And: The entity type should be correct
expect(pricingResult.entityType).toBe('league');
// And: The entity ID should be correct
expect(pricingResult.entityId).toBe(leagueId);
// And: The league should be accepting applications
expect(pricingResult.acceptingApplications).toBe(true);
// And: The custom requirements should be included
expect(pricingResult.customRequirements).toBe('Must have racing experience');
// And: The tiers should contain both main and secondary slots
expect(pricingResult.tiers).toHaveLength(2);
// And: The main slot should have correct price and benefits
expect(pricingResult.tiers[0].name).toBe('main');
expect(pricingResult.tiers[0].price.amount).toBe(10000);
expect(pricingResult.tiers[0].price.currency).toBe('USD');
expect(pricingResult.tiers[0].benefits).toHaveLength(5);
expect(pricingResult.tiers[0].benefits).toContain('Primary logo placement on all liveries');
// And: The secondary slot should have correct price and benefits
expect(pricingResult.tiers[1].name).toBe('secondary');
expect(pricingResult.tiers[1].price.amount).toBe(2000);
expect(pricingResult.tiers[1].price.currency).toBe('USD');
expect(pricingResult.tiers[1].benefits).toHaveLength(4);
expect(pricingResult.tiers[1].benefits).toContain('Secondary logo on liveries');
});
it('should correctly retrieve sponsorship pricing for different entity types', async () => {
// Given: A league exists with ID "league-123"
const leagueId = 'league-123';
// And: The league has sponsorship pricing configured
const leaguePricing = {
entityType: 'league' as const,
entityId: leagueId,
acceptingApplications: true,
mainSlot: {
price: { amount: 10000, currency: 'USD' },
benefits: ['Primary logo placement'],
},
};
await sponsorshipPricingRepository.create(leaguePricing);
// And: A team exists with ID "team-456"
const teamId = 'team-456';
// And: The team has sponsorship pricing configured
const teamPricing = {
entityType: 'team' as const,
entityId: teamId,
acceptingApplications: true,
mainSlot: {
price: { amount: 5000, currency: 'USD' },
benefits: ['Team logo placement'],
},
};
await sponsorshipPricingRepository.create(teamPricing);
// When: GetEntitySponsorshipPricingUseCase.execute() is called for league
const leagueResult = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'league',
entityId: leagueId,
});
// Then: The league pricing should be retrieved
expect(leagueResult.isOk()).toBe(true);
const leaguePricingResult = leagueResult.unwrap();
expect(leaguePricingResult.entityType).toBe('league');
expect(leaguePricingResult.entityId).toBe(leagueId);
expect(leaguePricingResult.tiers[0].price.amount).toBe(10000);
// When: GetEntitySponsorshipPricingUseCase.execute() is called for team
const teamResult = await getEntitySponsorshipPricingUseCase.execute({
entityType: 'team',
entityId: teamId,
});
// Then: The team pricing should be retrieved
expect(teamResult.isOk()).toBe(true);
const teamPricingResult = teamResult.unwrap();
expect(teamPricingResult.entityType).toBe('team');
expect(teamPricingResult.entityId).toBe(teamId);
expect(teamPricingResult.tiers[0].price.amount).toBe(5000);
});
});
});