import { describe, expect, it } from 'vitest'; import { MoneyError, formatCents, parseAmountToCents, platformFee, proPayout, splitCharge } from '../src/money'; describe('platformFee', () => { it('takes the stated percentage', () => { expect(platformFee(10_000, 1500)).toBe(1500); expect(platformFee(15_000, 1200)).toBe(1800); }); it('rounds half-up to whole cents', () => { expect(platformFee(333, 1500)).toBe(50); // 49.95 -> 50 expect(platformFee(1, 1500)).toBe(0); // 0.15 -> 0 }); it('handles the boundaries', () => { expect(platformFee(10_000, 0)).toBe(0); expect(platformFee(10_000, 10_000)).toBe(10_000); }); it('rejects nonsense rates', () => { expect(() => platformFee(10_000, -1)).toThrow(MoneyError); expect(() => platformFee(10_000, 10_001)).toThrow(MoneyError); expect(() => platformFee(10_000, 12.5)).toThrow(MoneyError); }); it('rejects non-integer amounts — floats never reach Stripe', () => { expect(() => platformFee(99.99, 1500)).toThrow(MoneyError); expect(() => platformFee(-100, 1500)).toThrow(MoneyError); }); }); describe('splitCharge', () => { it('always sums back to the original amount', () => { for (const amount of [1, 7, 333, 999, 10_000, 123_457]) { const { fee, payout } = splitCharge(amount, 1500); expect(fee + payout).toBe(amount); } }); it('agrees with proPayout', () => { expect(splitCharge(20_000, 1500).payout).toBe(proPayout(20_000, 1500)); }); }); describe('parseAmountToCents', () => { it('parses the shapes a human types', () => { expect(parseAmountToCents('150')).toBe(15_000); expect(parseAmountToCents('150.50')).toBe(15_050); expect(parseAmountToCents('150,50')).toBe(15_050); expect(parseAmountToCents('$150.50')).toBe(15_050); }); it('rounds to the nearest cent rather than truncating', () => { expect(parseAmountToCents('10.999')).toBe(1100); }); it('throws on junk', () => { expect(() => parseAmountToCents('abc')).toThrow(MoneyError); }); }); describe('formatCents', () => { it('renders whole currency units', () => { expect(formatCents(15_000)).toContain('150'); }); });