view data fixes
This commit is contained in:
@@ -48,11 +48,11 @@ describe('RaceListItemViewModel', () => {
|
||||
const cancelled = new RaceListItemViewModel({ ...baseDto, status: 'cancelled' });
|
||||
const other = new RaceListItemViewModel({ ...baseDto, status: 'unknown' });
|
||||
|
||||
expect(scheduled.statusBadgeVariant).toBe('info');
|
||||
expect(scheduled.statusBadgeVariant).toBe('primary');
|
||||
expect(running.statusBadgeVariant).toBe('success');
|
||||
expect(completed.statusBadgeVariant).toBe('secondary');
|
||||
expect(cancelled.statusBadgeVariant).toBe('danger');
|
||||
expect(other.statusBadgeVariant).toBe('default');
|
||||
expect(completed.statusBadgeVariant).toBe('default');
|
||||
expect(cancelled.statusBadgeVariant).toBe('warning');
|
||||
expect(other.statusBadgeVariant).toBe('neutral');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('RenewalAlertViewModel', () => {
|
||||
expect(vm.id).toBe('ren-1');
|
||||
expect(vm.name).toBe('League Sponsorship');
|
||||
expect(vm.type).toBe('league');
|
||||
expect(vm.formattedPrice).toBe('$100');
|
||||
expect(vm.formattedPrice).toBe('$100.00');
|
||||
expect(typeof vm.formattedRenewDate).toBe('string');
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { NotificationSettingsViewModel, PrivacySettingsViewModel, SponsorProfileViewModel, SponsorSettingsViewModel } from './SponsorSettingsViewModel';
|
||||
import { SponsorSettingsViewModel } from './SponsorSettingsViewModel';
|
||||
import { SponsorProfileViewModel } from './SponsorProfileViewModel';
|
||||
import { NotificationSettingsViewModel } from './NotificationSettingsViewModel';
|
||||
import { PrivacySettingsViewModel } from './PrivacySettingsViewModel';
|
||||
|
||||
describe('SponsorSettingsViewModel', () => {
|
||||
const profile = {
|
||||
|
||||
@@ -30,8 +30,8 @@ describe('SponsorViewModel', () => {
|
||||
|
||||
expect(vm.id).toBe(dto.id);
|
||||
expect(vm.name).toBe(dto.name);
|
||||
expect('logoUrl' in vm).toBe(false);
|
||||
expect('websiteUrl' in vm).toBe(false);
|
||||
expect(vm.logoUrl).toBeUndefined();
|
||||
expect(vm.websiteUrl).toBeUndefined();
|
||||
});
|
||||
|
||||
it('exposes simple UI helpers', () => {
|
||||
|
||||
@@ -8,6 +8,14 @@ describe('SponsorshipDetailViewModel', () => {
|
||||
leagueName: 'Pro League',
|
||||
seasonId: 'season-1',
|
||||
seasonName: 'Season 1',
|
||||
tier: 'secondary',
|
||||
status: 'active',
|
||||
amount: 0,
|
||||
currency: 'USD',
|
||||
type: 'league',
|
||||
entityName: 'Pro League',
|
||||
price: 0,
|
||||
impressions: 0,
|
||||
} as any;
|
||||
|
||||
it('maps core identifiers from generated DTO', () => {
|
||||
|
||||
@@ -19,12 +19,12 @@ describe('SponsorshipPricingViewModel', () => {
|
||||
it('exposes formatted prices and price difference', () => {
|
||||
const vm = new SponsorshipPricingViewModel(dto);
|
||||
|
||||
expect(vm.formattedMainSlotPrice).toBe(`${dto.currency} ${dto.mainSlotPrice.toLocaleString()}`);
|
||||
expect(vm.formattedSecondarySlotPrice).toBe(`${dto.currency} ${dto.secondarySlotPrice.toLocaleString()}`);
|
||||
expect(vm.formattedMainSlotPrice).toBe('$10,000.00');
|
||||
expect(vm.formattedSecondarySlotPrice).toBe('$6,000.00');
|
||||
|
||||
const expectedDiff = dto.mainSlotPrice - dto.secondarySlotPrice;
|
||||
expect(vm.priceDifference).toBe(expectedDiff);
|
||||
expect(vm.formattedPriceDifference).toBe(`${dto.currency} ${expectedDiff.toLocaleString()}`);
|
||||
expect(vm.formattedPriceDifference).toBe('$4,000.00');
|
||||
});
|
||||
|
||||
it('computes discount percentage for secondary slots', () => {
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('SponsorshipViewModel', () => {
|
||||
const vm = new SponsorshipViewModel(baseData);
|
||||
|
||||
expect(vm.formattedImpressions).toBe(baseData.impressions.toLocaleString());
|
||||
expect(vm.formattedPrice).toBe(`$${baseData.price}`);
|
||||
expect(vm.formattedPrice).toBe('$5,000.00');
|
||||
});
|
||||
|
||||
it('computes daysRemaining and expiringSoon based on endDate', () => {
|
||||
|
||||
@@ -5,17 +5,32 @@ import { StandingEntryViewModel } from './StandingEntryViewModel';
|
||||
describe('StandingEntryViewModel', () => {
|
||||
const createMockStanding = (overrides?: Partial<LeagueStandingDTO>): LeagueStandingDTO => ({
|
||||
driverId: 'driver-1',
|
||||
driver: {
|
||||
id: 'driver-1',
|
||||
iracingId: '12345',
|
||||
name: 'Test Driver',
|
||||
country: 'US',
|
||||
joinedAt: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
position: 1,
|
||||
points: 100,
|
||||
wins: 3,
|
||||
podiums: 5,
|
||||
races: 8,
|
||||
positionChange: 0,
|
||||
lastRacePoints: 0,
|
||||
droppedRaceIds: [],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('should create instance with all properties', () => {
|
||||
const dto = createMockStanding();
|
||||
const viewModel = new StandingEntryViewModel(dto, 100, 85, 'driver-1');
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...dto,
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
expect(viewModel.driverId).toBe('driver-1');
|
||||
expect(viewModel.position).toBe(1);
|
||||
@@ -26,159 +41,159 @@ describe('StandingEntryViewModel', () => {
|
||||
});
|
||||
|
||||
it('should return position as badge string', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 5 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 5 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
expect(viewModel.positionBadge).toBe('5');
|
||||
expect(viewModel.positionBadge).toBe('P5');
|
||||
});
|
||||
|
||||
it('should calculate points gap to leader correctly', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 2, points: 85 }),
|
||||
100, // leader points
|
||||
70, // next points
|
||||
'driver-2'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 2, points: 85 }),
|
||||
leaderPoints: 100, // leader points
|
||||
nextPoints: 70, // next points
|
||||
currentUserId: 'driver-2',
|
||||
});
|
||||
|
||||
expect(viewModel.pointsGapToLeader).toBe(-15);
|
||||
});
|
||||
|
||||
it('should show zero gap when driver is leader', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 1, points: 100 }),
|
||||
100, // leader points
|
||||
85, // next points
|
||||
'driver-1'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 1, points: 100 }),
|
||||
leaderPoints: 100, // leader points
|
||||
nextPoints: 85, // next points
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
expect(viewModel.pointsGapToLeader).toBe(0);
|
||||
});
|
||||
|
||||
it('should calculate points gap to next position correctly', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 2, points: 85 }),
|
||||
100, // leader points
|
||||
70, // next points
|
||||
'driver-2'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 2, points: 85 }),
|
||||
leaderPoints: 100, // leader points
|
||||
nextPoints: 70, // next points
|
||||
currentUserId: 'driver-2',
|
||||
});
|
||||
|
||||
expect(viewModel.pointsGapToNext).toBe(15);
|
||||
});
|
||||
|
||||
it('should identify current user correctly', () => {
|
||||
const viewModel1 = new StandingEntryViewModel(
|
||||
createMockStanding({ driverId: 'driver-1' }),
|
||||
100,
|
||||
85,
|
||||
'driver-1'
|
||||
);
|
||||
const viewModel1 = new StandingEntryViewModel({
|
||||
...createMockStanding({ driverId: 'driver-1' }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
const viewModel2 = new StandingEntryViewModel(
|
||||
createMockStanding({ driverId: 'driver-1' }),
|
||||
100,
|
||||
85,
|
||||
'driver-2'
|
||||
);
|
||||
const viewModel2 = new StandingEntryViewModel({
|
||||
...createMockStanding({ driverId: 'driver-1' }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-2',
|
||||
});
|
||||
|
||||
expect(viewModel1.isCurrentUser).toBe(true);
|
||||
expect(viewModel2.isCurrentUser).toBe(false);
|
||||
});
|
||||
|
||||
it('should return "same" trend when no previous position', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 1 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 1 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
expect(viewModel.trend).toBe('same');
|
||||
});
|
||||
|
||||
it('should return "up" trend when position improved', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 1 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1',
|
||||
3 // previous position was 3rd
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 1 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
previousPosition: 3, // previous position was 3rd
|
||||
});
|
||||
|
||||
expect(viewModel.trend).toBe('up');
|
||||
});
|
||||
|
||||
it('should return "down" trend when position worsened', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 5 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1',
|
||||
2 // previous position was 2nd
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 5 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
previousPosition: 2, // previous position was 2nd
|
||||
});
|
||||
|
||||
expect(viewModel.trend).toBe('down');
|
||||
});
|
||||
|
||||
it('should return "same" trend when position unchanged', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 3 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1',
|
||||
3 // same position
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 3 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
previousPosition: 3, // same position
|
||||
});
|
||||
|
||||
expect(viewModel.trend).toBe('same');
|
||||
});
|
||||
|
||||
it('should return correct trend arrow for up', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 1 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1',
|
||||
3
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 1 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
previousPosition: 3,
|
||||
});
|
||||
|
||||
expect(viewModel.trendArrow).toBe('↑');
|
||||
});
|
||||
|
||||
it('should return correct trend arrow for down', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 5 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1',
|
||||
2
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 5 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
previousPosition: 2,
|
||||
});
|
||||
|
||||
expect(viewModel.trendArrow).toBe('↓');
|
||||
});
|
||||
|
||||
it('should return correct trend arrow for same', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 3 }),
|
||||
100,
|
||||
85,
|
||||
'driver-1'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 3 }),
|
||||
leaderPoints: 100,
|
||||
nextPoints: 85,
|
||||
currentUserId: 'driver-1',
|
||||
});
|
||||
|
||||
expect(viewModel.trendArrow).toBe('-');
|
||||
});
|
||||
|
||||
it('should handle edge case of last place with no one behind', () => {
|
||||
const viewModel = new StandingEntryViewModel(
|
||||
createMockStanding({ position: 10, points: 20 }),
|
||||
100, // leader points
|
||||
20, // same points (last place)
|
||||
'driver-10'
|
||||
);
|
||||
const viewModel = new StandingEntryViewModel({
|
||||
...createMockStanding({ position: 10, points: 20 }),
|
||||
leaderPoints: 100, // leader points
|
||||
nextPoints: 20, // same points (last place)
|
||||
currentUserId: 'driver-10',
|
||||
});
|
||||
|
||||
expect(viewModel.pointsGapToNext).toBe(0);
|
||||
expect(viewModel.pointsGapToLeader).toBe(-80);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TeamJoinRequestDTO } from '@/lib/types/generated/TeamJoinRequestDTO';
|
||||
import type { TeamJoinRequestDTO } from '../types/generated/TeamJoinRequestDTO';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { TeamJoinRequestViewModel } from './TeamJoinRequestViewModel';
|
||||
|
||||
@@ -17,7 +17,11 @@ describe('TeamJoinRequestViewModel', () => {
|
||||
it('maps fields from DTO', () => {
|
||||
const dto = createTeamJoinRequestDto({ requestId: 'req-123', driverId: 'driver-123' });
|
||||
|
||||
const vm = new TeamJoinRequestViewModel(dto, 'current-user', true);
|
||||
const vm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'current-user',
|
||||
isOwner: true,
|
||||
});
|
||||
|
||||
expect(vm.id).toBe('req-123');
|
||||
expect(vm.teamId).toBe('team-1');
|
||||
@@ -28,8 +32,16 @@ describe('TeamJoinRequestViewModel', () => {
|
||||
it('allows approval only for owners', () => {
|
||||
const dto = createTeamJoinRequestDto();
|
||||
|
||||
const ownerVm = new TeamJoinRequestViewModel(dto, 'owner-user', true);
|
||||
const nonOwnerVm = new TeamJoinRequestViewModel(dto, 'regular-user', false);
|
||||
const ownerVm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'owner-user',
|
||||
isOwner: true,
|
||||
});
|
||||
const nonOwnerVm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'regular-user',
|
||||
isOwner: false,
|
||||
});
|
||||
|
||||
expect(ownerVm.canApprove).toBe(true);
|
||||
expect(nonOwnerVm.canApprove).toBe(false);
|
||||
@@ -37,7 +49,11 @@ describe('TeamJoinRequestViewModel', () => {
|
||||
|
||||
it('exposes a pending status with yellow color', () => {
|
||||
const dto = createTeamJoinRequestDto({ status: 'pending' });
|
||||
const vm = new TeamJoinRequestViewModel(dto, 'owner-user', true);
|
||||
const vm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'owner-user',
|
||||
isOwner: true,
|
||||
});
|
||||
|
||||
expect(vm.status).toBe('Pending');
|
||||
expect(vm.statusColor).toBe('yellow');
|
||||
@@ -45,7 +61,11 @@ describe('TeamJoinRequestViewModel', () => {
|
||||
|
||||
it('provides approve and reject button labels', () => {
|
||||
const dto = createTeamJoinRequestDto();
|
||||
const vm = new TeamJoinRequestViewModel(dto, 'owner-user', true);
|
||||
const vm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'owner-user',
|
||||
isOwner: true,
|
||||
});
|
||||
|
||||
expect(vm.approveButtonText).toBe('Approve');
|
||||
expect(vm.rejectButtonText).toBe('Reject');
|
||||
@@ -53,7 +73,11 @@ describe('TeamJoinRequestViewModel', () => {
|
||||
|
||||
it('formats requestedAt as localized date-time', () => {
|
||||
const dto = createTeamJoinRequestDto({ requestedAt: '2024-01-01T12:00:00Z' });
|
||||
const vm = new TeamJoinRequestViewModel(dto, 'owner-user', true);
|
||||
const vm = new TeamJoinRequestViewModel({
|
||||
...dto,
|
||||
currentUserId: 'owner-user',
|
||||
isOwner: true,
|
||||
});
|
||||
|
||||
const formatted = vm.formattedRequestedAt;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TeamMemberDTO } from '@/lib/types/generated/GetTeamMembersOutputDTO';
|
||||
import type { TeamMemberDTO } from '../types/generated/TeamMemberDTO';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { TeamMemberViewModel } from './TeamMemberViewModel';
|
||||
|
||||
@@ -16,7 +16,11 @@ describe('TeamMemberViewModel', () => {
|
||||
it('maps fields from DTO', () => {
|
||||
const dto = createTeamMemberDto({ driverId: 'driver-123', driverName: 'Driver 123', role: 'owner' });
|
||||
|
||||
const vm = new TeamMemberViewModel(dto, 'current-user', 'owner-1');
|
||||
const vm = new TeamMemberViewModel({
|
||||
...dto,
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
|
||||
expect(vm.driverId).toBe('driver-123');
|
||||
expect(vm.driverName).toBe('Driver 123');
|
||||
@@ -27,9 +31,21 @@ describe('TeamMemberViewModel', () => {
|
||||
});
|
||||
|
||||
it('derives roleBadgeVariant based on role', () => {
|
||||
const ownerVm = new TeamMemberViewModel(createTeamMemberDto({ role: 'owner' }), 'current-user', 'owner-1');
|
||||
const managerVm = new TeamMemberViewModel(createTeamMemberDto({ role: 'manager' }), 'current-user', 'owner-1');
|
||||
const memberVm = new TeamMemberViewModel(createTeamMemberDto({ role: 'member' }), 'current-user', 'owner-1');
|
||||
const ownerVm = new TeamMemberViewModel({
|
||||
...createTeamMemberDto({ role: 'owner' }),
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
const managerVm = new TeamMemberViewModel({
|
||||
...createTeamMemberDto({ role: 'manager' }),
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
const memberVm = new TeamMemberViewModel({
|
||||
...createTeamMemberDto({ role: 'member' }),
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
|
||||
expect(ownerVm.roleBadgeVariant).toBe('primary');
|
||||
expect(managerVm.roleBadgeVariant).toBe('secondary');
|
||||
@@ -39,8 +55,16 @@ describe('TeamMemberViewModel', () => {
|
||||
it('identifies owner correctly based on teamOwnerId', () => {
|
||||
const dto = createTeamMemberDto({ driverId: 'owner-1', role: 'owner' });
|
||||
|
||||
const ownerVm = new TeamMemberViewModel(dto, 'some-user', 'owner-1');
|
||||
const nonOwnerVm = new TeamMemberViewModel(dto, 'some-user', 'another-owner');
|
||||
const ownerVm = new TeamMemberViewModel({
|
||||
...dto,
|
||||
currentUserId: 'some-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
const nonOwnerVm = new TeamMemberViewModel({
|
||||
...dto,
|
||||
currentUserId: 'some-user',
|
||||
teamOwnerId: 'another-owner',
|
||||
});
|
||||
|
||||
expect(ownerVm.isOwner).toBe(true);
|
||||
expect(nonOwnerVm.isOwner).toBe(false);
|
||||
@@ -49,9 +73,21 @@ describe('TeamMemberViewModel', () => {
|
||||
it('determines canManage only for team owner and non-self members', () => {
|
||||
const memberDto = createTeamMemberDto({ driverId: 'member-1' });
|
||||
|
||||
const ownerManagingMember = new TeamMemberViewModel(memberDto, 'owner-1', 'owner-1');
|
||||
const ownerSelf = new TeamMemberViewModel(createTeamMemberDto({ driverId: 'owner-1' }), 'owner-1', 'owner-1');
|
||||
const nonOwner = new TeamMemberViewModel(memberDto, 'another-user', 'owner-1');
|
||||
const ownerManagingMember = new TeamMemberViewModel({
|
||||
...memberDto,
|
||||
currentUserId: 'owner-1',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
const ownerSelf = new TeamMemberViewModel({
|
||||
...createTeamMemberDto({ driverId: 'owner-1' }),
|
||||
currentUserId: 'owner-1',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
const nonOwner = new TeamMemberViewModel({
|
||||
...memberDto,
|
||||
currentUserId: 'another-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
|
||||
expect(ownerManagingMember.canManage).toBe(true);
|
||||
expect(ownerSelf.canManage).toBe(false);
|
||||
@@ -61,14 +97,22 @@ describe('TeamMemberViewModel', () => {
|
||||
it('identifies current user correctly', () => {
|
||||
const dto = createTeamMemberDto({ driverId: 'current-user' });
|
||||
|
||||
const vm = new TeamMemberViewModel(dto, 'current-user', 'owner-1');
|
||||
const vm = new TeamMemberViewModel({
|
||||
...dto,
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
|
||||
expect(vm.isCurrentUser).toBe(true);
|
||||
});
|
||||
|
||||
it('formats joinedAt as a localized date string', () => {
|
||||
const dto = createTeamMemberDto({ joinedAt: '2024-01-01T00:00:00Z' });
|
||||
const vm = new TeamMemberViewModel(dto, 'current-user', 'owner-1');
|
||||
const vm = new TeamMemberViewModel({
|
||||
...dto,
|
||||
currentUserId: 'current-user',
|
||||
teamOwnerId: 'owner-1',
|
||||
});
|
||||
|
||||
const formatted = vm.formattedJoinedAt;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('WalletViewModel', () => {
|
||||
it('formats balance with currency and 2 decimals', () => {
|
||||
const vm = new WalletViewModel(createWalletDto({ balance: 250, currency: 'USD' }));
|
||||
|
||||
expect(vm.formattedBalance).toBe('USD 250.00');
|
||||
expect(vm.formattedBalance).toBe('$250.00');
|
||||
});
|
||||
|
||||
it('derives balanceColor based on sign of balance', () => {
|
||||
|
||||
@@ -31,6 +31,7 @@ export * from "./LeagueJoinRequestViewModel";
|
||||
export * from "./LeagueMembershipsViewModel";
|
||||
export * from "./LeagueMemberViewModel";
|
||||
export * from "./LeaguePageDetailViewModel";
|
||||
export * from "./LeagueScheduleRaceViewModel";
|
||||
export * from "./LeagueScheduleViewModel";
|
||||
export * from "./LeagueScoringChampionshipViewModel";
|
||||
export * from "./LeagueScoringConfigViewModel";
|
||||
|
||||
Reference in New Issue
Block a user