[ { "name": "adding a driver half way: 120.00 more a year for 183 of 365 days is 60.16, plus a 25.00 fee", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 2500, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 183, "premiumChange": { "minor": 6016, "currency": "GBP" }, "adminFee": { "minor": 2500, "currency": "GBP" }, "amountDue": { "minor": 8516, "currency": "GBP" }, "kind": "additional" } }, { "name": "one rounding of the difference, not two: pro-rating 500.00 and 620.00 separately would give 60.17", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 0, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 183, "premiumChange": { "minor": 6016, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 6016, "currency": "GBP" }, "kind": "additional" } }, { "name": "removing the driver returns 60.16, less the 25.00 fee", "args": [ { "minor": 62000, "currency": "GBP" }, { "minor": 50000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 2500, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 183, "premiumChange": { "minor": -6016, "currency": "GBP" }, "adminFee": { "minor": 2500, "currency": "GBP" }, "amountDue": { "minor": -3516, "currency": "GBP" }, "kind": "return" } }, { "name": "rounding up charges the part penny", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 0, "currency": "GBP" }, "up" ], "expect": { "totalDays": 365, "remainingDays": 183, "premiumChange": { "minor": 6017, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 6017, "currency": "GBP" }, "kind": "additional" } }, { "name": "a change from inception is the whole difference", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-01", { "minor": 0, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 365, "premiumChange": { "minor": 12000, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 12000, "currency": "GBP" }, "kind": "additional" } }, { "name": "a change on the expiry date costs nothing but the fee", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2027-01-01", { "minor": 2500, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 0, "premiumChange": { "minor": 0, "currency": "GBP" }, "adminFee": { "minor": 2500, "currency": "GBP" }, "amountDue": { "minor": 2500, "currency": "GBP" }, "kind": "none" } }, { "name": "a change with no premium effect still carries its fee", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 50000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-03-15", { "minor": 1500, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 292, "premiumChange": { "minor": 0, "currency": "GBP" }, "adminFee": { "minor": 1500, "currency": "GBP" }, "amountDue": { "minor": 1500, "currency": "GBP" }, "kind": "none" } }, { "name": "a leap-year term has 366 days: 366.00 more for the last 31 is 31.00", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": 36600, "currency": "GBP" }, "2028-01-01", "2029-01-01", "2028-12-01", { "minor": 0, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 366, "remainingDays": 31, "premiumChange": { "minor": 3100, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 3100, "currency": "GBP" }, "kind": "additional" } }, { "name": "exactly half a penny rounds up half-up", "args": [ { "minor": 10000, "currency": "GBP" }, { "minor": 10001, "currency": "GBP" }, "2026-01-01", "2026-01-05", "2026-01-03", { "minor": 0, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 4, "remainingDays": 2, "premiumChange": { "minor": 1, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 1, "currency": "GBP" }, "kind": "additional" } }, { "name": "exactly half a penny rounds to even: nothing to charge", "args": [ { "minor": 10000, "currency": "GBP" }, { "minor": 10001, "currency": "GBP" }, "2026-01-01", "2026-01-05", "2026-01-03", { "minor": 0, "currency": "GBP" }, "half-even" ], "expect": { "totalDays": 4, "remainingDays": 2, "premiumChange": { "minor": 0, "currency": "GBP" }, "adminFee": { "minor": 0, "currency": "GBP" }, "amountDue": { "minor": 0, "currency": "GBP" }, "kind": "none" } }, { "name": "a return premium smaller than the fee still leaves something to pay", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 49000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 2500, "currency": "GBP" }, "half-up" ], "expect": { "totalDays": 365, "remainingDays": 183, "premiumChange": { "minor": -501, "currency": "GBP" }, "adminFee": { "minor": 2500, "currency": "GBP" }, "amountDue": { "minor": 1999, "currency": "GBP" }, "kind": "return" } }, { "name": "a change before inception is refused", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2025-12-31", { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "changeDate must be from inceptionDate to expiryDate" }, { "name": "a change after expiry is refused", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2027-01-02", { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "changeDate must be from inceptionDate to expiryDate" }, { "name": "expiry must be after inception", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2027-01-01", "2026-01-01", "2026-01-01", { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "expiryDate must be after inceptionDate" }, { "name": "a negative fee is refused", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": -1, "currency": "GBP" }, "half-up" ], "expectError": "adminFee must not be negative" }, { "name": "a negative premium is refused", "args": [ { "minor": -50000, "currency": "GBP" }, { "minor": 62000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "premiums must not be negative" }, { "name": "premiums in two currencies are refused", "args": [ { "minor": 50000, "currency": "GBP" }, { "minor": 62000, "currency": "EUR" }, "2026-01-01", "2027-01-01", "2026-07-02", { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "currency mismatch" } ]