import { describe, it, expect } from 'vitest'; import { UserProfileViewModel } from './UserProfileViewModel'; describe('UserProfileViewModel', () => { it('maps required properties from the DTO', () => { const dto = { id: 'user-1', name: 'Roo Racer', }; const viewModel = new UserProfileViewModel(dto); expect(viewModel.id).toBe('user-1'); expect(viewModel.name).toBe('Roo Racer'); expect(viewModel.avatarUrl).toBeUndefined(); expect(viewModel.iracingId).toBeUndefined(); expect(viewModel.rating).toBeUndefined(); }); it('maps optional properties only when provided', () => { const dto = { id: 'user-2', name: 'Rated Driver', avatarUrl: 'https://example.com/avatar.jpg', iracingId: '12345', rating: 2734, }; const viewModel = new UserProfileViewModel(dto); expect(viewModel.avatarUrl).toBe('https://example.com/avatar.jpg'); expect(viewModel.iracingId).toBe('12345'); expect(viewModel.rating).toBe(2734); }); it('formats rating as whole-number string when present, or Unrated otherwise', () => { const unrated = new UserProfileViewModel({ id: 'user-1', name: 'Unrated Driver' }); const rated = new UserProfileViewModel({ id: 'user-2', name: 'Rated Driver', rating: 2734.56 }); expect(unrated.formattedRating).toBe('Unrated'); expect(rated.formattedRating).toBe('2735'); }); it('indicates whether an iRacing ID is present', () => { const withoutId = new UserProfileViewModel({ id: 'user-1', name: 'No ID' }); const withId = new UserProfileViewModel({ id: 'user-2', name: 'Has ID', iracingId: '67890' }); expect(withoutId.hasIracingId).toBe(false); expect(withId.hasIracingId).toBe(true); }); it('computes profile completeness based on available optional fields', () => { const base = new UserProfileViewModel({ id: 'user-1', name: 'Base User' }); const withAvatar = new UserProfileViewModel({ id: 'user-2', name: 'Avatar User', avatarUrl: 'url' }); const withAvatarAndId = new UserProfileViewModel({ id: 'user-3', name: 'Avatar + ID', avatarUrl: 'url', iracingId: '123', }); const withAll = new UserProfileViewModel({ id: 'user-4', name: 'Full Profile', avatarUrl: 'url', iracingId: '123', rating: 2000, }); expect(base.profileCompleteness).toBe(25); expect(withAvatar.profileCompleteness).toBe(50); expect(withAvatarAndId.profileCompleteness).toBe(75); expect(withAll.profileCompleteness).toBe(100); }); it('derives avatar initials from the name', () => { const viewModel = new UserProfileViewModel({ id: 'user-1', name: 'Roo Racer' }); expect(viewModel.avatarInitials).toBe('RR'); }); });