import { describe, it, expect, vi, Mocked } from 'vitest'; import { TeamService } from './TeamService'; import { TeamsApiClient } from '@/lib/api/teams/TeamsApiClient'; import { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel'; import { TeamDetailsViewModel } from '@/lib/view-models/TeamDetailsViewModel'; import { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel'; describe('TeamService', () => { let mockApiClient: Mocked; let service: TeamService; beforeEach(() => { mockApiClient = { getAll: vi.fn(), getDetails: vi.fn(), getMembers: vi.fn(), create: vi.fn(), update: vi.fn(), getDriverTeam: vi.fn(), } as Mocked; service = new TeamService(mockApiClient); }); describe('getAllTeams', () => { it('should call apiClient.getAll and return array of TeamSummaryViewModel', async () => { const mockDto = { teams: [ { id: 'team-1', name: 'Test Team', tag: 'TT', description: 'A test team', memberCount: 5, leagues: ['league-1'], specialization: 'endurance' as const, region: 'EU', languages: ['en'], }, ], totalCount: 1, }; mockApiClient.getAll.mockResolvedValue(mockDto); const result = await service.getAllTeams(); expect(mockApiClient.getAll).toHaveBeenCalled(); expect(result.isOk()).toBe(true); const teams = result.unwrap(); expect(teams).toHaveLength(1); expect(teams[0].id).toBe('team-1'); expect(teams[0].name).toBe('Test Team'); expect(teams[0].tag).toBe('TT'); }); it('should throw error when apiClient.getAll fails', async () => { const error = new Error('API call failed'); mockApiClient.getAll.mockRejectedValue(error); const result = await service.getAllTeams(); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); describe('getTeamDetails', () => { it('should call apiClient.getDetails and return TeamDetailsViewModel when data exists', async () => { const mockDto = { team: { id: 'team-1', name: 'Test Team', tag: 'TT', description: 'A test team', ownerId: 'owner-1', leagues: ['league-1'], createdAt: '2023-01-01T00:00:00Z', specialization: 'endurance', region: 'EU', languages: ['en'], }, membership: { role: 'member', joinedAt: '2023-01-01T00:00:00Z', isActive: true, }, canManage: false, }; mockApiClient.getDetails.mockResolvedValue(mockDto); const result = await service.getTeamDetails('team-1', 'user-1'); expect(mockApiClient.getDetails).toHaveBeenCalledWith('team-1'); expect(result.isOk()).toBe(true); const details = result.unwrap(); expect(details.team.id).toBe('team-1'); expect(details.team.name).toBe('Test Team'); expect(details.team.tag).toBe('TT'); }); it('should return null when apiClient.getDetails returns null', async () => { mockApiClient.getDetails.mockResolvedValue(null as any); const result = await service.getTeamDetails('team-1', 'user-1'); expect(mockApiClient.getDetails).toHaveBeenCalledWith('team-1'); expect(result.isErr()).toBe(true); expect(result.getError().type).toBe('notFound'); }); it('should throw error when apiClient.getDetails fails', async () => { const error = new Error('API call failed'); mockApiClient.getDetails.mockRejectedValue(error); const result = await service.getTeamDetails('team-1', 'user-1'); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); describe('getTeamMembers', () => { it('should call apiClient.getMembers and return array of TeamMemberViewModel', async () => { const mockDto = { members: [ { driverId: 'driver-1', driverName: 'Driver One', role: 'member' as const, joinedAt: '2023-01-01T00:00:00Z', isActive: true, avatarUrl: 'avatar.png', }, ], totalCount: 1, ownerCount: 0, managerCount: 0, memberCount: 1, }; mockApiClient.getMembers.mockResolvedValue(mockDto); const result = await service.getTeamMembers('team-1', 'user-1', 'owner-1'); expect(mockApiClient.getMembers).toHaveBeenCalledWith('team-1'); expect(result.isOk()).toBe(true); const members = result.unwrap(); expect(members).toHaveLength(1); expect(members[0]).toBeInstanceOf(TeamMemberViewModel); expect(members[0].driverId).toBe('driver-1'); expect(members[0].role).toBe('member'); }); it('should throw error when apiClient.getMembers fails', async () => { const error = new Error('API call failed'); mockApiClient.getMembers.mockRejectedValue(error); const result = await service.getTeamMembers('team-1', 'user-1', 'owner-1'); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); describe('createTeam', () => { it('should call apiClient.create and return the result', async () => { const input = { name: 'New Team', tag: 'NT', description: 'A new team' }; const mockOutput = { id: 'team-123', success: true }; mockApiClient.create.mockResolvedValue(mockOutput); const result = await service.createTeam(input); expect(mockApiClient.create).toHaveBeenCalledWith(input); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual(mockOutput); }); it('should throw error when apiClient.create fails', async () => { const input = { name: 'New Team', tag: 'NT' }; const error = new Error('API call failed'); mockApiClient.create.mockRejectedValue(error); const result = await service.createTeam(input); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); describe('updateTeam', () => { it('should call apiClient.update and return the result', async () => { const input = { name: 'Updated Team', description: 'Updated description' }; const mockOutput = { success: true }; mockApiClient.update.mockResolvedValue(mockOutput); const result = await service.updateTeam('team-1', input); expect(mockApiClient.update).toHaveBeenCalledWith('team-1', input); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual(mockOutput); }); it('should throw error when apiClient.update fails', async () => { const input = { name: 'Updated Team' }; const error = new Error('API call failed'); mockApiClient.update.mockRejectedValue(error); const result = await service.updateTeam('team-1', input); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); describe('getDriverTeam', () => { it('should call apiClient.getDriverTeam and return the result', async () => { const mockOutput = { team: { id: 'team-1', name: 'Test Team', tag: 'TT', description: 'A test team', ownerId: 'owner-1', leagues: [], specialization: 'endurance' as const, region: 'EU', languages: ['en'], }, membership: { role: 'member', joinedAt: '2023-01-01T00:00:00Z', isActive: true, }, isOwner: false, canManage: false, }; mockApiClient.getDriverTeam.mockResolvedValue(mockOutput); const result = await service.getDriverTeam('driver-1'); expect(mockApiClient.getDriverTeam).toHaveBeenCalledWith('driver-1'); expect(result.isOk()).toBe(true); const data = result.unwrap(); expect(data?.teamId).toBe('team-1'); expect(data?.teamName).toBe('Test Team'); expect(data?.role).toBe('member'); }); it('should return null when apiClient.getDriverTeam returns null', async () => { mockApiClient.getDriverTeam.mockResolvedValue(null); const result = await service.getDriverTeam('driver-1'); expect(mockApiClient.getDriverTeam).toHaveBeenCalledWith('driver-1'); expect(result.isOk()).toBe(true); expect(result.unwrap()).toBeNull(); }); it('should throw error when apiClient.getDriverTeam fails', async () => { const error = new Error('API call failed'); mockApiClient.getDriverTeam.mockRejectedValue(error); const result = await service.getDriverTeam('driver-1'); expect(result.isErr()).toBe(true); expect(result.getError().message).toBe('API call failed'); }); }); });