import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { LeagueDetailPageQuery } from '../../../../apps/website/lib/page-queries/LeagueDetailPageQuery'; import { WebsiteTestContext } from '../WebsiteTestContext'; // Mock data factories const createMockLeagueData = (leagueId: string = 'league-1') => ({ leagues: [ { id: leagueId, name: 'Test League', description: 'A test league', ownerId: 'driver-1', createdAt: new Date().toISOString(), usedSlots: 5, settings: { maxDrivers: 10, }, scoring: { gameId: 'game-1', gameName: 'Test Game', primaryChampionshipType: 'driver' as const, scoringPresetId: 'preset-1', scoringPresetName: 'Test Preset', dropPolicySummary: 'No drops', scoringPatternSummary: 'Standard scoring', }, }, ], }); const createMockMembershipsData = () => ({ members: [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'Driver 1', }, role: 'owner', joinedAt: new Date().toISOString(), }, ], }); const createMockRacesData = (leagueId: string = 'league-1') => ({ races: [ { id: 'race-1', track: 'Test Track', car: 'Test Car', scheduledAt: new Date().toISOString(), leagueId: leagueId, leagueName: 'Test League', status: 'scheduled', strengthOfField: 50, }, ], }); const createMockDriverData = () => ({ id: 'driver-1', name: 'Test Driver', avatarUrl: 'https://example.com/avatar.png', }); const createMockConfigData = () => ({ form: { scoring: { presetId: 'preset-1', }, }, }); describe('LeagueDetailPageQuery Integration', () => { const ctx = WebsiteTestContext.create(); beforeEach(() => { ctx.setup(); }); afterEach(() => { ctx.teardown(); }); describe('Happy Path', () => { it('should return valid league detail data when API returns success', async () => { // Arrange const leagueId = 'league-1'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); // For getAllWithCapacityAndScoring ctx.mockFetchResponse(createMockMembershipsData()); // For getMemberships ctx.mockFetchResponse(createMockRacesData(leagueId)); // For getPageData ctx.mockFetchResponse(createMockDriverData()); // For getDriver ctx.mockFetchResponse(createMockConfigData()); // For getLeagueConfig // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.leagueId).toBe(leagueId); expect(data.name).toBe('Test League'); expect(data.ownerSummary).toBeDefined(); expect(data.ownerSummary?.driverName).toBe('Test Driver'); }); it('should handle league without owner', async () => { // Arrange const leagueId = 'league-2'; const leagueData = createMockLeagueData(leagueId); leagueData.leagues[0].ownerId = ''; // No owner ctx.mockFetchResponse(leagueData); // getAllWithCapacityAndScoring ctx.mockFetchResponse(createMockMembershipsData()); // getMemberships ctx.mockFetchResponse(createMockRacesData(leagueId)); // getPageData ctx.mockFetchResponse(createMockConfigData()); // getLeagueConfig // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.ownerSummary).toBeNull(); }); it('should handle league with no races', async () => { // Arrange const leagueId = 'league-3'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); // getAllWithCapacityAndScoring ctx.mockFetchResponse(createMockMembershipsData()); // getMemberships ctx.mockFetchResponse({ races: [] }); // getPageData ctx.mockFetchResponse(createMockDriverData()); // getDriver ctx.mockFetchResponse(createMockConfigData()); // getLeagueConfig // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.info.racesCount).toBe(0); }); }); describe('Error Handling', () => { it('should handle 404 error when league not found', async () => { // Arrange const leagueId = 'non-existent-league'; ctx.mockFetchResponse({ leagues: [] }); // getAllWithCapacityAndScoring ctx.mockFetchResponse(createMockMembershipsData()); // getMemberships ctx.mockFetchResponse(createMockRacesData(leagueId)); // getPageData // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('notFound'); }); it('should handle 500 error when API server error', async () => { // Arrange ctx.mockFetchResponse({ message: 'Internal Server Error' }, 500, false); ctx.mockFetchResponse({ message: 'Internal Server Error' }, 500, false); ctx.mockFetchResponse({ message: 'Internal Server Error' }, 500, false); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('serverError'); }); it('should handle network error', async () => { // Arrange ctx.mockFetchError(new Error('Network error: Unable to reach the API server')); ctx.mockFetchError(new Error('Network error: Unable to reach the API server')); ctx.mockFetchError(new Error('Network error: Unable to reach the API server')); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('serverError'); }); it('should handle timeout error', async () => { // Arrange const timeoutError = new Error('Request timed out after 30 seconds'); timeoutError.name = 'AbortError'; ctx.mockFetchError(timeoutError); ctx.mockFetchError(timeoutError); ctx.mockFetchError(timeoutError); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('serverError'); }); it('should handle unauthorized error', async () => { // Arrange ctx.mockFetchResponse({ message: 'Unauthorized' }, 401, false); ctx.mockFetchResponse({ message: 'Unauthorized' }, 401, false); ctx.mockFetchResponse({ message: 'Unauthorized' }, 401, false); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('unauthorized'); }); it('should handle forbidden error', async () => { // Arrange ctx.mockFetchResponse({ message: 'Forbidden' }, 403, false); ctx.mockFetchResponse({ message: 'Forbidden' }, 403, false); ctx.mockFetchResponse({ message: 'Forbidden' }, 403, false); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('unauthorized'); }); }); describe('Missing Data', () => { it('should handle API returning partial data (missing memberships)', async () => { // Arrange const leagueId = 'league-1'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); ctx.mockFetchResponse(null); // Missing memberships ctx.mockFetchResponse(createMockRacesData(leagueId)); ctx.mockFetchResponse(createMockDriverData()); ctx.mockFetchResponse(createMockConfigData()); // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.info.membersCount).toBe(0); }); it('should handle API returning partial data (missing races)', async () => { // Arrange const leagueId = 'league-1'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(null); // Missing races ctx.mockFetchResponse(createMockDriverData()); ctx.mockFetchResponse(createMockConfigData()); // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.info.racesCount).toBe(0); }); it('should handle API returning partial data (missing scoring config)', async () => { // Arrange const leagueId = 'league-1'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(createMockRacesData(leagueId)); ctx.mockFetchResponse(createMockDriverData()); ctx.mockFetchResponse({ message: 'Config not found' }, 404, false); // Missing config // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.info.scoring).toBe('Standard'); }); it('should handle API returning partial data (missing owner)', async () => { // Arrange const leagueId = 'league-1'; ctx.mockFetchResponse(createMockLeagueData(leagueId)); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(createMockRacesData(leagueId)); ctx.mockFetchResponse(null); // Missing owner ctx.mockFetchResponse(createMockConfigData()); // Act const result = await LeagueDetailPageQuery.execute(leagueId); // Assert expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data.ownerSummary).toBeNull(); }); }); describe('Edge Cases', () => { it('should handle API returning empty leagues array', async () => { // Arrange ctx.mockFetchResponse({ leagues: [] }); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(createMockRacesData('league-1')); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('notFound'); }); it('should handle API returning null data', async () => { // Arrange ctx.mockFetchResponse(null); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(createMockRacesData('league-1')); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('notFound'); }); it('should handle API returning malformed data', async () => { // Arrange ctx.mockFetchResponse({ someOtherKey: [] }); ctx.mockFetchResponse(createMockMembershipsData()); ctx.mockFetchResponse(createMockRacesData('league-1')); // Act const result = await LeagueDetailPageQuery.execute('league-1'); // Assert expect(result.isErr()).toBe(true); expect(result.getError()).toBe('notFound'); }); }); });