[ { "name": "GOV.UK's example: plan 1 on \u00a342,000 in 2026/27 repays \u00a31,359", "args": [ { "minor": 4200000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2026-07-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 2690000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 4200000, "currency": "GBP" }, "repayment": { "minor": 135900, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 135900, "currency": "GBP" } } }, { "name": "the same, with \u00a31,200 already deducted through PAYE: \u00a3159 left to pay", "args": [ { "minor": 4200000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2026-07-01", { "minor": 120000, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 2690000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 4200000, "currency": "GBP" }, "repayment": { "minor": 135900, "currency": "GBP" }, "deductedThroughPaye": { "minor": 120000, "currency": "GBP" }, "balance": { "minor": 15900, "currency": "GBP" } } }, { "name": "postgraduate loan: 6% over \u00a321,000", "args": [ { "minor": 3000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "postgraduate", "2026-07-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 2100000, "currency": "GBP" }, "basisPoints": 600, "countedIncome": { "minor": 3000000, "currency": "GBP" }, "repayment": { "minor": 54000, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 54000, "currency": "GBP" } } }, { "name": "pence are dropped: plan 1 2025/26 on \u00a330,000 is \u00a3354.15, so \u00a3354", "args": [ { "minor": 3000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 2606500, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 3000000, "currency": "GBP" }, "repayment": { "minor": 35400, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 35400, "currency": "GBP" } } }, { "name": "unearned income of exactly \u00a32,000 is left out", "args": [ { "minor": 3000000, "currency": "GBP" }, { "minor": 200000, "currency": "GBP" }, "plan-2", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 2847000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 3000000, "currency": "GBP" }, "repayment": { "minor": 13700, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 13700, "currency": "GBP" } } }, { "name": "a penny more and all of it counts", "args": [ { "minor": 3000000, "currency": "GBP" }, { "minor": 200001, "currency": "GBP" }, "plan-2", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 2847000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 3200001, "currency": "GBP" }, "repayment": { "minor": 31700, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 31700, "currency": "GBP" } } }, { "name": "income below the threshold repays nothing, and PAYE deductions are owed back", "args": [ { "minor": 2000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-2", "2025-10-01", { "minor": 5000, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 2847000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 2000000, "currency": "GBP" }, "repayment": { "minor": 0, "currency": "GBP" }, "deductedThroughPaye": { "minor": 5000, "currency": "GBP" }, "balance": { "minor": -5000, "currency": "GBP" } } }, { "name": "income exactly at the threshold repays nothing", "args": [ { "minor": 2847000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-2", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 2847000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 2847000, "currency": "GBP" }, "repayment": { "minor": 0, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 0, "currency": "GBP" } } }, { "name": "plan 5 from 2026/27", "args": [ { "minor": 3500000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-5", "2026-12-31", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 2500000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 3500000, "currency": "GBP" }, "repayment": { "minor": 90000, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 90000, "currency": "GBP" } } }, { "name": "5 April 2026 is still 2025/26: plan 4 at \u00a332,745", "args": [ { "minor": 4000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-4", "2026-04-05", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2025/26", "threshold": { "minor": 3274500, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 4000000, "currency": "GBP" }, "repayment": { "minor": 65200, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 65200, "currency": "GBP" } } }, { "name": "6 April 2026 is 2026/27: plan 4 at \u00a333,795", "args": [ { "minor": 4000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-4", "2026-04-06", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 3379500, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 4000000, "currency": "GBP" }, "repayment": { "minor": 55800, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 55800, "currency": "GBP" } } }, { "name": "2023/24, plan 2 at \u00a327,295", "args": [ { "minor": 5000000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-2", "2023-06-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2023/24", "threshold": { "minor": 2729500, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 5000000, "currency": "GBP" }, "repayment": { "minor": 204300, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 204300, "currency": "GBP" } } }, { "name": "no income at all", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2026-07-01", { "minor": 0, "currency": "GBP" } ], "expect": { "taxYear": "2026/27", "threshold": { "minor": 2690000, "currency": "GBP" }, "basisPoints": 900, "countedIncome": { "minor": 0, "currency": "GBP" }, "repayment": { "minor": 0, "currency": "GBP" }, "deductedThroughPaye": { "minor": 0, "currency": "GBP" }, "balance": { "minor": 0, "currency": "GBP" } } }, { "name": "plan 5 before 2026/27 is an error", "args": [ { "minor": 3500000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-5", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "no student loan threshold for plan-5 in tax year 2025/26" }, { "name": "a tax year before the data is an error", "args": [ { "minor": 3500000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2022-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "no student loan threshold for plan-1 in tax year 2022/23" }, { "name": "an unknown plan is an error", "args": [ { "minor": 3500000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-3", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "unknown student loan plan \"plan-3\"" }, { "name": "income in euros is an error", "args": [ { "minor": 3500000, "currency": "EUR" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "earnedIncome must be in GBP, received EUR" }, { "name": "negative earned income is an error", "args": [ { "minor": -1, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "earnedIncome must not be negative, received -1" }, { "name": "negative unearned income is an error", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": -1, "currency": "GBP" }, "plan-1", "2025-10-01", { "minor": 0, "currency": "GBP" } ], "expectError": "unearnedIncome must not be negative, received -1" }, { "name": "a negative PAYE deduction is an error", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2025-10-01", { "minor": -1, "currency": "GBP" } ], "expectError": "deductedThroughPaye must not be negative, received -1" }, { "name": "an impossible date is an error", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "plan-1", "2025-02-30", { "minor": 0, "currency": "GBP" } ], "expectError": "\"2025-02-30\" is not a real calendar date" } ]