[
{
"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"
}
]