import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { LeaguesPageQuery } from '../../../../apps/website/lib/page-queries/LeaguesPageQuery'; import { WebsiteTestContext } from '../WebsiteTestContext'; // Mock data factories const createMockLeaguesData = () => ({ leagues: [ { id: 'league-1', name: 'Test League 1', 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', }, }, { id: 'league-2', name: 'Test League 2', description: 'Another test league', ownerId: 'driver-2', createdAt: new Date().toISOString(), usedSlots: 15, settings: { maxDrivers: 20, }, scoring: { gameId: 'game-1', gameName: 'Test Game', primaryChampionshipType: 'driver' as const, scoringPresetId: 'preset-1', scoringPresetName: 'Test Preset', dropPolicySummary: 'No drops', scoringPatternSummary: 'Standard scoring', }, }, ], totalCount: 2, }); const createMockEmptyLeaguesData = () => ({ leagues: [], }); describe('LeaguesPageQuery Integration', () => { const ctx = WebsiteTestContext.create(); beforeEach(() => { ctx.setup(); }); afterEach(() => { ctx.teardown(); }); describe('Happy Path', () => { it('should return valid leagues data when API returns success', async () => { // Arrange const mockData = createMockLeaguesData(); ctx.mockFetchResponse(mockData); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isOk()).toBe(true); const viewData = result.unwrap(); expect(viewData).toBeDefined(); expect(viewData.leagues).toBeDefined(); expect(viewData.leagues.length).toBe(2); // Verify first league expect(viewData.leagues[0].id).toBe('league-1'); expect(viewData.leagues[0].name).toBe('Test League 1'); expect(viewData.leagues[0].maxDrivers).toBe(10); expect(viewData.leagues[0].usedDriverSlots).toBe(5); // Verify second league expect(viewData.leagues[1].id).toBe('league-2'); expect(viewData.leagues[1].name).toBe('Test League 2'); expect(viewData.leagues[1].maxDrivers).toBe(20); expect(viewData.leagues[1].usedDriverSlots).toBe(15); }); it('should handle single league correctly', async () => { // Arrange const mockData = { leagues: [ { id: 'single-league', name: 'Single League', description: 'Only one league', ownerId: 'driver-1', createdAt: new Date().toISOString(), usedSlots: 3, settings: { maxDrivers: 5, }, scoring: { gameId: 'game-1', gameName: 'Test Game', primaryChampionshipType: 'driver' as const, scoringPresetId: 'preset-1', scoringPresetName: 'Test Preset', dropPolicySummary: 'No drops', scoringPatternSummary: 'Standard scoring', }, }, ], }; ctx.mockFetchResponse(mockData); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isOk()).toBe(true); const viewData = result.unwrap(); expect(viewData.leagues.length).toBe(1); expect(viewData.leagues[0].id).toBe('single-league'); expect(viewData.leagues[0].name).toBe('Single League'); }); }); describe('Empty Results', () => { it('should handle empty leagues list from API', async () => { // Arrange const mockData = createMockEmptyLeaguesData(); ctx.mockFetchResponse(mockData); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isOk()).toBe(true); const viewData = result.unwrap(); expect(viewData).toBeDefined(); expect(viewData.leagues).toBeDefined(); expect(viewData.leagues.length).toBe(0); }); }); describe('Error Handling', () => { it('should handle 404 error when leagues endpoint not found', async () => { // Arrange ctx.mockFetchResponse({ message: 'Leagues not found' }, 404, false); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('notFound'); }); it('should handle 500 error when API server error', async () => { // Arrange ctx.mockFetchResponse({ message: 'Internal Server Error' }, 500, false); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('LEAGUES_FETCH_FAILED'); }); it('should handle network error', async () => { // Arrange ctx.mockFetchError(new Error('Network error: Unable to reach the API server')); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('LEAGUES_FETCH_FAILED'); }); it('should handle timeout error', async () => { // Arrange const timeoutError = new Error('Request timed out after 30 seconds'); timeoutError.name = 'AbortError'; ctx.mockFetchError(timeoutError); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('LEAGUES_FETCH_FAILED'); }); it('should handle unauthorized error (redirect)', async () => { // Arrange ctx.mockFetchResponse({ message: 'Unauthorized' }, 401, false); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('redirect'); }); it('should handle forbidden error (redirect)', async () => { // Arrange ctx.mockFetchResponse({ message: 'Forbidden' }, 403, false); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('redirect'); }); it('should handle unknown error type', async () => { // Arrange ctx.mockFetchResponse({ message: 'Unknown error' }, 999, false); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('LEAGUES_FETCH_FAILED'); }); }); describe('Edge Cases', () => { it('should handle API returning null or undefined data', async () => { // Arrange ctx.mockFetchResponse({ leagues: null }); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('UNKNOWN_ERROR'); }); it('should handle API returning malformed data', async () => { // Arrange const mockData = { // Missing 'leagues' property someOtherProperty: 'value', }; ctx.mockFetchResponse(mockData); // Act const result = await LeaguesPageQuery.execute(); // Assert expect(result.isErr()).toBe(true); const error = result.getError(); expect(error).toBe('UNKNOWN_ERROR'); }); it('should handle API returning leagues with missing required fields', async () => { // Arrange const mockData = { leagues: [ { id: 'league-1', name: 'Test League', // Missing other required fields settings: { maxDrivers: 10 }, usedSlots: 5, createdAt: new Date().toISOString(), }, ], }; ctx.mockFetchResponse(mockData); // Act const result = await LeaguesPageQuery.execute(); // Assert // Should still succeed - the builder should handle partial data expect(result.isOk()).toBe(true); const viewData = result.unwrap(); expect(viewData.leagues.length).toBe(1); }); }); });