import { Prize } from './Prize'; import { Money } from '../../value-objects/Money'; import { RacingDomainValidationError, RacingDomainInvariantError } from '../../errors/RacingDomainError'; describe('Prize', () => { describe('create', () => { it('should create a prize with required fields', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); expect(prize.id.toString()).toBe('prize-1'); expect(prize.seasonId.toString()).toBe('season-1'); expect(prize.position.toNumber()).toBe(1); expect(prize.amount).toEqual(amount); expect(prize.driverId).toBeUndefined(); expect(prize.status.toString()).toBe('pending'); expect(prize.awardedAt).toBeUndefined(); expect(prize.paidAt).toBeUndefined(); expect(prize.description).toBeUndefined(); }); it('should create a prize with all fields', () => { const amount = Money.create(2000, 'USD'); const createdAt = new Date('2023-01-01'); const awardedAt = new Date('2023-01-02'); const paidAt = new Date('2023-01-03'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 2, amount, driverId: 'driver-1', status: 'paid', createdAt, awardedAt, paidAt, description: 'First place prize', }); expect(prize.id.toString()).toBe('prize-1'); expect(prize.seasonId.toString()).toBe('season-1'); expect(prize.position.toNumber()).toBe(2); expect(prize.amount).toEqual(amount); expect(prize.driverId!.toString()).toBe('driver-1'); expect(prize.status.toString()).toBe('paid'); expect(prize.createdAt).toEqual(createdAt); expect(prize.awardedAt).toEqual(awardedAt); expect(prize.paidAt).toEqual(paidAt); expect(prize.description).toBe('First place prize'); }); it('should throw error for invalid id', () => { const amount = Money.create(1000, 'USD'); expect(() => Prize.create({ id: '', seasonId: 'season-1', position: 1, amount, })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid seasonId', () => { const amount = Money.create(1000, 'USD'); expect(() => Prize.create({ id: 'prize-1', seasonId: '', position: 1, amount, })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid position', () => { const amount = Money.create(1000, 'USD'); expect(() => Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 0, amount, })).toThrow(RacingDomainValidationError); }); it('should throw error for non-integer position', () => { const amount = Money.create(1000, 'USD'); expect(() => Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1.5, amount, })).toThrow(RacingDomainValidationError); }); it('should throw error for zero amount', () => { const amount = Money.create(0, 'USD'); expect(() => Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, })).toThrow(RacingDomainValidationError); }); }); describe('awardTo', () => { it('should award prize to a driver', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); const awarded = prize.awardTo('driver-1'); expect(awarded.driverId!.toString()).toBe('driver-1'); expect(awarded.status.toString()).toBe('awarded'); expect(awarded.awardedAt).toBeInstanceOf(Date); }); it('should throw error for empty driverId', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); expect(() => prize.awardTo('')).toThrow(RacingDomainValidationError); }); it('should throw error if not pending', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'awarded', }); expect(() => prize.awardTo('driver-1')).toThrow(RacingDomainInvariantError); }); }); describe('markAsPaid', () => { it('should mark prize as paid', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, driverId: 'driver-1', status: 'awarded', }); const paid = prize.markAsPaid(); expect(paid.status.toString()).toBe('paid'); expect(paid.paidAt).toBeInstanceOf(Date); }); it('should throw error if not awarded', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); expect(() => prize.markAsPaid()).toThrow(RacingDomainInvariantError); }); it('should throw error if no driverId', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'awarded', }); expect(() => prize.markAsPaid()).toThrow(RacingDomainInvariantError); }); }); describe('cancel', () => { it('should cancel pending prize', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); const cancelled = prize.cancel(); expect(cancelled.status.toString()).toBe('cancelled'); }); it('should cancel awarded prize', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, driverId: 'driver-1', status: 'awarded', }); const cancelled = prize.cancel(); expect(cancelled.status.toString()).toBe('cancelled'); }); it('should throw error if paid', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, driverId: 'driver-1', status: 'paid', }); expect(() => prize.cancel()).toThrow(RacingDomainInvariantError); }); }); describe('isPending', () => { it('should return true for pending status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); expect(prize.isPending()).toBe(true); }); it('should return false for awarded status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'awarded', }); expect(prize.isPending()).toBe(false); }); }); describe('isAwarded', () => { it('should return true for awarded status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'awarded', }); expect(prize.isAwarded()).toBe(true); }); it('should return false for pending status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, }); expect(prize.isAwarded()).toBe(false); }); }); describe('isPaid', () => { it('should return true for paid status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'paid', }); expect(prize.isPaid()).toBe(true); }); it('should return false for awarded status', () => { const amount = Money.create(1000, 'USD'); const prize = Prize.create({ id: 'prize-1', seasonId: 'season-1', position: 1, amount, status: 'awarded', }); expect(prize.isPaid()).toBe(false); }); }); });