/** * Integration Test: Teams List Use Case Orchestration * * Tests the orchestration logic of teams list-related Use Cases: * - GetAllTeamsUseCase: Retrieves list of teams with enrichment (member count, stats) * - 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 { InMemoryTeamRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTeamRepository'; import { InMemoryTeamMembershipRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository'; import { InMemoryTeamStatsRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTeamStatsRepository'; import { GetAllTeamsUseCase } from '../../../core/racing/application/use-cases/GetAllTeamsUseCase'; import { Team } from '../../../core/racing/domain/entities/Team'; import { Logger } from '../../../core/shared/domain/Logger'; describe('Teams List Use Case Orchestration', () => { let teamRepository: InMemoryTeamRepository; let membershipRepository: InMemoryTeamMembershipRepository; let statsRepository: InMemoryTeamStatsRepository; let getAllTeamsUseCase: GetAllTeamsUseCase; let mockLogger: Logger; beforeAll(() => { mockLogger = { info: () => {}, debug: () => {}, warn: () => {}, error: () => {}, } as unknown as Logger; teamRepository = new InMemoryTeamRepository(mockLogger); membershipRepository = new InMemoryTeamMembershipRepository(mockLogger); statsRepository = new InMemoryTeamStatsRepository(); getAllTeamsUseCase = new GetAllTeamsUseCase(teamRepository, membershipRepository, statsRepository, mockLogger); }); beforeEach(() => { teamRepository.clear(); membershipRepository.clear(); statsRepository.clear(); }); describe('GetAllTeamsUseCase - Success Path', () => { it('should retrieve complete teams list with all teams and enrichment', async () => { // Scenario: Teams list with multiple teams // Given: Multiple teams exist const team1 = Team.create({ id: 't1', name: 'Team 1', tag: 'T1', description: 'Desc 1', ownerId: 'o1', leagues: [] }); const team2 = Team.create({ id: 't2', name: 'Team 2', tag: 'T2', description: 'Desc 2', ownerId: 'o2', leagues: [] }); await teamRepository.create(team1); await teamRepository.create(team2); // And: Teams have members await membershipRepository.saveMembership({ teamId: 't1', driverId: 'd1', role: 'owner', status: 'active', joinedAt: new Date() }); await membershipRepository.saveMembership({ teamId: 't1', driverId: 'd2', role: 'driver', status: 'active', joinedAt: new Date() }); await membershipRepository.saveMembership({ teamId: 't2', driverId: 'd3', role: 'owner', status: 'active', joinedAt: new Date() }); // And: Teams have stats await statsRepository.saveTeamStats('t1', { totalWins: 5, totalRaces: 20, rating: 1500, performanceLevel: 'intermediate', specialization: 'sprint', region: 'EU', languages: ['en'], isRecruiting: true }); // When: GetAllTeamsUseCase.execute() is called const result = await getAllTeamsUseCase.execute({}); // Then: The result should contain all teams with enrichment expect(result.isOk()).toBe(true); const { teams, totalCount } = result.unwrap(); expect(totalCount).toBe(2); const enriched1 = teams.find(t => t.team.id.toString() === 't1'); expect(enriched1).toBeDefined(); expect(enriched1?.memberCount).toBe(2); expect(enriched1?.totalWins).toBe(5); expect(enriched1?.rating).toBe(1500); const enriched2 = teams.find(t => t.team.id.toString() === 't2'); expect(enriched2).toBeDefined(); expect(enriched2?.memberCount).toBe(1); expect(enriched2?.totalWins).toBe(0); // Default value }); it('should handle empty teams list', async () => { // Scenario: No teams exist // When: GetAllTeamsUseCase.execute() is called const result = await getAllTeamsUseCase.execute({}); // Then: The result should be empty expect(result.isOk()).toBe(true); const { teams, totalCount } = result.unwrap(); expect(totalCount).toBe(0); expect(teams).toHaveLength(0); }); }); });