const { calculatePayout, calculateStraightPayout, calculateParlayPayout } = require('../../src/services/payoutCalculator'); describe('payoutCalculator', () => { describe('straight bets', () => { test('negative odds: -110, $20 → $38.18', () => { const payout = calculatePayout(20, 'straight', [-110]); expect(payout).toBeCloseTo(38.18, 1); }); test('positive odds: +150, $20 → $50', () => { const payout = calculatePayout(20, 'straight', [150]); expect(payout).toBe(50); }); test('even odds: -100, $20 → $40', () => { const payout = calculatePayout(20, 'straight', [-100]); expect(payout).toBe(40); }); test('heavy favorite: -200, $20 → $30', () => { const payout = calculatePayout(20, 'straight', [-200]); expect(payout).toBe(30); }); test('big underdog: +300, $10 → $40', () => { const payout = calculatePayout(10, 'straight', [300]); expect(payout).toBe(40); }); }); describe('parlay bets', () => { test('2-leg parlay: -110 and -110, $20', () => { const payout = calculatePayout(20, 'parlay', [-110, -110]); // Each leg: 1 + 100/110 = 1.909..., product = 3.647, payout = 20 * 3.647 = 72.93 expect(payout).toBeCloseTo(72.93, 0); }); test('3-leg parlay: -110, -110, +150, $10', () => { const payout = calculatePayout(10, 'parlay', [-110, -110, 150]); // 1.909 * 1.909 * 2.5 = 9.118, payout = 91.18 expect(payout).toBeCloseTo(91.18, 0); }); test('2-leg parlay: +200 and +200, $10', () => { const payout = calculatePayout(10, 'parlay', [200, 200]); // 3 * 3 = 9, payout = 90 expect(payout).toBe(90); }); }); describe('edge cases', () => { test('empty odds returns amount', () => { expect(calculatePayout(20, 'straight', [])).toBe(20); }); test('single leg in parlay treated as straight', () => { const straight = calculatePayout(20, 'straight', [-110]); const parlaySingle = calculatePayout(20, 'parlay', [-110]); // Single leg parlay should use parlay calc but result is same as straight expect(parlaySingle).toBeCloseTo(straight, 1); }); }); });