import { Payment, PaymentStatus, PaymentType, PayerType, } from '@core/payments/domain/entities/Payment'; import { describe, expect, it } from 'vitest'; describe('payments/domain/entities/Payment', () => { describe('PaymentType enum', () => { it('should have correct payment type values', () => { expect(PaymentType.SPONSORSHIP).toBe('sponsorship'); expect(PaymentType.MEMBERSHIP_FEE).toBe('membership_fee'); }); }); describe('PayerType enum', () => { it('should have correct payer type values', () => { expect(PayerType.SPONSOR).toBe('sponsor'); expect(PayerType.DRIVER).toBe('driver'); }); }); describe('PaymentStatus enum', () => { it('should have correct status values', () => { expect(PaymentStatus.PENDING).toBe('pending'); expect(PaymentStatus.COMPLETED).toBe('completed'); expect(PaymentStatus.FAILED).toBe('failed'); expect(PaymentStatus.REFUNDED).toBe('refunded'); }); }); describe('Payment interface', () => { it('should have all required properties', () => { const payment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; expect(payment.id).toBe('payment-123'); expect(payment.type).toBe(PaymentType.SPONSORSHIP); expect(payment.amount).toBe(1000); expect(payment.platformFee).toBe(50); expect(payment.netAmount).toBe(950); expect(payment.payerId).toBe('sponsor-456'); expect(payment.payerType).toBe(PayerType.SPONSOR); expect(payment.leagueId).toBe('league-789'); expect(payment.status).toBe(PaymentStatus.PENDING); expect(payment.createdAt).toEqual(new Date('2024-01-01')); }); it('should support optional seasonId property', () => { const payment: Payment = { id: 'payment-123', type: PaymentType.MEMBERSHIP_FEE, amount: 100, platformFee: 5, netAmount: 95, payerId: 'driver-456', payerType: PayerType.DRIVER, leagueId: 'league-789', seasonId: 'season-999', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), completedAt: new Date('2024-01-15'), }; expect(payment.seasonId).toBe('season-999'); expect(payment.completedAt).toEqual(new Date('2024-01-15')); }); it('should support optional completedAt property', () => { const payment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), completedAt: new Date('2024-01-15'), }; expect(payment.completedAt).toEqual(new Date('2024-01-15')); }); }); describe('Payment.rehydrate', () => { it('should rehydrate a Payment from props', () => { const props: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; const rehydrated = Payment.rehydrate(props); expect(rehydrated).toEqual(props); expect(rehydrated.id).toBe('payment-123'); expect(rehydrated.type).toBe(PaymentType.SPONSORSHIP); expect(rehydrated.amount).toBe(1000); expect(rehydrated.platformFee).toBe(50); expect(rehydrated.netAmount).toBe(950); expect(rehydrated.payerId).toBe('sponsor-456'); expect(rehydrated.payerType).toBe(PayerType.SPONSOR); expect(rehydrated.leagueId).toBe('league-789'); expect(rehydrated.status).toBe(PaymentStatus.PENDING); expect(rehydrated.createdAt).toEqual(new Date('2024-01-01')); }); it('should preserve optional seasonId when rehydrating', () => { const props: Payment = { id: 'payment-123', type: PaymentType.MEMBERSHIP_FEE, amount: 100, platformFee: 5, netAmount: 95, payerId: 'driver-456', payerType: PayerType.DRIVER, leagueId: 'league-789', seasonId: 'season-999', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), completedAt: new Date('2024-01-15'), }; const rehydrated = Payment.rehydrate(props); expect(rehydrated.seasonId).toBe('season-999'); expect(rehydrated.completedAt).toEqual(new Date('2024-01-15')); }); }); describe('Business rules and invariants', () => { it('should calculate netAmount correctly (amount - platformFee)', () => { const payment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; expect(payment.netAmount).toBe(payment.amount - payment.platformFee); }); it('should support different payment types', () => { const sponsorshipPayment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; const membershipFeePayment: Payment = { id: 'payment-124', type: PaymentType.MEMBERSHIP_FEE, amount: 100, platformFee: 5, netAmount: 95, payerId: 'driver-456', payerType: PayerType.DRIVER, leagueId: 'league-789', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), }; expect(sponsorshipPayment.type).toBe(PaymentType.SPONSORSHIP); expect(membershipFeePayment.type).toBe(PaymentType.MEMBERSHIP_FEE); }); it('should support different payer types', () => { const sponsorPayment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; const driverPayment: Payment = { id: 'payment-124', type: PaymentType.MEMBERSHIP_FEE, amount: 100, platformFee: 5, netAmount: 95, payerId: 'driver-456', payerType: PayerType.DRIVER, leagueId: 'league-789', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), }; expect(sponsorPayment.payerType).toBe(PayerType.SPONSOR); expect(driverPayment.payerType).toBe(PayerType.DRIVER); }); it('should support different payment statuses', () => { const pendingPayment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; const completedPayment: Payment = { id: 'payment-124', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.COMPLETED, createdAt: new Date('2024-01-01'), completedAt: new Date('2024-01-15'), }; const failedPayment: Payment = { id: 'payment-125', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.FAILED, createdAt: new Date('2024-01-01'), }; const refundedPayment: Payment = { id: 'payment-126', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 50, netAmount: 950, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.REFUNDED, createdAt: new Date('2024-01-01'), }; expect(pendingPayment.status).toBe(PaymentStatus.PENDING); expect(completedPayment.status).toBe(PaymentStatus.COMPLETED); expect(failedPayment.status).toBe(PaymentStatus.FAILED); expect(refundedPayment.status).toBe(PaymentStatus.REFUNDED); }); it('should handle zero and negative amounts', () => { const zeroPayment: Payment = { id: 'payment-123', type: PaymentType.SPONSORSHIP, amount: 0, platformFee: 0, netAmount: 0, payerId: 'sponsor-456', payerType: PayerType.SPONSOR, leagueId: 'league-789', status: PaymentStatus.PENDING, createdAt: new Date('2024-01-01'), }; expect(zeroPayment.amount).toBe(0); expect(zeroPayment.platformFee).toBe(0); expect(zeroPayment.netAmount).toBe(0); }); }); });