Acceptance criteria and their tests
213 of 213 criteria have a test that names them and passed in release pipeline run 20261017-1440-26d46b1.
The criteria are those of the Business Requirements Document, revision 50. Each test names the criteria it proves, and a release stops if a criterion has no test that passed.
ADM-01 Parts of the calculator
| ID | Criterion | Tests |
|---|---|---|
| ADM-01.1 | Given a part is off, when a customer goes to one of its question pages by address, then the page does not open, even part way through a journey. | 30 tests for ADM-01.1
|
| ADM-01.2 | Given a part is off, when an API request sends one of its fields, then the request is refused with 422 and code MODULE_NOT_ENABLED, naming the field. |
2 tests for ADM-01.2
|
| ADM-01.3 | Given a customer answered a part's questions before it was switched off, when the bill is worked out, then those answers are ignored. | 1 test for ADM-01.3
|
| ADM-01.4 | Given no part is ticked, when the administrator saves, then the error "Select at least one part of the calculator" is shown and nothing is saved. | 1 test for ADM-01.4
|
| ADM-01.5 | Given Marriage Allowance or Married Couple's Allowance is on, when the shared question is asked, then it offers only the choices of the parts that are on. | 1 test for ADM-01.5
|
| ADM-01.6 | Given a request or saved setting uses an older, broader name (employment_extras, payments, allowances), when it is read, then it is treated as every finer part it became. |
2 tests for ADM-01.6
|
| ADM-01.7 | GET /api/v1/modules lists every part, whether it is on, and its fields. |
2 tests for ADM-01.7
|
ADM-02 Scottish Income Tax
| ID | Criterion | Tests |
|---|---|---|
| ADM-02.1 | Given the switch is on, when a customer starts, then they are asked whether they pay Scottish Income Tax (an app sends jurisdiction), and Scottish taxpayers get Scottish rates and bands. |
2 tests for ADM-02.1
|
| ADM-02.2 | Given the switch is off, when a bill is worked out, then everyone is taxed at the rates for England, Wales and Northern Ireland. | 2 tests for ADM-02.2
|
| ADM-02.3 | Given the switch is off, when an API request sends "jurisdiction": "scotland", then it is refused rather than give a Scottish taxpayer the wrong figure. |
2 tests for ADM-02.3
|
ADM-03 Tax years offered
| ID | Criterion | Tests |
|---|---|---|
| ADM-03.1 | Given a year is off, when the tax year question is shown, then that year is not offered, and posting it is refused. | 5 tests for ADM-03.1
|
| ADM-03.2 | Given a year is off, when the API, an app's journey, the tax so far or a Making Tax Digital forecast asks for it, then it is refused with code TAX_YEAR_NOT_OFFERED, listing the years offered. |
7 tests for ADM-03.2
|
| ADM-03.3 | Given the latest year that has ended is off, when an API calculation is sent without tax_year, then it is refused with TAX_YEAR_NOT_OFFERED rather than worked out for that year; an app's journey without a year still starts, and the customer chooses one of the years offered. |
6 tests for ADM-03.3
|
| ADM-03.4 | Given a new tax year is added to the rates, when nobody has switched it off, then it is offered. | 1 test for ADM-03.4
|
| ADM-03.5 | Given only some years are on, when the start page is shown, then it names those years (a range when they follow on, otherwise each year), and names the year most people need only if it is offered. | 6 tests for ADM-03.5
|
| ADM-03.6 | Given a year is off, then take-home pay does not offer it, and its API refuses it. | 5 tests for ADM-03.6
|
| ADM-03.7 | Given no year is ticked, when the administrator saves, then "Select at least one tax year" is shown. | 1 test for ADM-03.7
|
ADM-04 Ways of use
| ID | Criterion | Tests |
|---|---|---|
| ADM-04.1 | Given a way is closed, when a customer opens its pages, then they see "This service is not available" (404); when an app calls its API, then it gets 403. | 2 tests for ADM-04.1
|
| ADM-04.2 | Given every way is unticked, when the administrator saves, then "Select at least one way to use the calculator" is shown. | 1 test for ADM-04.2
|
| ADM-04.3 | Given the service's own settings, when they are saved, then the embedded way stays off: only organisations can open pages inside an app. | 1 test for ADM-04.3
|
ADM-05 Reading answers from records, per way of use
| ID | Criterion | Tests |
|---|---|---|
| ADM-05.1 | Given reading is off for a way, when a customer or app uses that way, then nothing is read and every question is asked or must be sent. | 1 test for ADM-05.1
|
| ADM-05.2 | Given reading is on for the API and no data source is switched on, when an app calls calculate/with-hmrc-data, then it gets 409 "No data sources are switched on. Send all figures in the request instead." |
1 test for ADM-05.2
|
ADM-06 Data sources
| ID | Criterion | Tests |
|---|---|---|
| ADM-06.1 | Given a source is off, when a part it fills is set to read records, then that part's questions are asked instead. | 1 test for ADM-06.1
|
| ADM-06.2 | Given a source's connection is not configured, when the data sources page is shown, then it says the source is unavailable. | 1 test for ADM-06.2
|
| ADM-06.3 | GET /api/v1/data-sources shows which sources are on. |
1 test for ADM-06.3
|
ADM-07 Each part's answers: ask, check or read
| ID | Criterion | Tests |
|---|---|---|
| ADM-07.1 | Given ask, then nothing is read for that part and the customer enters it. |
2 tests for ADM-07.1
|
| ADM-07.2 | Given check, when records are read, then the answers are filled in on the question pages for the customer to check and change. |
2 tests for ADM-07.2
|
| ADM-07.3 | Given auto, when a question is answered completely from records, then it is skipped but still listed on Check your answers; anything that could not be read is asked. |
2 tests for ADM-07.3
|
| ADM-07.4 | GET /api/v1/modules shows each part's choice as read_automatically. |
2 tests for ADM-07.4
|
ADM-08 What else can be worked out (capabilities)
| ID | Criterion | Tests |
|---|---|---|
| ADM-08.1 | Given a capability is on for a way, when that way is closed or the capability's feature is off, then the capability is not offered. | 10 tests for ADM-08.1
|
| ADM-08.2 | Given a capability is off for a way, when a customer or app uses it that way, then its pages return 404 and its API returns 404 or 403, and its links are not shown. | 11 tests for ADM-08.2
|
| ADM-08.3 | Given the service's settings, when the service starts for the first time, then payment plans are on for the web and the API. | 1 test for ADM-08.3
|
ADM-09 Features for the whole service
| ID | Criterion | Tests |
|---|---|---|
| ADM-09.1 | Given a feature is off, then all its pages and API routes return 404 and its links disappear. | 21 tests for ADM-09.1
|
| ADM-09.2 | Given a feature is switched back on, then its finer settings are as they were. | 1 test for ADM-09.2
|
| ADM-09.3 | Given a feature was never installed (FEATURES), then the calculator gives exactly the same answers as with it. |
4 tests for ADM-09.3
|
ADM-10 Features for one organisation
| ID | Criterion | Tests |
|---|---|---|
| ADM-10.1 | Given a feature is off for an organisation, when its customers, its app or its key reach the feature, then it is closed, while other organisations are unaffected. | 18 tests for ADM-10.1
|
ADM-11 Documents customers can upload
| ID | Criterion | Tests |
|---|---|---|
| ADM-11.1 | Given a part is on for documents, when a customer uploads the document, then the answers it holds are filled in for them to check, and the document is not kept. It is read on the service itself and never sent to an AI model. | 3 tests for ADM-11.1
|
| ADM-11.2 | Given no reader is configured, then the upload option is not offered. | 1 test for ADM-11.2
|
ADM-12 Answers an app sends (organisations)
| ID | Criterion | Tests |
|---|---|---|
| ADM-12.1 | Given skip, when a journey starts with answers, then fully answered questions are skipped. |
2 tests for ADM-12.1
|
| ADM-12.2 | Given check, or the journey sets confirm_prefill: true, then those questions are shown filled in. |
3 tests for ADM-12.2
|
ADM-13 What the result shows
| ID | Criterion | Tests |
|---|---|---|
| ADM-13.1 | Given summary, when a result page is shown (the calculator, tax so far or a Making Tax Digital helper), then the working is left out and the totals and payment dates are kept. API responses always carry the whole calculation. |
2 tests for ADM-13.1
|
ADM-14 Apps customers can be sent back to (organisations)
| ID | Criterion | Tests |
|---|---|---|
| ADM-14.1 | Given a journey's continue_url or back_url is not on a listed host, when the app starts the journey, then it is refused with 422 and code INVALID_RETURN_URL. |
6 tests for ADM-14.1
|
| ADM-14.2 | Given a return address does not start with https://, when a journey is started, then it is refused (http only for this computer, when the service runs locally or in its tests). App hosts are saved as host names. | 1 test for ADM-14.2
|
ADM-15 Telling the app when a customer finishes (organisations)
| ID | Criterion | Tests |
|---|---|---|
| ADM-15.1 | Given a notify address, when a customer finishes, then a signed notification (<kind>.completed, Standard Webhooks signature) is sent with only the journey and result IDs, no figures or personal details. |
3 tests for ADM-15.1
|
| ADM-15.2 | Given the app does not answer with 2xx within 10 seconds, then it is tried again after 1 minute, 10 minutes, 1 hour and 6 hours, then marked failed. | 1 test for ADM-15.2
|
| ADM-15.3 | Given the address is not https, not on a listed app host, or on a private network, then it is refused. The signing secret is shown once. | 3 tests for ADM-15.3
|
ADM-16 Organisations and their API keys
| ID | Criterion | Tests |
|---|---|---|
| ADM-16.1 | Given a key is created, then it is shown once and stored only as a SHA-256 hash. | 1 test for ADM-16.1
|
| ADM-16.2 | Given a key is revoked or the organisation suspended, when it is used, then every request is refused. | 2 tests for ADM-16.2
|
| ADM-16.3 | Given an organisation exceeds its requests a minute, then it gets 429 with Retry-After; given a monthly quota, then requests past it get 429 "This organisation has used its requests for this month", with Retry-After set to the start of the next month. |
2 tests for ADM-16.3
|
| ADM-16.4 | Given any organisation's key, then it can only see that organisation's clients and results. | 2 tests for ADM-16.4
|
ADM-17 Organisation administrators
| ID | Criterion | Tests |
|---|---|---|
| ADM-17.1 | Given I administer an organisation, then I can change only that organisation's settings and keys. | 2 tests for ADM-17.1
|
| ADM-17.2 | Given an app with the organisation's key, when it reads GET /api/v1/saas/settings, then it sees the settings and cannot change them. |
1 test for ADM-17.2
|
ADM-18 Audit log
| ID | Criterion | Tests |
|---|---|---|
| ADM-18.1 | Given any settings, feature, data source or organisation change, then the audit log records who, when, from which address, and the settings before and after (GET /api/v1/admin/audit). |
2 tests for ADM-18.1
|
ADM-19 Rates
| ID | Criterion | Tests |
|---|---|---|
| ADM-19.1 | Given a what-if rate, when I run POST /api/v1/admin/rates/what-if, then a customer's bill is worked out on a copy of the rates and shown beside the bill at today's rates; the live rates are never changed. |
1 test for ADM-19.1
|
| ADM-19.2 | Given the rates file has been updated, when rates are reloaded, then new calculations use them, and the load fails if any figure has lost its source. | 1 test for ADM-19.2
|
CAL-01 Start page
| ID | Criterion | Tests |
|---|---|---|
| CAL-01.1 | Given the service's settings, when the start page is shown, then it lists what is estimated, names the tax years offered ("the tax years from 6 April 2023 to 5 April 2028", or each year when there are gaps), the latest completed tax year most people need (only when it is offered), and that it takes 10 to 20 minutes. | 2 tests for CAL-01.1
|
| CAL-01.2 | It warns that this is an estimate and does not file a return or tell HMRC anything, and links to the take-home pay calculator. | 1 test for CAL-01.2
|
| CAL-01.3 | Given an organisation's address, when its start page is shown, then it carries the organisation's name, the parts it uses (when not all) and the years it offers. | 3 tests for CAL-01.3
|
CAL-02 Tax year
| ID | Criterion | Tests |
|---|---|---|
| CAL-02.1 | Given the years offered, when the question is shown, then only those years are listed. | 5 tests for CAL-02.1
|
| CAL-02.2 | Given a year whose figures are not all announced (for example Scottish rates for 2027 to 2028), when the bill is shown, then it uses the year before's figures and says which. | 1 test for CAL-02.2
|
CAL-03 Where the customer pays tax
| ID | Criterion | Tests |
|---|---|---|
| CAL-03.1 | Given Scottish Income Tax is on, then the customer is asked whether they pay it; given it is off, the question is not asked. | 2 tests for CAL-03.1
|
| CAL-03.2 | Given the residence part is on, then non-residents and split years are asked about; given it is off, everyone is treated as UK resident. | 1 test for CAL-03.2
|
CAL-04 Types of income
| ID | Criterion | Tests |
|---|---|---|
| CAL-04.1 | Given a part is off, then its kind of income is not offered. | 2 tests for CAL-04.1
|
| CAL-04.2 | Given "None of these" is ticked with another box, then the page is refused (400) with an error asking the customer to select 'None of these' only; this works without JavaScript. | 1 test for CAL-04.2
|
CAL-05 Question pages
| ID | Criterion | Tests |
|---|---|---|
| CAL-05.1 | Given an earlier required page is unanswered, when a later page is opened by its address, then the customer is redirected (303) to the first page still to answer. | 2 tests for CAL-05.1
|
| CAL-05.2 | Given no session, when a question page is opened, then the customer is sent to /calculate/start. |
2 tests for CAL-05.2
|
| CAL-05.3 | Given an answer is missing or invalid, when the page is submitted, then the page title starts with "Error: ", an error summary links to each field, and the message is shown at the field, as the GOV.UK Design System sets out. | 2 tests for CAL-05.3
|
| CAL-05.4 | Every page has a back link, works without JavaScript and carries a CSRF token. | 3 tests for CAL-05.4
|
CAL-06 Filling answers from HMRC records
| ID | Criterion | Tests |
|---|---|---|
| CAL-06.1 | Given reading is on for the web and a part is set to check or auto, when the customer chooses to use their records, then they sign in and give permission first, and only figures about them are read. |
3 tests for CAL-06.1
|
| CAL-06.2 | Given check, then the figures are filled in on the question pages for the customer to check and change. |
2 tests for CAL-06.2
|
| CAL-06.3 | Given auto, then questions answered completely are skipped and still listed on Check your answers; figures that could not be read are asked. |
2 tests for CAL-06.3
|
| CAL-06.4 | Given a source is unavailable, then its questions are asked and nothing fails. | 2 tests for CAL-06.4
|
CAL-07 Filling answers from a document
| ID | Criterion | Tests |
|---|---|---|
| CAL-07.1 | Given documents are on for the part and a reader is configured, when the customer is on that part's question page, then they can upload a PDF of the document. The answers are filled in for them to check, and the document is not kept. | 2 tests for CAL-07.1
|
| CAL-07.2 | Given the figures for that part came from HMRC records, then no upload is offered. | 1 test for CAL-07.2
|
| CAL-07.3 | Given a file that is not a PDF, then the error is "The selected file must be a PDF". | 1 test for CAL-07.3
|
| CAL-07.4 | The link only appears on the question page itself, in the order of the questions. | 1 test for CAL-07.4
|
CAL-08 Check your answers
| ID | Criterion | Tests |
|---|---|---|
| CAL-08.1 | Given the customer reaches the end, then every answer is listed with a change link, including answers read from records. | 2 tests for CAL-08.1
|
| CAL-08.2 | Given an answer is changed, then the customer returns to Check your answers, with any new questions that answer brings asked first. | 1 test for CAL-08.2
|
CAL-09 The result
| ID | Criterion | Tests |
|---|---|---|
| CAL-09.1 | The result shows the estimated bill for the tax year, or the repayment due, or that there is nothing to pay. | 1 test for CAL-09.1
|
| CAL-09.2 | "What to pay and when": total tax, tax already paid or deducted, the balance, any amount collected through the tax code, the first and second payments on account for next year with their dates, and the total to pay by 31 January. | 3 tests for CAL-09.2
|
| CAL-09.3 | Given the result shows full, then "How your tax is worked out" lists income, reliefs, allowances, adjusted net income, Income Tax by band, reductions, charges (High Income Child Benefit Charge, pension savings, Gift Aid, remittance basis), Class 2 and Class 4 National Insurance, Capital Gains Tax and student loan repayments; given summary, it is left out. |
3 tests for CAL-09.3
|
| CAL-09.4 | The result also says whether Making Tax Digital applies, and shows things to know, ways the customer may be able to pay less (Marriage Allowance, reducing payments on account, student loans) and what happens next. | 1 test for CAL-09.4
|
| CAL-09.5 | Given the Making Tax Digital helpers are on for the web, then the result adds a panel on whether Making Tax Digital applies, with a link to the helper. The result also links to change the answers, start a new estimate, sign in to file a return, and the rates used. | 1 test for CAL-09.5
|
CAL-10 Time out and privacy of answers
| ID | Criterion | Tests |
|---|---|---|
| CAL-10.1 | Given 13 minutes without use, then the HMRC timeout warning offers to stay signed in; at 15 minutes the session ends and its answers can no longer be used (CAL-10.2). | 1 test for CAL-10.1
|
| CAL-10.2 | Answers are kept only in the customer's session: in memory, or in the service's database when it has one. They can no longer be used 15 minutes after the customer last used the service, are deleted by the clean-up that runs every 5 minutes, and are never sent to HMRC. | 2 tests for CAL-10.2
|
CAL-11 Take-home pay
| ID | Criterion | Tests |
|---|---|---|
| CAL-11.1 | Given a salary for an offered year, then the result shows Income Tax, National Insurance, any student loan and what is left, weekly, monthly and yearly. Only the tax years offered are listed. The same is at GET or POST /api/v1/calculate/quick. |
7 tests for CAL-11.1
|
CAL-12 Rates and help pages
| ID | Criterion | Tests |
|---|---|---|
| CAL-12.1 | /tax-rates shows every rate and allowance for a year, each with its source. |
1 test for CAL-12.1
|
| CAL-12.2 | Every page links to cookies, the accessibility statement, privacy, terms, and a form to report a problem. | 1 test for CAL-12.2
|
API-01 Calling as an organisation
| ID | Criterion | Tests |
|---|---|---|
| API-01.1 | Given a valid key, when the app calls /api/v1/saas/calculate, then the organisation's parts, years and capabilities apply. |
2 tests for API-01.1
|
| API-01.2 | Given a missing, revoked or unknown key, or a suspended organisation, then the call is refused. | 3 tests for API-01.2
|
| API-01.3 | Given more calls a minute than the organisation's limit, then 429 with Retry-After; GET /api/v1/saas/usage shows the month's calls and limits. |
2 tests for API-01.3
|
| API-01.4 | GET /api/v1/saas/settings shows the organisation's settings, read only. |
1 test for API-01.4
|
API-02 The full calculation
| ID | Criterion | Tests |
|---|---|---|
| API-02.1 | Given no field is required, when only some figures are sent, then the calculation uses them, and without tax_year it is for the latest tax year that has ended on as_of (default today), and the result says so. |
2 tests for API-02.1
|
| API-02.2 | Given no tax_year and the latest year that has ended is switched off, then 422 with TAX_YEAR_NOT_OFFERED, asking for tax_year. |
6 tests for API-02.2
|
| API-02.3 | Given an unknown field name, then 422 lists every problem; nothing is calculated. | 1 test for API-02.3
|
| API-02.4 | Given a field of a part that is off, then 422 with MODULE_NOT_ENABLED; given a year that is off, then 422 with TAX_YEAR_NOT_OFFERED. |
6 tests for API-02.4
|
| API-02.5 | Given the API is closed in the settings, then 403 "Calculations through the API are switched off". | 1 test for API-02.5
|
| API-02.6 | The response carries the tax for the year by type, the working, the balance, payments on account and the payment schedule, notes and recommendations, and where the rates came from. | 95 tests for API-02.6
|
API-03 One part at a time
| ID | Criterion | Tests |
|---|---|---|
| API-03.1 | GET /api/v1/modules lists every part, whether it is on, its fields and how its answers are read. |
1 test for API-03.1
|
| API-03.2 | Given {"tax_year": "2025/26", "salary_gross": 30000} sent to POST /api/v1/modules/employment/calculate, then the calculation uses only that part's fields. |
1 test for API-03.2
|
| API-03.3 | Given the part is off, then 403 naming the part. | 1 test for API-03.3
|
API-04 Checking a request
| ID | Criterion | Tests |
|---|---|---|
| API-04.1 | POST /api/v1/validate returns whether the request is valid, the tax year it would use, and its errors and warnings, without calculating. |
1 test for API-04.1
|
API-05 Reference data
| ID | Criterion | Tests |
|---|---|---|
| API-05.1 | GET /api/v1/tax-years lists the supported years; GET /api/v1/tax-rates?tax_year=2025-26 returns every rate for a year with its source. |
2 tests for API-05.1
|
| API-05.2 | GET or POST /api/v1/calculate/quick returns take-home pay from a salary. |
1 test for API-05.2
|
API-06 Extra calculations through the API
| ID | Criterion | Tests |
|---|---|---|
| API-06.1 | Given a capability is off for the API, or its feature is off for the organisation, then its endpoint is refused and no figure is returned. | 12 tests for API-06.1
|
| API-06.2 | Given a tool's API, then it takes the same answers as its question pages, as JSON, and checks them the same way; GET /api/v1/{tool} lists its tools with an example request. |
1 test for API-06.2
|
API-07 Turning records into figures
| ID | Criterion | Tests |
|---|---|---|
| API-07.1 | POST /api/v1/ingest/open-banking and /api/v1/ingest/cis-statement turn bank transactions or CIS statements into calculation fields; bank transactions that cannot be recognised for certain are listed for review rather than used. |
2 tests for API-07.1
|
API-08 Tracking clients through the year (organisations)
| ID | Criterion | Tests |
|---|---|---|
| API-08.1 | POST /api/v1/saas/clients adds a client under the organisation's own reference (never a NINO or UTR) with their profile; updates, history and deletion are under /api/v1/saas/clients/{id}. |
2 tests for API-08.1
|
| API-08.2 | Given income so far is added, then a new forecast is returned and kept in the history. | 2 tests for API-08.2
|
| API-08.3 | Given a client is deleted, then everything held about them is deleted. | 1 test for API-08.3
|
API-09 A stable contract
| ID | Criterion | Tests |
|---|---|---|
| API-09.1 | Given a release, when it removes an operation or a returned field, or makes a field newly required, then the release pipeline blocks it unless the change is approved and recorded. | 3 tests for API-09.1
|
| API-09.2 | Full documentation is at /docs and /openapi.json. |
1 test for API-09.2
|
EMB-01 Start a journey
| ID | Criterion | Tests |
|---|---|---|
| EMB-01.1 | Given the embedded way is closed, then 403 "Question pages inside another app are switched off". | 1 test for EMB-01.1
|
| EMB-01.2 | Given a kind other than tax_estimate that is not switched on inside an app, then 403 naming the kind. |
1 test for EMB-01.2
|
| EMB-01.3 | Given prefill holds an unknown field, an invalid value or a field of a part that is off, then 422 and no journey is made. |
1 test for EMB-01.3
|
| EMB-01.4 | Given continue_url or back_url is not on one of the organisation's app hosts, then 422 INVALID_RETURN_URL. |
6 tests for EMB-01.4
|
EMB-02 The customer opens the link
| ID | Criterion | Tests |
|---|---|---|
| EMB-02.1 | Given a new journey, when the customer opens start_url, then a session starts under the organisation's settings and the journey is tied to that browser. |
1 test for EMB-02.1
|
| EMB-02.2 | Given a back_url, then the first question's back link and "Go back to {organisation}" on every page go to it; given none, the first question has no back link. The customer never lands on the calculator's own start page. |
1 test for EMB-02.2
|
| EMB-02.3 | Given the customer selects the service name or the logo in the header inside an app, then the page reloads. The customer never leaves the app's journey by them. | 1 test for EMB-02.3
|
| EMB-02.4 | Given the link is opened in a second browser, then "This link has already been used" (409) is shown, with a pointer back to the app. | 3 tests for EMB-02.4
|
| EMB-02.5 | Given the journey has expired (60 minutes by default) or does not exist, then "This link has expired" (404) is shown. | 1 test for EMB-02.5
|
| EMB-02.6 | Given the organisation closes the embedded way or the kind after the journey was made, then "This service is not available" is shown. | 1 test for EMB-02.6
|
| EMB-02.7 | Given the same browser opens the link again, then the customer carries on where they left off. | 1 test for EMB-02.7
|
EMB-03 Questions with the app's answers
| ID | Criterion | Tests |
|---|---|---|
| EMB-03.1 | Given the settings say skip and confirm_prefill is not set, then questions the app's answers fill completely are skipped, and still listed on Check your answers. |
2 tests for EMB-03.1
|
| EMB-03.2 | Given the settings say check, or the journey sets confirm_prefill: true, then those questions are shown filled in for the customer to check. This applies to every kind of journey. |
3 tests for EMB-03.2
|
| EMB-03.3 | Given reading records is on inside an app, then records are read as each part's choice says (ADM-07), after the customer gives permission, and only for what the app did not send (DAT-04). | 2 tests for EMB-03.3
|
| EMB-03.4 | Only the organisation's parts and years are asked, as on the standalone pages (CAL-02 to CAL-08). | 1 test for EMB-03.4
|
EMB-04 Sending the result back
| ID | Criterion | Tests |
|---|---|---|
| EMB-04.1 | Given the result page, when the customer selects "Continue", then the result is saved and they go to continue_url?resultId=.... |
2 tests for EMB-04.1
|
| EMB-04.2 | Given a back_url, then the result page also offers "Go back to {organisation} without sending this estimate", and nothing is saved. |
1 test for EMB-04.2
|
EMB-05 Collecting the result
| ID | Criterion | Tests |
|---|---|---|
| EMB-05.1 | The result carries kind, the request used, a summary (for a tax estimate: the tax for the year, the balance and what to pay when), and the whole calculation, forecast, tax_so_far or helper result for its kind. |
19 tests for EMB-05.1
|
| EMB-05.2 | Given another organisation's key, then the result is not found: an organisation only sees its own journeys and results. | 3 tests for EMB-05.2
|
| EMB-05.3 | Given 24 hours have passed (default), then the result has expired. | 1 test for EMB-05.3
|
| EMB-05.4 | GET /api/v1/saas/journeys/{id} returns the status: not_started, started or completed, with the result_id once completed. |
2 tests for EMB-05.4
|
EMB-06 Being told the customer has finished
| ID | Criterion | Tests |
|---|---|---|
| EMB-06.1 | Given a notify address (ADM-15), when the customer selects Continue, then the app receives <kind>.completed with the journey and result IDs, signed, and collects the figures with its key. |
2 tests for EMB-06.1
|
DAT-01 An app asks the service to read the figures
| ID | Criterion | Tests |
|---|---|---|
| DAT-01.1 | Given figures the app sent, then they are always used; read figures only fill fields the app left out. | 1 test for DAT-01.1
|
| DAT-01.2 | Given a read figure belongs to a part that is off or set to ask, then it is not used. |
1 test for DAT-01.2
|
| DAT-01.3 | The response returns the calculation, every figure read with its source and whether it was used, and the sources that were unavailable. |
2 tests for DAT-01.3
|
| DAT-01.4 | Given no data source is on for the API, then 409 "No data sources are switched on. Send all figures in the request instead." | 1 test for DAT-01.4
|
| DAT-01.5 | Given an invalid NINO, then 422 INVALID_NINO; given no customer token, then 422; given an Authorization header that is not a Bearer token, then 401. |
1 test for DAT-01.5
|
| DAT-01.6 | Given a source fails or does not answer, then the calculation still runs on what was sent and read, and the source is listed as unavailable. | 1 test for DAT-01.6
|
DAT-02 The customer chooses to fill answers from records (pages)
| ID | Criterion | Tests |
|---|---|---|
| DAT-02.1 | Given reading is on for the way of use and at least one part can be read, when the customer has chosen the tax year, then they are asked "Do you want us to fill in some answers from HMRC records?", with the parts that can be filled listed and their National Insurance number asked. | 3 tests for DAT-02.1
|
| DAT-02.2 | Given "Yes", then the customer signs in and gives permission before anything is read; given "No, I will enter everything myself", then every question is asked. | 3 tests for DAT-02.2
|
| DAT-02.3 | Given a figure was read, then it is labelled as from HMRC records; given the customer changes it, then the label is removed. | 1 test for DAT-02.3
|
DAT-03 Check or read without asking
| ID | Criterion | Tests |
|---|---|---|
| DAT-03.1 | Given a part is set to check, then read figures are filled in on that part's pages for the customer to confirm or change. |
2 tests for DAT-03.1
|
| DAT-03.2 | Given a part is set to auto, then pages fully answered from records are skipped, and the figures are listed on Check your answers with a change link; anything not read is asked. |
2 tests for DAT-03.2
|
DAT-04 Reading inside an app
| ID | Criterion | Tests |
|---|---|---|
| DAT-04.1 | Given a journey inside an app and reading on for the embedded way, then the same choice and permission step as DAT-02 is offered, under the organisation's settings. | 2 tests for DAT-04.1
|
| DAT-04.2 | Given the app also sent some figures, then records are offered only for what it did not send, and a figure the app sent is never replaced, as through the API (DAT-01); given it sent everything the records could fill, then records are not offered (records are offered at all only where a switched-on source can fill a part the settings read). | 2 tests for DAT-04.2
|
DAT-05 Reading for the extra capabilities
| ID | Criterion | Tests |
|---|---|---|
| DAT-05.1 | Tax so far: given pay is read from records, then the pay and tax so far come from HMRC's Real Time Information after permission (API: nino and hmrc_access_token in POST /api/v1/tax-so-far). |
2 tests for DAT-05.1
|
| DAT-05.2 | Making Tax Digital "explain HMRC's estimate": HMRC's own tax calculation is read with permission and explained line by line. | 3 tests for DAT-05.2
|
| DAT-05.3 | Customer accounts: pay and tax so far and the Self Assessment account's bills and credit are read with permission, and the customer checks them before they are saved. | 2 tests for DAT-05.3
|
DAT-06 What is never done
| ID | Criterion | Tests |
|---|---|---|
| DAT-06.1 | Nothing is ever written to HMRC. | 1 test for DAT-06.1
|
| DAT-06.2 | Only the customer's own record is read, with their consent (HMRC OAuth scope read:self-assessment); DVLA data is public register information found by a registration number the customer gives. |
3 tests for DAT-06.2
|
| DAT-06.3 | Read figures are used for that estimate only. On the pages they are kept in the customer's session and deleted with it (CAL-10); nothing read through the API is kept; only a customer account the customer chose to keep holds them. | 2 tests for DAT-06.3
|
OPT-01 Payment plan amounts
| ID | Criterion | Tests |
|---|---|---|
| OPT-01.1 | Given the bills due on 31 January and 31 July, and this year's forecast, then the amount is the lowest fixed amount, rounded up to the nearest pound, so that the money collected by each deadline covers everything due by then. | 1 test for OPT-01.1
|
| OPT-01.2 | The forecast uses, in order of preference: the customer's own estimate, a seasonal adjustment, a blend of this year and last, this year scaled up, then last year; the other methods give the lowest and highest forecast. | 24 tests for OPT-01.2
|
| OPT-01.3 | Given a new Direct Debit, then the first collection is 5 working days after the request (3 if the customer has paid HMRC by Direct Debit from the same bank before), and dates on weekends or GOV.UK bank holidays move as GOV.UK sets out. | 1 test for OPT-01.3
|
| OPT-01.4 | Given a bill due before the first collection, then it is listed as "pay another way". | 23 tests for OPT-01.4
|
| OPT-01.5 | Given the customer has overdue tax, then they are shown the Time to Pay route instead, as GOV.UK requires them to be up to date first. | 2 tests for OPT-01.5
|
| OPT-01.6 | The service only gives the amount: HMRC has no public API to set up a plan, so the customer is told how to set it up in their HMRC online account. Nothing is stored for an API call. | 1 test for OPT-01.6
|
OPT-02 Tax so far this year
| ID | Criterion | Tests |
|---|---|---|
| OPT-02.1 | Given figures since 6 April, then they are forecast to the whole year with a low to high range, the year's tax is worked out with the calculator, and the tax so far is the year's tax times income so far divided by the forecast income. | 1 test for OPT-02.1
|
| OPT-02.2 | Given tax already paid (PAYE, CIS, student loan deductions), then it is taken off to show what has built up. | 2 tests for OPT-02.2
|
| OPT-02.3 | Every step is shown on the result page and returned to apps in explanation. |
1 test for OPT-02.3
|
OPT-03 Making Tax Digital for Income Tax helpers
| ID | Criterion | Tests |
|---|---|---|
| OPT-03.1 | Given a helper is used, then nothing is ever sent to HMRC. | 1 test for OPT-03.1
|
| OPT-03.2 | Given a customer used one helper, when they open the next in the same visit, then the update periods (and, for the same update, its businesses, turnover and residential finance costs) are filled in for them to check. | 1 test for OPT-03.2
|
| OPT-03.3 | Given a customer with an account asks for reminders, then emails are sent 14 and 3 days before each deadline. | 2 tests for OPT-03.3
|
OPT-04 Tax tools
| ID | Criterion | Tests |
|---|---|---|
| OPT-04.1 | Given a tool, then it asks one question per page, shows Check your answers and a result, and is at the service's address and at /o/{organisation}/.... |
2 tests for OPT-04.1
|
| OPT-04.2 | Given the tool's API, then it takes the same answers as JSON and checks them the same way. | 3 tests for OPT-04.2
|
| OPT-04.3 | Given an organisation switches a tool on inside its app, then its app can start a journey of that tool's kind with any of the answers the API takes; the customer answers the rest, selects "Continue to {organisation}", and the app collects the result: a summary (heading, main figure, data) and the whole result (EMB-01 to EMB-06). | 19 tests for OPT-04.3
|
OPT-05 Document reading
| ID | Criterion | Tests |
|---|---|---|
| OPT-05.1 | Given an upload, then figures are filled in for the customer to check, and the document is not kept. | 1 test for OPT-05.1
|
| OPT-05.2 | Given any upload, then the document is read on the service itself and never sent to an AI model. | 2 tests for OPT-05.2
|
| OPT-05.3 | Given a digital P60, then the pay and tax are read from the row "In this employment", never "Total for year", and the tax year from "Tax year to 5 April". These are the rows HMRC's P60 specification sets out (RD1, HMRC 01/25). | 1 test for OPT-05.3
|
| OPT-05.4 | Given another statement (dividends, interest, letting agent, pension contributions), then a figure is read where a line starts with its usual wording. A figure not found is left for the customer to type. | 1 test for OPT-05.4
|
| OPT-05.5 | Given a scan, a photo or a PDF without text, then nothing is read, and the customer is asked to download the document from their employer's or provider's online service, or type the figures. There is no OCR. | 1 test for OPT-05.5
|
| OPT-05.6 | Given HMRC records gave a part's figures, then no document is asked for (structured data first). | 1 test for OPT-05.6
|
| OPT-05.7 | The test site reads only its sample documents, in the same way. | 1 test for OPT-05.7
|
OPT-06 Customer accounts
| ID | Criterion | Tests |
|---|---|---|
| OPT-06.1 | Given a customer signs in with GOV.UK One Login or creates an account (email and a password of at least 12 characters, not commonly used), then they answer a few questions and see their forecast tax, next bill and the amount to put aside. | 3 tests for OPT-06.1
|
| OPT-06.2 | Given they upload a bank statement CSV, then only transactions recognised for certain are used, the rest are listed to check, and only totals are kept. | 2 tests for OPT-06.2
|
| OPT-06.3 | Given the amount to pay changes by £10 and 10% or more, then the customer is emailed. | 3 tests for OPT-06.3
|
| OPT-06.4 | Given they ask, then they can download everything held about them as JSON, or delete their account; given 2 years without use, the account is deleted. | 3 tests for OPT-06.4
|
| OPT-06.5 | Given 5 wrong passwords, then the address is locked for 15 minutes, whether or not an account exists. | 1 test for OPT-06.5
|
PLN-01 Asking for a plan
| ID | Criterion | Tests |
|---|---|---|
| PLN-01.1 | Given the planner is on for the organisation's API, then the response gives the calculation, the tax year, the parts, the question pages the customer will see as far as is known, whether records are offered and which, whether the customer checks the answers, the prefill, and a list of decisions, each with its reason. | 2 tests for PLN-01.1
|
| PLN-01.2 | Given the planner is off for the organisation's API, then 403. | 1 test for PLN-01.2
|
PLN-02 Starting a planned journey
| ID | Criterion | Tests |
|---|---|---|
| PLN-02.1 | Given the planner is on inside the organisation's app, then the response gives the plan and the journey: its start_url and when it expires. The customer is sent there, and the result comes back as from any journey (EMB-02 to EMB-06). |
2 tests for PLN-02.1
|
| PLN-02.2 | Given continue_url or back_url is not on one of the organisation's app hosts, then 422 INVALID_RETURN_URL. |
1 test for PLN-02.2
|
| PLN-02.3 | Given the planner is off inside the organisation's app, then 403. | 1 test for PLN-02.3
|
PLN-03 The calculation
| ID | Criterion | Tests |
|---|---|---|
| PLN-03.1 | Given a purpose of tax_estimate, or any kind of journey switched on inside the organisation's app (EMB-01), then that is the journey's calculation. |
1 test for PLN-03.1
|
| PLN-03.2 | Given an unknown purpose, then 422 listing the purposes; given one switched off inside the app, then 403. | 1 test for PLN-03.2
|
PLN-04 The tax year
| ID | Criterion | Tests |
|---|---|---|
| PLN-04.1 | Given the app names a year, or describes it with which_year, then that year is used if it is offered. Otherwise 422 TAX_YEAR_NOT_OFFERED, listing the years offered. |
1 test for PLN-04.1
|
| PLN-04.2 | Given nothing about the year, and only one year offered, then that year is used. | 1 test for PLN-04.2
|
| PLN-04.3 | Given nothing about the year, and several years offered, then the customer chooses one of them on the first question. | 1 test for PLN-04.3
|
PLN-05 The questions
| ID | Criterion | Tests |
|---|---|---|
| PLN-05.1 | Given the app lists the customer's kinds of income and says the list is complete, then other kinds of income are not asked about. The income question is answered with that list, and its pages follow. | 3 tests for PLN-05.1
|
| PLN-05.2 | Given the app lists some income, or sends figures, without saying the list is complete, then the customer is shown the income question with what the app knows ticked, to add any other. | 1 test for PLN-05.2
|
| PLN-05.3 | Given the app sent figures for a part, then that part is always kept. | 1 test for PLN-05.3
|
| PLN-05.4 | Given a kind of income the organisation does not use, then it is not asked about, with that reason. | 1 test for PLN-05.4
|
| PLN-05.5 | Given a page of a part the plan left out, when the customer opens it by its address, then it does not open. | 1 test for PLN-05.5
|
PLN-06 HMRC records
| ID | Criterion | Tests |
|---|---|---|
| PLN-06.1 | The customer agreed in the app. | 1 test for PLN-06.1
|
| PLN-06.2 | The organisation reads records inside its app. | 1 test for PLN-06.2
|
| PLN-06.3 | A switched-on source can fill something the app did not send. | 1 test for PLN-06.3
|
PLN-07 Checking the app's answers
| ID | Criterion | Tests |
|---|---|---|
| PLN-07.1 | Given the app asks for it, or the organisation's settings show the app's answers to check, then the customer sees them filled in (EMB-03). | 1 test for PLN-07.1
|
| PLN-07.2 | Otherwise, questions the app's answers fill are skipped. | 1 test for PLN-07.2
|
PLN-08 Never wider, and no AI
| ID | Criterion | Tests |
|---|---|---|
| PLN-08.1 | Given any plan, then the customer's settings are the organisation's with parts removed and, when the plan says so, records not read. A plan never adds a part, a tax year, a way of use or a data source. | 1 test for PLN-08.1
|
| PLN-08.2 | Given any request, then it is decided by the written rules only. Nothing is sent to an AI model, and the only service outside the calculator reached is HMRC, for the records the customer agreed to (PLN-06, PLN-11). | 1 test for PLN-08.2
|
PLN-09 Switching it on and off
| ID | Criterion | Tests |
|---|---|---|
| PLN-09.1 | Given the feature is switched off for the service, then its API returns 404. | 1 test for PLN-09.1
|
| PLN-09.2 | Given it is switched off for one organisation, then that organisation's app gets 403 and the others are unaffected. | 1 test for PLN-09.2
|
| PLN-09.3 | Given the feature is on, then the calculator's own pages, other organisations' journeys and journeys started without a plan work exactly as without it. | 1 test for PLN-09.3
|
PLN-10 Questions for an app with its own screens
| ID | Criterion | Tests |
|---|---|---|
| PLN-10.1 | Given the planner is on for the organisation's API calculations, when the app sends what it knows, the answers so far and the pages the customer has been through, then the response is the next page to show: each question's name, type, label, hint, whether it is required, its choices and the questions each choice brings, and the API field it fills. | 3 tests for PLN-10.1
|
| PLN-10.2 | Given the plan answered a page from what the app knows, then that page is not given, unless the customer is to check the app's answers. | 2 tests for PLN-10.2
|
| PLN-10.3 | Given the customer's answers on a page are wrong, then the same page comes back with what is wrong, worded as the calculator's own pages word it. | 1 test for PLN-10.3
|
| PLN-10.4 | Given nothing is left to ask, then the response holds the whole calculation and the figures an app usually needs. | 2 tests for PLN-10.4
|
| PLN-10.5 | Given a purpose other than the tax estimate, then 422: a tax tool's own API lists its questions. | 1 test for PLN-10.5
|
| PLN-10.6 | Given the planner is off for the organisation's API calculations, then 403. | 1 test for PLN-10.6
|
PLN-11 HMRC records for an app with its own screens
| ID | Criterion | Tests |
|---|---|---|
| PLN-11.1 | Given the plan offers records and the app sends the customer's NINO and HMRC token, then the records are read once and fill only what neither the app nor the customer gave. The response lists them, and the page they fill is given for the customer to check. | 1 test for PLN-11.1
|
| PLN-11.2 | Given the app sent a figure, then a figure from the records never replaces it. | 1 test for PLN-11.2
|