Files
gridpilot.gg/apps/website/lib/view-models/UserProfileViewModel.test.ts
2026-01-24 01:25:46 +01:00

81 lines
2.7 KiB
TypeScript

import { describe, expect, it } 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');
});
});