view models
This commit is contained in:
@@ -2,113 +2,52 @@ import { describe, it, expect } from 'vitest';
|
||||
import { ProtestViewModel } from './ProtestViewModel';
|
||||
import type { ProtestDTO } from '../types/generated/ProtestDTO';
|
||||
|
||||
const createProtestDto = (overrides: Partial<ProtestDTO> = {}): ProtestDTO => ({
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
protestingDriverId: 'driver-111',
|
||||
accusedDriverId: 'driver-222',
|
||||
description: 'Unsafe driving in turn 3',
|
||||
submittedAt: '2023-01-15T10:30:00Z',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe('ProtestViewModel', () => {
|
||||
it('should create instance with all properties', () => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Unsafe driving in turn 3',
|
||||
status: 'pending',
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
it('maps core fields from ProtestDTO', () => {
|
||||
const dto: ProtestDTO = createProtestDto();
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
|
||||
expect(viewModel.id).toBe('protest-123');
|
||||
expect(viewModel.raceId).toBe('race-456');
|
||||
expect(viewModel.complainantId).toBe('driver-111');
|
||||
expect(viewModel.defendantId).toBe('driver-222');
|
||||
expect(viewModel.protestingDriverId).toBe('driver-111');
|
||||
expect(viewModel.accusedDriverId).toBe('driver-222');
|
||||
expect(viewModel.description).toBe('Unsafe driving in turn 3');
|
||||
expect(viewModel.submittedAt).toBe('2023-01-15T10:30:00Z');
|
||||
});
|
||||
|
||||
it('defaults status and review fields for new protests', () => {
|
||||
const viewModel = new ProtestViewModel(createProtestDto());
|
||||
|
||||
expect(viewModel.status).toBe('pending');
|
||||
expect(viewModel.createdAt).toBe('2023-01-15T10:30:00Z');
|
||||
expect(viewModel.reviewedAt).toBeUndefined();
|
||||
expect(viewModel.decisionNotes).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should format createdAt as locale string', () => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Test',
|
||||
status: 'pending',
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
it('formats submittedAt as a locale string', () => {
|
||||
const viewModel = new ProtestViewModel(createProtestDto({
|
||||
submittedAt: '2023-01-15T10:30:00Z',
|
||||
}));
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
const formatted = viewModel.formattedCreatedAt;
|
||||
const formatted = viewModel.formattedSubmittedAt;
|
||||
|
||||
expect(formatted).toContain('2023');
|
||||
expect(formatted).toContain('1/15');
|
||||
expect(typeof formatted).toBe('string');
|
||||
expect(formatted.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should capitalize status for display', () => {
|
||||
const statuses = ['pending', 'approved', 'rejected', 'reviewing'];
|
||||
|
||||
statuses.forEach(status => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Test',
|
||||
status,
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
const expected = status.charAt(0).toUpperCase() + status.slice(1);
|
||||
|
||||
expect(viewModel.statusDisplay).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle already capitalized status', () => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Test',
|
||||
status: 'Pending',
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
it('exposes a fixed status display label for pending protests', () => {
|
||||
const viewModel = new ProtestViewModel(createProtestDto());
|
||||
|
||||
expect(viewModel.statusDisplay).toBe('Pending');
|
||||
});
|
||||
|
||||
it('should handle single character status', () => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Test',
|
||||
status: 'p',
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
|
||||
expect(viewModel.statusDisplay).toBe('P');
|
||||
});
|
||||
|
||||
it('should handle empty status', () => {
|
||||
const dto: ProtestDTO = {
|
||||
id: 'protest-123',
|
||||
raceId: 'race-456',
|
||||
complainantId: 'driver-111',
|
||||
defendantId: 'driver-222',
|
||||
description: 'Test',
|
||||
status: '',
|
||||
createdAt: '2023-01-15T10:30:00Z',
|
||||
};
|
||||
|
||||
const viewModel = new ProtestViewModel(dto);
|
||||
|
||||
expect(viewModel.statusDisplay).toBe('');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user