[ { "name": "\u00a3500 overdrawn all month at 39.9%, no buffer", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -50000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 1694, "currency": "GBP" }, "daysOverdrawn": 31, "daysCharged": 31 } }, { "name": "a \u00a3250 buffer: only the \u00a3250 above it is charged", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -50000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 25000, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 847, "currency": "GBP" }, "daysOverdrawn": 31, "daysCharged": 31 } }, { "name": "within the buffer all month: no interest", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -20000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 25000, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 0, "currency": "GBP" }, "daysOverdrawn": 31, "daysCharged": 0 } }, { "name": "in and out of the overdraft during the month", "args": [ [ { "date": "2026-03-01", "balance": { "minor": 10000, "currency": "GBP" } }, { "date": "2026-03-10", "balance": { "minor": -80000, "currency": "GBP" } }, { "date": "2026-03-20", "balance": { "minor": -30000, "currency": "GBP" } }, { "date": "2026-03-25", "balance": { "minor": 5000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 25000, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 629, "currency": "GBP" }, "daysOverdrawn": 15, "daysCharged": 15 } }, { "name": "in credit all month: no interest and no overdrawn days", "args": [ [ { "date": "2026-03-01", "balance": { "minor": 150000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 0, "currency": "GBP" }, "daysOverdrawn": 0, "daysCharged": 0 } }, { "name": "a balance exactly at the buffer is not charged", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -25000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 25000, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 0, "currency": "GBP" }, "daysOverdrawn": 31, "daysCharged": 0 } }, { "name": "opening balance from before the statement", "args": [ [ { "date": "2026-02-20", "balance": { "minor": -100000, "currency": "GBP" } }, { "date": "2026-03-15", "balance": { "minor": 0, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 1990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 763, "currency": "GBP" }, "daysOverdrawn": 14, "daysCharged": 14 } }, { "name": "a zero-rate overdraft counts days but charges nothing", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -100000, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 0, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 0, "currency": "GBP" }, "daysOverdrawn": 31, "daysCharged": 31 } }, { "name": "customer-friendly rounding down", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -12345, "currency": "GBP" } } ], "2026-03-01", "2026-03-08", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "down" ], "expect": { "interest": { "minor": 94, "currency": "GBP" }, "daysOverdrawn": 7, "daysCharged": 7 } }, { "name": "a leap-year February on ACT/365F", "args": [ [ { "date": "2028-02-01", "balance": { "minor": -100000, "currency": "GBP" } } ], "2028-02-01", "2028-03-01", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expect": { "interest": { "minor": 3170, "currency": "GBP" }, "daysOverdrawn": 29, "daysCharged": 29 } }, { "name": "a negative rate is refused", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -100, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", -1, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expectError": "annualRateBasisPoints must not be negative" }, { "name": "a negative buffer is refused", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -100, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": -1, "currency": "GBP" }, "act-365f", "half-up" ], "expectError": "interestFreeBuffer must not be negative" }, { "name": "a buffer in another currency is refused", "args": [ [ { "date": "2026-03-01", "balance": { "minor": -100, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 0, "currency": "EUR" }, "act-365f", "half-up" ], "expectError": "currency mismatch" }, { "name": "balances out of order are refused", "args": [ [ { "date": "2026-03-05", "balance": { "minor": -100, "currency": "GBP" } }, { "date": "2026-03-01", "balance": { "minor": -200, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expectError": "strictly ascending date order" }, { "name": "a first balance after the statement starts is refused", "args": [ [ { "date": "2026-03-05", "balance": { "minor": -100, "currency": "GBP" } } ], "2026-03-01", "2026-04-01", 3990, { "minor": 0, "currency": "GBP" }, "act-365f", "half-up" ], "expectError": "after fromIso" } ]