refactor
This commit is contained in:
226
core/racing/domain/entities/Protest.test.ts
Normal file
226
core/racing/domain/entities/Protest.test.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
import { Protest } from './Protest';
|
||||
import { RacingDomainValidationError, RacingDomainInvariantError } from '../errors/RacingDomainError';
|
||||
|
||||
describe('Protest', () => {
|
||||
describe('create', () => {
|
||||
it('should create a protest with required fields', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
|
||||
expect(protest.id).toBe('protest-1');
|
||||
expect(protest.raceId).toBe('race-1');
|
||||
expect(protest.protestingDriverId).toBe('driver-1');
|
||||
expect(protest.accusedDriverId).toBe('driver-2');
|
||||
expect(protest.incident.lap.toNumber()).toBe(5);
|
||||
expect(protest.incident.description.toString()).toBe('Unsafe overtake');
|
||||
expect(protest.status.toString()).toBe('pending');
|
||||
expect(protest.filedAt).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should create a protest with all fields', () => {
|
||||
const filedAt = new Date('2023-01-01');
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake', timeInRace: 120.5 },
|
||||
comment: 'He cut me off',
|
||||
proofVideoUrl: 'https://example.com/video.mp4',
|
||||
status: 'under_review',
|
||||
reviewedBy: 'steward-1',
|
||||
decisionNotes: 'Reviewed and upheld',
|
||||
filedAt,
|
||||
reviewedAt: new Date('2023-01-02'),
|
||||
defense: { statement: 'It was a racing incident', videoUrl: 'https://example.com/defense.mp4', submittedAt: new Date('2023-01-01T12:00:00Z') },
|
||||
defenseRequestedAt: new Date('2023-01-01T10:00:00Z'),
|
||||
defenseRequestedBy: 'steward-1',
|
||||
});
|
||||
|
||||
expect(protest.id).toBe('protest-1');
|
||||
expect(protest.comment).toBe('He cut me off');
|
||||
expect(protest.proofVideoUrl).toBe('https://example.com/video.mp4');
|
||||
expect(protest.status.toString()).toBe('under_review');
|
||||
expect(protest.reviewedBy).toBe('steward-1');
|
||||
expect(protest.decisionNotes).toBe('Reviewed and upheld');
|
||||
expect(protest.filedAt).toEqual(filedAt);
|
||||
expect(protest.defense).toBeDefined();
|
||||
expect(protest.defenseRequestedAt).toBeInstanceOf(Date);
|
||||
expect(protest.defenseRequestedBy).toBe('steward-1');
|
||||
});
|
||||
|
||||
it('should throw error for invalid id', () => {
|
||||
expect(() => Protest.create({
|
||||
id: '',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
})).toThrow(RacingDomainValidationError);
|
||||
});
|
||||
|
||||
it('should throw error for invalid lap', () => {
|
||||
expect(() => Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: -1, description: 'Unsafe overtake' },
|
||||
})).toThrow(RacingDomainValidationError);
|
||||
});
|
||||
|
||||
it('should throw error for empty description', () => {
|
||||
expect(() => Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: '' },
|
||||
})).toThrow(RacingDomainValidationError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('requestDefense', () => {
|
||||
it('should request defense for pending protest', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
const updated = protest.requestDefense('steward-1');
|
||||
expect(updated.status.toString()).toBe('awaiting_defense');
|
||||
expect(updated.defenseRequestedAt).toBeInstanceOf(Date);
|
||||
expect(updated.defenseRequestedBy).toBe('steward-1');
|
||||
});
|
||||
|
||||
it('should throw error if not pending', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
status: 'upheld',
|
||||
});
|
||||
expect(() => protest.requestDefense('steward-1')).toThrow(RacingDomainInvariantError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('submitDefense', () => {
|
||||
it('should submit defense for awaiting defense protest', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
status: 'awaiting_defense',
|
||||
});
|
||||
const updated = protest.submitDefense('It was a racing incident');
|
||||
expect(updated.status.toString()).toBe('under_review');
|
||||
expect(updated.defense).toBeDefined();
|
||||
if (updated.defense) {
|
||||
expect(updated.defense.statement.toString()).toBe('It was a racing incident');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw error if not awaiting defense', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
expect(() => protest.submitDefense('Statement')).toThrow(RacingDomainInvariantError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('uphold', () => {
|
||||
it('should uphold pending protest', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
const updated = protest.uphold('steward-1', 'Penalty applied');
|
||||
expect(updated.status.toString()).toBe('upheld');
|
||||
expect(updated.reviewedBy).toBe('steward-1');
|
||||
expect(updated.decisionNotes).toBe('Penalty applied');
|
||||
expect(updated.reviewedAt).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should throw error if resolved', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
status: 'upheld',
|
||||
});
|
||||
expect(() => protest.uphold('steward-1', 'Notes')).toThrow(RacingDomainInvariantError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('withdraw', () => {
|
||||
it('should withdraw pending protest', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
const updated = protest.withdraw();
|
||||
expect(updated.status.toString()).toBe('withdrawn');
|
||||
expect(updated.reviewedAt).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should throw error if resolved', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
status: 'upheld',
|
||||
});
|
||||
expect(() => protest.withdraw()).toThrow(RacingDomainInvariantError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPending', () => {
|
||||
it('should return true for pending status', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
});
|
||||
expect(protest.isPending()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for upheld status', () => {
|
||||
const protest = Protest.create({
|
||||
id: 'protest-1',
|
||||
raceId: 'race-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Unsafe overtake' },
|
||||
status: 'upheld',
|
||||
});
|
||||
expect(protest.isPending()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user