← back to Costa Rica

test/money.test.js

48 lines

'use strict';
// Pure money-math coverage for the branches marketplace.test.js doesn't hit:
// a nonzero processor fee (which reduces host payout), currency validation,
// formatting, and reversed/zero night ranges. Integer minor units throughout.
const { test } = require('node:test');
const assert = require('node:assert');
const { computeSplit, nights, fmt, assertCurrency } = require('../lib/money');

test('computeSplit: a processor fee comes out of the host payout, total unchanged', () => {
  // 3 nights @ $120 + $40 cleaning = $400.00 total; 10% platform + 3% processor.
  const s = computeSplit({ subtotal: 36000, cleaningFee: 4000, currency: 'USD',
    platformFeeBps: 1000, processorFeeBps: 300 });
  assert.equal(s.total, 40000);            // traveler still charged the full total
  assert.equal(s.platformFee, 4000);       // 10% of 400.00
  assert.equal(s.processorFee, 1200);      // 3% of 400.00
  assert.equal(s.hostPayout, 34800);       // total - platform - processor
  // Conservation: nothing vanishes, nothing is minted.
  assert.equal(s.hostPayout + s.platformFee + s.processorFee, s.total);
});

test('computeSplit: conservation holds across processor-fee combos (no rounding leak)', () => {
  for (const [sub, clean, pbps, prbps] of [
    [3333, 777, 1000, 250], [9999, 0, 1250, 300], [10001, 501, 999, 175], [1, 0, 1, 1]]) {
    const s = computeSplit({ subtotal: sub, cleaningFee: clean, currency: 'CRC',
      platformFeeBps: pbps, processorFeeBps: prbps });
    assert.equal(s.hostPayout + s.platformFee + s.processorFee, s.total);
    assert.ok(s.hostPayout >= 0, 'host payout never goes negative');
  }
});

test('assertCurrency rejects an unsupported currency and computeSplit refuses it', () => {
  assert.throws(() => assertCurrency('EUR'), /unsupported currency/);
  assert.throws(() => computeSplit({ subtotal: 100, currency: 'BTC' }), /unsupported currency/);
  assert.doesNotThrow(() => assertCurrency('USD'));
  assert.doesNotThrow(() => assertCurrency('CRC'));
});

test('fmt renders minor units as major with 2 decimals', () => {
  assert.equal(fmt(40000, 'USD'), 'USD 400.00');
  assert.equal(fmt(5, 'CRC'), 'CRC 0.05');
  assert.equal(fmt(0, 'USD'), 'USD 0.00');
});

test('nights clamps reversed ranges to 0 (never negative)', () => {
  assert.equal(nights('2026-09-13', '2026-09-10'), 0); // check-out before check-in
  assert.equal(nights('2026-09-10', '2026-09-11'), 1);
});