BillTracker/tests/statusService.test.js

99 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-05-16 20:26:09 -05:00
const test = require('node:test');
const assert = require('node:assert/strict');
const {
buildTrackerRow,
getCycleRange,
resolveDueDate,
} = require('../services/statusService');
function bill(overrides = {}) {
return {
id: 1,
name: 'Test bill',
due_day: 15,
expected_amount: 100,
autopay_enabled: 0,
autodraft_status: 'none',
cycle_type: 'monthly',
cycle_day: '1',
...overrides,
};
}
test('monthly bills use due_day and calendar-month cycle range', () => {
const monthly = bill({ due_day: 31, cycle_day: '1' });
assert.equal(resolveDueDate(monthly, 2026, 2), '2026-02-28');
assert.deepEqual(getCycleRange(2026, 2, monthly), {
start: '2026-02-01',
end: '2026-02-28',
});
});
test('weekly bills use cycle_day as weekday', () => {
const weekly = bill({ cycle_type: 'weekly', cycle_day: 'wednesday' });
assert.equal(resolveDueDate(weekly, 2026, 5), '2026-05-06');
assert.deepEqual(getCycleRange(2026, 5, weekly), {
start: '2026-05-06',
end: '2026-05-12',
});
});
test('biweekly bills use cycle_day weekday on the deterministic two-week cadence', () => {
const biweekly = bill({ cycle_type: 'biweekly', cycle_day: 'monday' });
assert.equal(resolveDueDate(biweekly, 2026, 5), '2026-05-04');
assert.deepEqual(getCycleRange(2026, 5, biweekly), {
start: '2026-05-04',
end: '2026-05-17',
});
});
test('quarterly bills only occur in assigned quarter months', () => {
const quarterly = bill({ cycle_type: 'quarterly', cycle_day: '2', due_day: 30 });
assert.equal(resolveDueDate(quarterly, 2026, 2), '2026-02-28');
assert.equal(resolveDueDate(quarterly, 2026, 3), null);
assert.equal(resolveDueDate(quarterly, 2026, 5), '2026-05-30');
assert.deepEqual(getCycleRange(2026, 5, quarterly), {
start: '2026-05-01',
end: '2026-07-31',
});
});
test('annual bills only occur in their assigned month', () => {
const annual = bill({ cycle_type: 'annual', cycle_day: '11', due_day: 31 });
assert.equal(resolveDueDate(annual, 2026, 10), null);
assert.equal(resolveDueDate(annual, 2026, 11), '2026-11-30');
assert.deepEqual(getCycleRange(2026, 11, annual), {
start: '2026-01-01',
end: '2026-12-31',
});
});
test('tracker rows are skipped when a bill does not occur in the requested month', () => {
const quarterly = bill({ cycle_type: 'quarterly', cycle_day: '1' });
assert.equal(buildTrackerRow(quarterly, [], 2026, 2, '2026-02-01', { gracePeriodDays: 5 }), null);
});
test('tracker rows cap due math when a payment exceeds the amount due', () => {
const row = buildTrackerRow(
bill({ expected_amount: 10000 }),
[{ amount: 12500, paid_date: '2026-05-10' }],
2026-05-16 20:26:09 -05:00
2026,
5,
'2026-05-16',
{ gracePeriodDays: 5 },
);
assert.equal(row.status, 'paid');
assert.equal(row.total_paid, 125);
assert.equal(row.paid_toward_due, 100);
assert.equal(row.overpaid_amount, 25);
assert.equal(row.balance, 0);
});