import { calculateInstallments, formatMoney, roundToMinimumUnit, calculateMonthlyRepayment } from '../src'; describe('@payafter/currency', () => { describe('calculateInstallments - RWF', () => { it('should calculate 3 installments with RWF rounding', () => { const installments = calculateInstallments(100000, 3, 'RWF'); expect(installments).toHaveLength(3); expect(installments[0]).toBe(33300); // Rounded to 100 expect(installments[1]).toBe(33300); // Rounded to 100 expect(installments[2]).toBe(33400); // Absorbs remainder expect(installments.reduce((a, b) => a + b, 0)).toBe(100000); }); it('should ensure all installments except last are multiples of 100', () => { const installments = calculateInstallments(250000, 6, 'RWF'); for (let i = 0; i < installments.length - 1; i++) { expect(installments[i] % 100).toBe(0); } expect(installments.reduce((a, b) => a + b, 0)).toBe(250000); }); it('should handle single installment', () => { const installments = calculateInstallments(100000, 1, 'RWF'); expect(installments).toEqual([100000]); }); it('should handle zero count', () => { const installments = calculateInstallments(100000, 0, 'RWF'); expect(installments).toEqual([]); }); }); describe('calculateInstallments - XOF', () => { it('should calculate installments without rounding constraint', () => { const installments = calculateInstallments(100000, 3, 'XOF'); expect(installments).toHaveLength(3); expect(installments.reduce((a, b) => a + b, 0)).toBe(100000); }); it('should distribute precisely for XOF', () => { const installments = calculateInstallments(100, 3, 'XOF'); expect(installments.reduce((a, b) => a + b, 0)).toBe(100); }); }); describe('formatMoney', () => { it('should format RWF correctly', () => { const formatted = formatMoney(100000, 'RWF'); expect(formatted).toContain('100,000'); expect(formatted).toContain('RWF'); }); it('should format XOF correctly with French locale', () => { const formatted = formatMoney(100000, 'XOF', 'fr-FR'); expect(formatted).toContain('100'); expect(formatted).toContain('000'); expect(formatted).toContain('F CFA'); }); it('should handle Dinero objects', () => { const Dinero = require('dinero.js'); const money = Dinero({ amount: 100000, currency: 'RWF', precision: 0 }); const formatted = formatMoney(money, 'RWF'); expect(formatted).toContain('100,000'); }); }); describe('roundToMinimumUnit', () => { it('should round to nearest 100 for RWF', () => { expect(roundToMinimumUnit(33333, 'RWF')).toBe(33300); expect(roundToMinimumUnit(33350, 'RWF')).toBe(33400); expect(roundToMinimumUnit(33399, 'RWF')).toBe(33400); expect(roundToMinimumUnit(33301, 'RWF')).toBe(33300); }); it('should not round for XOF', () => { expect(roundToMinimumUnit(33333, 'XOF')).toBe(33333); expect(roundToMinimumUnit(12345, 'XOF')).toBe(12345); }); }); describe('calculateMonthlyRepayment', () => { it('should calculate monthly repayment correctly for RWF', () => { const result = calculateMonthlyRepayment(100000, 20000, 6, 'RWF'); expect(result.monthlyReturn).toBeDefined(); expect(result.monthlyPrincipal).toBeDefined(); expect(result.monthlyProfit).toBeDefined(); expect(result.monthlyProfit).toBe(result.monthlyReturn - result.monthlyPrincipal); }); it('should ensure monthly values are multiples of 100 for RWF', () => { const result = calculateMonthlyRepayment(100000, 20000, 6, 'RWF'); expect(result.monthlyReturn % 100).toBe(0); expect(result.monthlyPrincipal % 100).toBe(0); }); it('should calculate monthly repayment correctly for XOF', () => { const result = calculateMonthlyRepayment(100000, 20000, 6, 'XOF'); expect(result.monthlyReturn).toBeDefined(); expect(result.monthlyPrincipal).toBeDefined(); expect(result.monthlyProfit).toBeDefined(); }); }); });