[ { "name": "pro rata after 90 of 365 days: 600.00 keeps 147.95 and returns 452.05", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "pro-rata", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 90, "totalDays": 365, "retained": { "minor": 14795, "currency": "GBP" }, "returnPremium": { "minor": 45205, "currency": "GBP" }, "minimumApplied": false } }, { "name": "short period on the last day of the 3-month band keeps 40%", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 90, "totalDays": 365, "retained": { "minor": 24000, "currency": "GBP" }, "returnPremium": { "minor": 36000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "one day into the 4th month moves to the 50% band", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-02", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 91, "totalDays": 365, "retained": { "minor": 30000, "currency": "GBP" }, "returnPremium": { "minor": 30000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "four days in: the one-week band keeps 10%", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-05", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 4, "totalDays": 365, "retained": { "minor": 6000, "currency": "GBP" }, "returnPremium": { "minor": 54000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "exactly 8 months keeps 80%", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-09-01", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 243, "totalDays": 365, "retained": { "minor": 48000, "currency": "GBP" }, "returnPremium": { "minor": 12000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "longer than every band keeps the whole premium", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-09-02", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 244, "totalDays": 365, "retained": { "minor": 60000, "currency": "GBP" }, "returnPremium": { "minor": 0, "currency": "GBP" }, "minimumApplied": false } }, { "name": "pro rata cancelled on the inception date returns everything", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-01", "pro-rata", [], null ], "expect": { "daysInForce": 0, "totalDays": 365, "retained": { "minor": 0, "currency": "GBP" }, "returnPremium": { "minor": 60000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "pro rata cancelled on the expiry date returns nothing", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2027-01-01", "pro-rata", [], null ], "expect": { "daysInForce": 365, "totalDays": 365, "retained": { "minor": 60000, "currency": "GBP" }, "returnPremium": { "minor": 0, "currency": "GBP" }, "minimumApplied": false } }, { "name": "a minimum retained premium of 75.00 beats 23.01 pro rata", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-15", "pro-rata", [], { "minor": 7500, "currency": "GBP" } ], "expect": { "daysInForce": 14, "totalDays": 365, "retained": { "minor": 7500, "currency": "GBP" }, "returnPremium": { "minor": 52500, "currency": "GBP" }, "minimumApplied": true } }, { "name": "the minimum is capped at the premium: nothing more than was paid is kept", "args": [ { "minor": 5000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-11", "pro-rata", [], { "minor": 7500, "currency": "GBP" } ], "expect": { "daysInForce": 10, "totalDays": 365, "retained": { "minor": 5000, "currency": "GBP" }, "returnPremium": { "minor": 0, "currency": "GBP" }, "minimumApplied": true } }, { "name": "a minimum below the scale's figure changes nothing", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], { "minor": 7500, "currency": "GBP" } ], "expect": { "daysInForce": 90, "totalDays": 365, "retained": { "minor": 24000, "currency": "GBP" }, "returnPremium": { "minor": 36000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "20% of 333.33 is 66.666, kept as 66.67", "args": [ { "minor": 33333, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-01-20", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 19, "totalDays": 365, "retained": { "minor": 6667, "currency": "GBP" }, "returnPremium": { "minor": 26666, "currency": "GBP" }, "minimumApplied": false } }, { "name": "a month is a calendar month: 30 days from 31 January passes 28 February, so the 2-month band", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-31", "2027-01-31", "2026-03-02", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 30, "totalDays": 365, "retained": { "minor": 18000, "currency": "GBP" }, "returnPremium": { "minor": 42000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "28 February is exactly one month from 31 January", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-31", "2027-01-31", "2026-02-28", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 28, "totalDays": 365, "retained": { "minor": 12000, "currency": "GBP" }, "returnPremium": { "minor": 48000, "currency": "GBP" }, "minimumApplied": false } }, { "name": "a leap-year policy has 366 days: 274 of them keep 274.00 of 366.00", "args": [ { "minor": 36600, "currency": "GBP" }, "2027-06-01", "2028-06-01", "2028-03-01", "pro-rata", [], null ], "expect": { "daysInForce": 274, "totalDays": 366, "retained": { "minor": 27400, "currency": "GBP" }, "returnPremium": { "minor": 9200, "currency": "GBP" }, "minimumApplied": false } }, { "name": "a zero premium returns zero", "args": [ { "minor": 0, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 7, "unit": "days", "retainedBasisPoints": 1000 }, { "upTo": 1, "unit": "months", "retainedBasisPoints": 2000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 3, "unit": "months", "retainedBasisPoints": 4000 }, { "upTo": 4, "unit": "months", "retainedBasisPoints": 5000 }, { "upTo": 6, "unit": "months", "retainedBasisPoints": 7000 }, { "upTo": 8, "unit": "months", "retainedBasisPoints": 8000 } ], null ], "expect": { "daysInForce": 90, "totalDays": 365, "retained": { "minor": 0, "currency": "GBP" }, "returnPremium": { "minor": 0, "currency": "GBP" }, "minimumApplied": false } }, { "name": "cancelling after expiry is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2027-01-02", "pro-rata", [], null ], "expectError": "cancellationDate must be from inceptionDate to expiryDate" }, { "name": "cancelling before inception is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2025-12-31", "pro-rata", [], null ], "expectError": "cancellationDate must be from inceptionDate to expiryDate" }, { "name": "expiry must be after inception", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2026-01-01", "2026-01-01", "pro-rata", [], null ], "expectError": "expiryDate must be after inceptionDate" }, { "name": "short period without a scale is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [], null ], "expectError": "a short-period cancellation needs a scale" }, { "name": "a share above 100% is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 1, "unit": "months", "retainedBasisPoints": 10001 } ], null ], "expectError": "retainedBasisPoints must be from 0 to 10000" }, { "name": "a scale that keeps less for longer is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 1, "unit": "months", "retainedBasisPoints": 3000 }, { "upTo": 2, "unit": "months", "retainedBasisPoints": 2000 } ], null ], "expectError": "must not keep less for a longer period" }, { "name": "a fractional upTo is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "short-period", [ { "upTo": 1.5, "unit": "months", "retainedBasisPoints": 3000 } ], null ], "expectError": "upTo must be a whole number" }, { "name": "a negative premium is refused", "args": [ { "minor": -100, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "pro-rata", [], null ], "expectError": "premium must not be negative" }, { "name": "a minimum in another currency is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "pro-rata", [], { "minor": 7500, "currency": "EUR" } ], "expectError": "currency mismatch" }, { "name": "an unknown basis is refused", "args": [ { "minor": 60000, "currency": "GBP" }, "2026-01-01", "2027-01-01", "2026-04-01", "flat", [], null ], "expectError": "unknown basis" } ]