import { describe, it, expect } from 'vitest'; import { ProfileViewDataBuilder } from './ProfileViewDataBuilder'; import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO'; describe('ProfileViewDataBuilder', () => { describe('happy paths', () => { it('should transform GetDriverProfileOutputDTO to ProfileViewData correctly', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: 'Test bio', iracingId: 12345, joinedAt: '2024-01-01', globalRank: 100, }, stats: { totalRaces: 50, wins: 10, podiums: 20, dnfs: 5, avgFinish: 5.5, bestFinish: 1, worstFinish: 20, finishRate: 90, winRate: 20, podiumRate: 40, percentile: 95, rating: 1500, consistency: 85, overallRank: 100, }, finishDistribution: { totalRaces: 50, wins: 10, podiums: 20, topTen: 30, dnfs: 5, other: 15, }, teamMemberships: [ { teamId: 'team-1', teamName: 'Test Team', teamTag: 'TT', role: 'driver', joinedAt: '2024-01-01', isCurrent: true, }, ], socialSummary: { friendsCount: 10, friends: [ { id: 'friend-1', name: 'Friend 1', country: 'US', avatarUrl: 'avatar-url', }, ], }, extendedProfile: { socialHandles: [ { platform: 'twitter', handle: '@test', url: 'https://twitter.com/test', }, ], achievements: [ { id: 'ach-1', title: 'Achievement', description: 'Test achievement', icon: 'trophy', rarity: 'rare', earnedAt: '2024-01-01', }, ], racingStyle: 'Aggressive', favoriteTrack: 'Test Track', favoriteCar: 'Test Car', timezone: 'UTC', availableHours: 10, lookingForTeam: true, openToRequests: true, }, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.id).toBe('driver-123'); expect(result.driver.name).toBe('Test Driver'); expect(result.driver.countryCode).toBe('US'); expect(result.driver.bio).toBe('Test bio'); expect(result.driver.iracingId).toBe('12345'); expect(result.stats).not.toBeNull(); expect(result.stats?.ratingLabel).toBe('1500'); expect(result.teamMemberships).toHaveLength(1); expect(result.extendedProfile).not.toBeNull(); expect(result.extendedProfile?.socialHandles).toHaveLength(1); expect(result.extendedProfile?.achievements).toHaveLength(1); }); it('should handle null driver (no profile)', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: null, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.id).toBe(''); expect(result.driver.name).toBe(''); expect(result.driver.countryCode).toBe(''); expect(result.driver.bio).toBeNull(); expect(result.driver.iracingId).toBeNull(); expect(result.stats).toBeNull(); expect(result.teamMemberships).toHaveLength(0); expect(result.extendedProfile).toBeNull(); }); it('should handle null stats', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.stats).toBeNull(); }); }); describe('data transformation', () => { it('should preserve all DTO fields in the output', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: 'Test bio', iracingId: 12345, joinedAt: '2024-01-01', globalRank: 100, }, stats: { totalRaces: 50, wins: 10, podiums: 20, dnfs: 5, avgFinish: 5.5, bestFinish: 1, worstFinish: 20, finishRate: 90, winRate: 20, podiumRate: 40, percentile: 95, rating: 1500, consistency: 85, overallRank: 100, }, finishDistribution: { totalRaces: 50, wins: 10, podiums: 20, topTen: 30, dnfs: 5, other: 15, }, teamMemberships: [ { teamId: 'team-1', teamName: 'Test Team', teamTag: 'TT', role: 'driver', joinedAt: '2024-01-01', isCurrent: true, }, ], socialSummary: { friendsCount: 10, friends: [ { id: 'friend-1', name: 'Friend 1', country: 'US', avatarUrl: 'avatar-url', }, ], }, extendedProfile: { socialHandles: [ { platform: 'twitter', handle: '@test', url: 'https://twitter.com/test', }, ], achievements: [ { id: 'ach-1', title: 'Achievement', description: 'Test achievement', icon: 'trophy', rarity: 'rare', earnedAt: '2024-01-01', }, ], racingStyle: 'Aggressive', favoriteTrack: 'Test Track', favoriteCar: 'Test Car', timezone: 'UTC', availableHours: 10, lookingForTeam: true, openToRequests: true, }, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.id).toBe(profileDto.currentDriver?.id); expect(result.driver.name).toBe(profileDto.currentDriver?.name); expect(result.driver.countryCode).toBe(profileDto.currentDriver?.country); expect(result.driver.bio).toBe(profileDto.currentDriver?.bio); expect(result.driver.iracingId).toBe(String(profileDto.currentDriver?.iracingId)); expect(result.stats?.totalRacesLabel).toBe('50'); expect(result.stats?.winsLabel).toBe('10'); expect(result.teamMemberships).toHaveLength(1); expect(result.extendedProfile?.socialHandles).toHaveLength(1); expect(result.extendedProfile?.achievements).toHaveLength(1); }); it('should not modify the input DTO', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: 'Test bio', iracingId: 12345, joinedAt: '2024-01-01', globalRank: 100, }, stats: { totalRaces: 50, wins: 10, podiums: 20, dnfs: 5, avgFinish: 5.5, bestFinish: 1, worstFinish: 20, finishRate: 90, winRate: 20, podiumRate: 40, percentile: 95, rating: 1500, consistency: 85, overallRank: 100, }, finishDistribution: { totalRaces: 50, wins: 10, podiums: 20, topTen: 30, dnfs: 5, other: 15, }, teamMemberships: [ { teamId: 'team-1', teamName: 'Test Team', teamTag: 'TT', role: 'driver', joinedAt: '2024-01-01', isCurrent: true, }, ], socialSummary: { friendsCount: 10, friends: [ { id: 'friend-1', name: 'Friend 1', country: 'US', avatarUrl: 'avatar-url', }, ], }, extendedProfile: { socialHandles: [ { platform: 'twitter', handle: '@test', url: 'https://twitter.com/test', }, ], achievements: [ { id: 'ach-1', title: 'Achievement', description: 'Test achievement', icon: 'trophy', rarity: 'rare', earnedAt: '2024-01-01', }, ], racingStyle: 'Aggressive', favoriteTrack: 'Test Track', favoriteCar: 'Test Car', timezone: 'UTC', availableHours: 10, lookingForTeam: true, openToRequests: true, }, }; const originalDto = { ...profileDto }; ProfileViewDataBuilder.build(profileDto); expect(profileDto).toEqual(originalDto); }); }); describe('edge cases', () => { it('should handle driver without avatar', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: null, bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.avatarUrl).toContain('default'); }); it('should handle driver without iracingId', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.iracingId).toBeNull(); }); it('should handle driver without global rank', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.driver.globalRankLabel).toBe('—'); }); it('should handle empty team memberships', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: null, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.teamMemberships).toHaveLength(0); }); it('should handle empty friends list', () => { const profileDto: GetDriverProfileOutputDTO = { currentDriver: { id: 'driver-123', name: 'Test Driver', country: 'US', avatarUrl: 'avatar-url', bio: null, iracingId: null, joinedAt: '2024-01-01', globalRank: null, }, stats: null, finishDistribution: null, teamMemberships: [], socialSummary: { friendsCount: 0, friends: [], }, extendedProfile: { socialHandles: [], achievements: [], racingStyle: null, favoriteTrack: null, favoriteCar: null, timezone: null, availableHours: null, lookingForTeam: false, openToRequests: false, }, }; const result = ProfileViewDataBuilder.build(profileDto); expect(result.extendedProfile?.friends).toHaveLength(0); expect(result.extendedProfile?.friendsCountLabel).toBe('0'); }); }); });