Files
gridpilot.gg/apps/website/lib/builders/view-data/ProfileViewDataBuilder.test.ts
Marc Mintel 108cfbcd65
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m55s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data tests
2026-01-22 18:22:08 +01:00

500 lines
14 KiB
TypeScript

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');
});
});
});