Skip to main content

This is a test site with dummy HMRC services. Do not enter real personal information. How it works.

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

IDCriterionTests
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
  • test_profiles::test_pages_of_parts_that_are_off_do_not_open_by_their_address
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[benefits]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[blind_persons_allowance]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[capital_gains]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[child_benefit]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[dividends]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[employment]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[foreign]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[gift_aid]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[investment_reliefs]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[job_expenses]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[leaving_job]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[life_policies]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[marriage_allowance]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[married_couples_allowance]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[other_income]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[partnership]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[payments_on_account]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[penalties]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[pension_contributions]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[pensions]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[property]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[residence]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[savings]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[scotland]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[self_employment]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[state_benefits]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[student_loans]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[tax_code_collection]
  • test_switches::test_a_part_switched_off_is_closed_and_changes_nothing_else[trusts]
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
  • test_journeys::test_journey[J57]
  • test_profiles::test_fields_of_modules_that_are_off_are_reported
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
  • test_acceptance_criteria::test_answers_to_a_part_switched_off_since_are_ignored
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
  • test_profiles::test_settings_form_errors
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
  • test_profiles::test_marriage_choices_follow_their_own_parts
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
  • test_profiles::test_parts_records_can_fill_and_choices_from_older_settings
  • test_profiles::test_settings_saved_with_the_old_broad_parts_keep_working
ADM-01.7 GET /api/v1/modules lists every part, whether it is on, and its fields.
2 tests for ADM-01.7
  • test_acceptance_criteria::test_the_modules_api_lists_every_part
  • test_profiles::test_service_settings_page_switches_the_public_pages_to_basic

ADM-02 Scottish Income Tax

IDCriterionTests
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
  • test_journeys::test_journey[J80]
  • test_profiles::test_scottish_income_tax_is_a_switch_on_the_ready_made_sets
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
  • test_journeys::test_journey[J80]
  • test_profiles::test_scottish_income_tax_is_a_switch_on_the_ready_made_sets
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
  • test_journeys::test_journey[J80]
  • test_profiles::test_scottish_income_tax_is_a_switch_on_the_ready_made_sets

ADM-03 Tax years offered

IDCriterionTests
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
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_acceptance_criteria::test_a_year_switched_off_is_refused_by_the_tax_so_far_and_making_tax_digital
  • test_journey_planner::test_the_tax_year_rules
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_app_journeys::test_a_journey_without_a_tax_year_is_started_when_the_latest_year_is_switched_off
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_acceptance_criteria::test_tax_years_and_ways_in_the_settings
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
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
  • test_web::test_how_the_tax_years_covered_are_named
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
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_acceptance_criteria::test_tax_years_and_ways_in_the_settings

ADM-04 Ways of use

IDCriterionTests
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
  • test_journeys::test_journey[J55]
  • test_profiles::test_switching_off_the_public_pages_and_the_api
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
  • test_profiles::test_settings_form_errors
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
  • test_acceptance_criteria::test_tax_years_and_ways_in_the_settings

ADM-05 Reading answers from records, per way of use

IDCriterionTests
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
  • test_tenancy::test_each_organisation_chooses_its_own_data_sources
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
  • test_acceptance_criteria::test_reading_records_through_the_api_with_nothing_to_read

ADM-06 Data sources

IDCriterionTests
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
  • test_tenancy::test_each_organisation_chooses_its_own_data_sources
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
  • test_web::test_admin_sign_in_and_save
ADM-06.3 GET /api/v1/data-sources shows which sources are on.
1 test for ADM-06.3
  • test_acceptance_criteria::test_the_data_sources_api_lists_each_source_and_whether_it_is_on

ADM-07 Each part's answers: ask, check or read

IDCriterionTests
ADM-07.1 Given ask, then nothing is read for that part and the customer enters it.
2 tests for ADM-07.1
  • test_journeys::test_journey[J60]
  • test_web::test_prefill_follows_each_parts_reading_choice
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
  • test_journeys::test_journey[J59]
  • test_web::test_prefill_follows_each_parts_reading_choice
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
  • test_journeys::test_journey[J07]
  • test_web::test_prefill_follows_each_parts_reading_choice
ADM-07.4 GET /api/v1/modules shows each part's choice as read_automatically.
2 tests for ADM-07.4
  • test_acceptance_criteria::test_the_modules_api_lists_every_part
  • test_tenancy::test_each_part_has_its_own_reading_choice

ADM-08 What else can be worked out (capabilities)

IDCriterionTests
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
  • test_mtd::test_helpers_follow_the_settings
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_categories]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_check]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_deadlines]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_explain]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_quarterly]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_status]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_year_end]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[payment_plan]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[tax_so_far]
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
  • test_journeys::test_journey[J67]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_categories]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_check]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_deadlines]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_explain]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_quarterly]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_status]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_year_end]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[payment_plan]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[tax_so_far]
  • test_tax_so_far::test_not_offered_where_the_settings_switch_it_off
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
  • test_acceptance_criteria::test_payment_plans_start_on_for_the_services_pages_and_api

ADM-09 Features for the whole service

IDCriterionTests
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
  • test_features::test_admin_switches_a_feature_off_and_on
  • test_journeys::test_journey[J40]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[benefits]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[corporation_tax]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[demo]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[director_pay]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[document_reading]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[filing_check]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[inheritance_tax]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[journey_planner]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[mtd]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[partnership_return]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[paye_check]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[payment_plan]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[payroll]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[property_cgt]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[property_tax]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[saas]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[tax_so_far]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[trust_return]
  • test_switches::test_a_feature_switched_off_closes_every_page_and_route_and_changes_nothing_else[vat]
ADM-09.2 Given a feature is switched back on, then its finer settings are as they were.
1 test for ADM-09.2
  • test_acceptance_criteria::test_a_feature_switched_back_on_keeps_its_settings
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
  • test_features::test_calculator_works_without_any_feature[]
  • test_features::test_calculator_works_without_any_feature[none-of-these]
  • test_features::test_same_calculation_with_features_installed
  • test_journeys::test_journey[J42]

ADM-10 Features for one organisation

IDCriterionTests
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
  • test_journeys::test_journey[J78]
  • test_switches::test_a_feature_switched_off_for_one_organisation[benefits]
  • test_switches::test_a_feature_switched_off_for_one_organisation[corporation_tax]
  • test_switches::test_a_feature_switched_off_for_one_organisation[director_pay]
  • test_switches::test_a_feature_switched_off_for_one_organisation[document_reading]
  • test_switches::test_a_feature_switched_off_for_one_organisation[filing_check]
  • test_switches::test_a_feature_switched_off_for_one_organisation[inheritance_tax]
  • test_switches::test_a_feature_switched_off_for_one_organisation[journey_planner]
  • test_switches::test_a_feature_switched_off_for_one_organisation[mtd]
  • test_switches::test_a_feature_switched_off_for_one_organisation[partnership_return]
  • test_switches::test_a_feature_switched_off_for_one_organisation[paye_check]
  • test_switches::test_a_feature_switched_off_for_one_organisation[payment_plan]
  • test_switches::test_a_feature_switched_off_for_one_organisation[payroll]
  • test_switches::test_a_feature_switched_off_for_one_organisation[property_cgt]
  • test_switches::test_a_feature_switched_off_for_one_organisation[property_tax]
  • test_switches::test_a_feature_switched_off_for_one_organisation[tax_so_far]
  • test_switches::test_a_feature_switched_off_for_one_organisation[trust_return]
  • test_switches::test_a_feature_switched_off_for_one_organisation[vat]

ADM-11 Documents customers can upload

IDCriterionTests
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
  • test_documents::test_customer_fills_in_pay_from_a_p60
  • test_documents::test_settings_choose_the_parts
  • test_journeys::test_journey[J63]
ADM-11.2 Given no reader is configured, then the upload option is not offered.
1 test for ADM-11.2
  • test_acceptance_criteria::test_no_upload_without_a_reader

ADM-12 Answers an app sends (organisations)

IDCriterionTests
ADM-12.1 Given skip, when a journey starts with answers, then fully answered questions are skipped.
2 tests for ADM-12.1
  • test_journeys::test_journey[J52]
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_journeys::test_journey[J61]
  • test_tenancy::test_embedded_journey_checks
  • test_tenancy::test_organisation_chooses_whether_customers_check_what_its_app_sends

ADM-13 What the result shows

IDCriterionTests
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
  • test_acceptance_criteria::test_a_summary_leaves_the_working_out_of_every_result_page
  • test_profiles::test_service_settings_page_switches_the_public_pages_to_basic

ADM-14 Apps customers can be sent back to (organisations)

IDCriterionTests
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
  • test_journeys::test_journey[J25]
  • test_payment_plan::test_return_addresses_are_checked[http://plans.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[https://evil.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[https://user:pw@plans.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[javascript:alert(1)]
  • test_tenancy::test_embedded_journey_checks
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
  • test_profiles::test_return_addresses

ADM-15 Telling the app when a customer finishes (organisations)

IDCriterionTests
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
  • test_background::test_signature_follows_standard_webhooks
  • test_background::test_the_app_is_told_when_a_customer_finishes
  • test_journeys::test_journey[J62]
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
  • test_background::test_a_notification_that_fails_is_tried_again
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
  • test_background::test_addresses_on_a_private_network_are_refused
  • test_background::test_notify_address_must_be_on_the_organisations_app
  • test_background::test_organisation_admin_makes_a_signing_secret

ADM-16 Organisations and their API keys

IDCriterionTests
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
  • test_saas::test_admin_adds_organisation_and_key_shown_once
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
  • test_journeys::test_journey[J39]
  • test_saas::test_rate_limit_quota_revoked_and_suspended
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
  • test_journeys::test_journey[J39]
  • test_saas::test_rate_limit_quota_revoked_and_suspended
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
  • test_journeys::test_journey[J39]
  • test_saas::test_organisations_cannot_see_each_others_clients

ADM-17 Organisation administrators

IDCriterionTests
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
  • test_journeys::test_journey[J58]
  • test_tenancy::test_service_admin_adds_an_organisation_admin_who_manages_its_settings
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
  • test_acceptance_criteria::test_an_app_reads_its_settings_and_cannot_change_them

ADM-18 Audit log

IDCriterionTests
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
  • test_acceptance_criteria::test_the_audit_log_records_who_when_where_and_what_changed
  • test_api::test_admin_can_enable_configured_feed_and_it_is_audited

ADM-19 Rates

IDCriterionTests
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
  • test_api::test_what_if_does_not_change_live_rates
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
  • test_acceptance_criteria::test_rates_that_lose_a_source_do_not_load

CAL-01 Start page

IDCriterionTests
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
  • test_acceptance_criteria::test_the_start_page_says_what_is_estimated_and_how_long_it_takes
  • test_web::test_the_start_page_names_the_tax_years_supported
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
  • test_acceptance_criteria::test_the_start_page_warns_it_is_an_estimate_and_links_to_take_home_pay
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
  • test_journeys::test_journey[J50]
  • test_tenancy::test_an_organisations_start_page_names_the_tax_years_it_offers
  • test_tenancy::test_organisation_address_uses_its_own_modules

CAL-02 Tax year

IDCriterionTests
CAL-02.1 Given the years offered, when the question is shown, then only those years are listed.
5 tests for CAL-02.1
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_acceptance_criteria::test_figures_not_announced_yet_are_said

CAL-03 Where the customer pays tax

IDCriterionTests
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
  • test_journeys::test_journey[J80]
  • test_profiles::test_scottish_income_tax_is_a_switch_on_the_ready_made_sets
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
  • test_acceptance_criteria::test_without_the_residence_part_everyone_is_treated_as_uk_resident

CAL-04 Types of income

IDCriterionTests
CAL-04.1 Given a part is off, then its kind of income is not offered.
2 tests for CAL-04.1
  • test_journeys::test_journey[J57]
  • test_profiles::test_pages_and_income_types_follow_the_modules
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
  • test_web::test_checkboxes_none_is_exclusive_without_js

CAL-05 Question pages

IDCriterionTests
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
  • test_flows::test_calculator_pages_open_only_in_order
  • test_web::test_pages_out_of_order_redirect
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
  • test_flows::test_no_session_reaches_a_page_in_the_middle_of_a_flow
  • test_web::test_no_session_redirects_to_start
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
  • test_govuk_patterns::test_calculator_pages_follow_govuk_patterns
  • test_web::test_validation_errors_follow_govuk_pattern
CAL-05.4 Every page has a back link, works without JavaScript and carries a CSRF token.
3 tests for CAL-05.4
  • test_security::test_every_form_needs_its_csrf_token
  • test_web::test_back_link_and_page_heading
  • test_web::test_csrf_required

CAL-06 Filling answers from HMRC records

IDCriterionTests
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
  • test_integrations::test_hmrc_authorization_url_has_state_and_scope
  • test_journeys::test_journey[J01]
  • test_journeys::test_journey[J09]
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
  • test_journeys::test_journey[J59]
  • test_web::test_prefill_follows_each_parts_reading_choice
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
  • test_journeys::test_journey[J07]
  • test_web::test_prefill_follows_each_parts_reading_choice
CAL-06.4 Given a source is unavailable, then its questions are asked and nothing fails.
2 tests for CAL-06.4
  • test_integrations::test_hmrc_error_means_ask_the_customer
  • test_journeys::test_journey[J09]

CAL-07 Filling answers from a document

IDCriterionTests
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
  • test_documents::test_customer_fills_in_pay_from_a_p60
  • test_journeys::test_journey[J63]
CAL-07.2 Given the figures for that part came from HMRC records, then no upload is offered.
1 test for CAL-07.2
  • test_documents::test_no_document_is_asked_for_figures_hmrc_records_gave
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
  • test_documents::test_upload_problems_are_explained
CAL-07.4 The link only appears on the question page itself, in the order of the questions.
1 test for CAL-07.4
  • test_acceptance_criteria::test_a_document_is_offered_only_on_its_question_page_in_order

CAL-08 Check your answers

IDCriterionTests
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
  • test_journeys::test_journey[J01]
  • test_journeys::test_journey[J07]
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
  • test_acceptance_criteria::test_a_changed_answer_goes_back_to_check_your_answers_after_any_new_questions

CAL-09 The result

IDCriterionTests
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
  • test_acceptance_criteria::test_the_result_says_what_to_pay_or_get_back
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
  • test_journeys::test_journey[J01]
  • test_paying::test_every_payment_is_listed_with_its_date_and_a_weekend_deadline_says_when_to_pay
  • test_web::test_full_journey_matches_hand_calculation
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
  • test_journeys::test_journey[J50]
  • test_journeys::test_journey[J52]
  • test_profiles::test_service_settings_page_switches_the_public_pages_to_basic
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
  • test_acceptance_criteria::test_the_result_says_what_to_know_how_to_pay_less_and_what_happens_next
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
  • test_acceptance_criteria::test_the_result_says_what_to_know_how_to_pay_less_and_what_happens_next

CAL-10 Time out and privacy of answers

IDCriterionTests
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
  • test_acceptance_criteria::test_the_timeout_warning_and_the_end_of_a_session
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
  • test_background::test_answers_are_deleted_once_a_session_is_unused_for_15_minutes
  • test_web::test_delete_answers_clears_session

CAL-11 Take-home pay

IDCriterionTests
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
  • test_api::test_quick_post_and_get
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
  • test_web::test_take_home_form

CAL-12 Rates and help pages

IDCriterionTests
CAL-12.1 /tax-rates shows every rate and allowance for a year, each with its source.
1 test for CAL-12.1
  • test_acceptance_criteria::test_the_rates_page_and_the_links_on_every_page
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
  • test_acceptance_criteria::test_the_rates_page_and_the_links_on_every_page

API-01 Calling as an organisation

IDCriterionTests
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
  • test_journeys::test_journey[J54]
  • test_tenancy::test_organisation_api_follows_its_settings
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
  • test_journeys::test_journey[J25]
  • test_saas::test_rate_limit_quota_revoked_and_suspended
  • test_security::test_organisation_api_needs_a_key
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
  • test_saas::test_admin_adds_organisation_and_key_shown_once
  • test_saas::test_rate_limit_quota_revoked_and_suspended
API-01.4 GET /api/v1/saas/settings shows the organisation's settings, read only.
1 test for API-01.4
  • test_acceptance_criteria::test_an_app_reads_its_settings_and_cannot_change_them

API-02 The full calculation

IDCriterionTests
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
  • test_api::test_minimal_single_field
  • test_paying::test_the_default_year_follows_the_date_of_the_estimate
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
  • test_app_journeys::test_a_journey_without_a_tax_year_is_started_when_the_latest_year_is_switched_off
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
API-02.3 Given an unknown field name, then 422 lists every problem; nothing is calculated.
1 test for API-02.3
  • test_api::test_unknown_field_rejected
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
  • test_profiles::test_scottish_income_tax_is_a_switch_on_the_ready_made_sets
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2023/24]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2024/25]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2025/26]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2026/27]
  • test_switches::test_a_tax_year_switched_off_is_closed_and_changes_nothing_else[2027/28]
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
  • test_profiles::test_switching_off_the_public_pages_and_the_api
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
  • test_calculations::test_rates_provenance_in_response
  • test_calculations::test_scenario[aa_taper_ruk]
  • test_calculations::test_scenario[aa_taper_scotland]
  • test_calculations::test_scenario[additional_150k]
  • test_calculations::test_scenario[averaging_2_year]
  • test_calculations::test_scenario[badr_2024]
  • test_calculations::test_scenario[badr_2025]
  • test_calculations::test_scenario[badr_2026]
  • test_calculations::test_scenario[badr_uses_basic_band_first]
  • test_calculations::test_scenario[bpa_2026]
  • test_calculations::test_scenario[carried_interest_2025]
  • test_calculations::test_scenario[cgt_2023_residential]
  • test_calculations::test_scenario[cgt_2024_after_30_oct]
  • test_calculations::test_scenario[cgt_2024_before_30_oct]
  • test_calculations::test_scenario[cgt_losses]
  • test_calculations::test_scenario[class4_2023_and_class2]
  • test_calculations::test_scenario[class4_2024]
  • test_calculations::test_scenario[class4_over_spa]
  • test_calculations::test_scenario[class4_upper_2026]
  • test_calculations::test_scenario[coding_out_filed_late]
  • test_calculations::test_scenario[coding_out_over_3000]
  • test_calculations::test_scenario[coding_out_under_3000]
  • test_calculations::test_scenario[company_car_2026_petrol]
  • test_calculations::test_scenario[div_2023]
  • test_calculations::test_scenario[div_2026]
  • test_calculations::test_scenario[div_upper_2025]
  • test_calculations::test_scenario[div_upper_2026]
  • test_calculations::test_scenario[eis_relief]
  • test_calculations::test_scenario[empty_request]
  • test_calculations::test_scenario[fig_regime]
  • test_calculations::test_scenario[foreign_dividends_ftcr]
  • test_calculations::test_scenario[gift_aid_extends_band]
  • test_calculations::test_scenario[gift_aid_shortfall]
  • test_calculations::test_scenario[govuk_cgt_example_1]
  • test_calculations::test_scenario[govuk_cgt_example_2]
  • test_calculations::test_scenario[govuk_dividend_example]
  • test_calculations::test_scenario[govuk_savings_example]
  • test_calculations::test_scenario[govuk_sl_self_employed_example]
  • test_calculations::test_scenario[hicbc_2023_per_100]
  • test_calculations::test_scenario[hicbc_2024_whole_percent]
  • test_calculations::test_scenario[hicbc_partner_pays]
  • test_calculations::test_scenario[investors_relief_2025]
  • test_calculations::test_scenario[joint_property_share]
  • test_calculations::test_scenario[ma_receive]
  • test_calculations::test_scenario[ma_receive_higher_rate_not_due]
  • test_calculations::test_scenario[ma_transfer]
  • test_calculations::test_scenario[mca_full]
  • test_calculations::test_scenario[mca_tapered]
  • test_calculations::test_scenario[mileage_2025]
  • test_calculations::test_scenario[mileage_2026]
  • test_calculations::test_scenario[mpaa]
  • test_calculations::test_scenario[non_resident_limit]
  • test_calculations::test_scenario[p11d_benefits]
  • test_calculations::test_scenario[pa_most_beneficial_order]
  • test_calculations::test_scenario[pa_taper_110k]
  • test_calculations::test_scenario[poa_includes_child_benefit_charge]
  • test_calculations::test_scenario[poa_not_needed_80pct_at_source]
  • test_calculations::test_scenario[poa_self_employed]
  • test_calculations::test_scenario[property_allowance]
  • test_calculations::test_scenario[psa_basic]
  • test_calculations::test_scenario[psa_higher]
  • test_calculations::test_scenario[relief_cap]
  • test_calculations::test_scenario[remittance_basis_charge]
  • test_calculations::test_scenario[rent_a_room]
  • test_calculations::test_scenario[rent_a_room_shared]
  • test_calculations::test_scenario[ruk_30k_2023/24]
  • test_calculations::test_scenario[ruk_30k_2024/25]
  • test_calculations::test_scenario[ruk_30k_2025/26]
  • test_calculations::test_scenario[ruk_30k_2026/27]
  • test_calculations::test_scenario[ruk_80k]
  • test_calculations::test_scenario[s24_relief]
  • test_calculations::test_scenario[scot_2023_120k]
  • test_calculations::test_scenario[scot_2023_130k]
  • test_calculations::test_scenario[scot_2024_50k]
  • test_calculations::test_scenario[scot_2025_30k]
  • test_calculations::test_scenario[scot_2026_30k]
  • test_calculations::test_scenario[scot_2026_80k]
  • test_calculations::test_scenario[sideways_loss]
  • test_calculations::test_scenario[sl_paye_deducted_credited]
  • test_calculations::test_scenario[sl_pg_and_plan2_2026]
  • test_calculations::test_scenario[sl_plan1_plan2_single_repayment]
  • test_calculations::test_scenario[sl_plan2_2025]
  • test_calculations::test_scenario[sl_unearned_all_counted]
  • test_calculations::test_scenario[taxed_interest_grossed_up]
  • test_calculations::test_scenario[termination_top_slice]
  • test_calculations::test_scenario[top_slicing]
  • test_calculations::test_scenario[trading_allowance]
  • test_calculations::test_scenario[transition_not_in_child_benefit_ani]
  • test_calculations::test_scenario[transition_profit_spread]
  • test_calculations::test_scenario[trust_income_refund]
  • test_calculations::test_scenario[vct_2025_30pct]
  • test_calculations::test_scenario[vct_2026_20pct]
  • test_calculations::test_scenario[voluntary_class2_2025]
  • test_calculations::test_scenario[wfh_2025]
  • test_paying::test_the_api_takes_the_new_answers_and_returns_the_schedule

API-03 One part at a time

IDCriterionTests
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
  • test_acceptance_criteria::test_the_modules_api_lists_every_part
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
  • test_profiles::test_service_settings_page_switches_the_public_pages_to_basic
API-03.3 Given the part is off, then 403 naming the part.
1 test for API-03.3
  • test_profiles::test_service_settings_page_switches_the_public_pages_to_basic

API-04 Checking a request

IDCriterionTests
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
  • test_api::test_validate_endpoint

API-05 Reference data

IDCriterionTests
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
  • test_api::test_health_and_tax_years
  • test_api::test_tax_rates_are_read_only
API-05.2 GET or POST /api/v1/calculate/quick returns take-home pay from a salary.
1 test for API-05.2
  • test_api::test_quick_post_and_get

API-06 Extra calculations through the API

IDCriterionTests
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
  • test_filing_check::test_switched_off_for_a_way_of_use_or_altogether
  • test_journeys::test_journey[J67]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_categories]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_check]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_deadlines]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_explain]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_quarterly]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_status]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[mtd_year_end]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[payment_plan]
  • test_switches::test_a_capability_switched_off_is_not_available_on_the_service_pages[tax_so_far]
  • test_tax_so_far::test_api_follows_the_settings
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
  • test_filing_check::test_the_api_gives_the_same_answer_and_refuses_what_is_wrong

API-07 Turning records into figures

IDCriterionTests
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
  • test_acceptance_criteria::test_cis_statements_become_calculation_fields
  • test_api::test_open_banking_flags_uncertain_items

API-08 Tracking clients through the year (organisations)

IDCriterionTests
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
  • test_journeys::test_journey[J38]
  • test_saas::test_organisation_api_client_lifecycle
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
  • test_journeys::test_journey[J38]
  • test_saas::test_organisation_api_client_lifecycle
API-08.3 Given a client is deleted, then everything held about them is deleted.
1 test for API-08.3
  • test_saas::test_organisation_api_client_lifecycle

API-09 A stable contract

IDCriterionTests
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
  • test_api_contract::test_a_breaking_change_is_caught[<lambda>-POST /api/v1/calculate was removed]
  • test_api_contract::test_a_breaking_change_is_caught[<lambda>-no longer returns]
  • test_api_contract::test_the_api_has_not_broken_for_apps_that_use_it
API-09.2 Full documentation is at /docs and /openapi.json.
1 test for API-09.2
  • test_api_docs::test_the_api_reference_page

EMB-01 Start a journey

IDCriterionTests
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
  • test_acceptance_criteria::test_journeys_are_refused_where_question_pages_inside_an_app_are_closed
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
  • test_app_journeys::test_a_tool_is_only_offered_inside_an_app_when_its_settings_say_so
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
  • test_tenancy::test_embedded_journey_checks
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
  • test_journeys::test_journey[J25]
  • test_payment_plan::test_return_addresses_are_checked[http://plans.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[https://evil.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[https://user:pw@plans.example.com/next]
  • test_payment_plan::test_return_addresses_are_checked[javascript:alert(1)]
  • test_tenancy::test_embedded_journey_checks

EMB-02 The customer opens the link

IDCriterionTests
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
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_app_journeys::test_the_first_question_of_the_estimate_goes_back_to_the_app
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
  • test_app_journeys::test_inside_an_app_the_header_links_reload_the_page
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
  • test_journeys::test_journey[J25]
  • test_payment_plan::test_journey_link_only_works_in_the_first_browser
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_acceptance_criteria::test_a_journey_link_over_its_life
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
  • test_acceptance_criteria::test_a_journey_link_over_its_life
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
  • test_acceptance_criteria::test_a_journey_link_over_its_life

EMB-03 Questions with the app's answers

IDCriterionTests
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
  • test_journeys::test_journey[J52]
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_journeys::test_journey[J61]
  • test_tenancy::test_embedded_journey_checks
  • test_tenancy::test_organisation_chooses_whether_customers_check_what_its_app_sends
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
  • test_app_journeys::test_hmrc_records_fill_only_what_the_app_did_not_send
  • test_journeys::test_journey[J53]
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
  • test_acceptance_criteria::test_inside_an_app_only_the_organisations_parts_and_years_are_asked

EMB-04 Sending the result back

IDCriterionTests
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
  • test_journeys::test_journey[J52]
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_acceptance_criteria::test_the_customer_can_go_back_to_the_app_without_sending_the_estimate

EMB-05 Collecting the result

IDCriterionTests
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
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[benefits0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[benefits1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[capital-gains-tax-on-a-uk-home]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[check-if-you-need-a-tax-return]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[check-your-paye-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[corporation-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[director-salary-or-dividends]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[inheritance-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[partnership-profits]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[payroll]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property2]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[trust-income-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat2]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat3]
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
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
  • test_journeys::test_journey[J25]
  • test_journeys::test_journey[J58]
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
EMB-05.3 Given 24 hours have passed (default), then the result has expired.
1 test for EMB-05.3
  • test_acceptance_criteria::test_a_journey_link_over_its_life
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
  • test_tenancy::test_embedded_journey_gives_the_result_back_to_the_app
  • test_tenancy::test_payment_plan_journey_for_an_organisation

EMB-06 Being told the customer has finished

IDCriterionTests
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
  • test_background::test_the_app_is_told_when_a_customer_finishes
  • test_journeys::test_journey[J62]

DAT-01 An app asks the service to read the figures

IDCriterionTests
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
  • test_acceptance_criteria::test_the_apps_figures_win_and_unavailable_sources_are_listed
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
  • test_tenancy::test_api_uses_only_values_read_for_parts_that_are_read
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
  • test_acceptance_criteria::test_the_apps_figures_win_and_unavailable_sources_are_listed
  • test_tenancy::test_api_uses_only_values_read_for_parts_that_are_read
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
  • test_acceptance_criteria::test_reading_records_through_the_api_with_nothing_to_read
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
  • test_acceptance_criteria::test_reading_records_through_the_api_with_nothing_to_read
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
  • test_acceptance_criteria::test_the_apps_figures_win_and_unavailable_sources_are_listed

DAT-02 The customer chooses to fill answers from records (pages)

IDCriterionTests
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
  • test_acceptance_criteria::test_the_customer_is_asked_whether_to_fill_in_answers_from_hmrc_records
  • test_journeys::test_journey[J51]
  • test_journeys::test_journey[J53]
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
  • test_acceptance_criteria::test_the_customer_is_asked_whether_to_fill_in_answers_from_hmrc_records
  • test_journeys::test_journey[J08]
  • test_journeys::test_journey[J51]
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
  • test_acceptance_criteria::test_a_figure_from_records_loses_its_label_when_the_customer_changes_it

DAT-03 Check or read without asking

IDCriterionTests
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
  • test_journeys::test_journey[J59]
  • test_web::test_prefill_follows_each_parts_reading_choice
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
  • test_journeys::test_journey[J07]
  • test_web::test_prefill_follows_each_parts_reading_choice

DAT-04 Reading inside an app

IDCriterionTests
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
  • test_app_journeys::test_hmrc_records_fill_only_what_the_app_did_not_send
  • test_journeys::test_journey[J53]
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
  • test_app_journeys::test_hmrc_records_are_not_offered_when_the_app_sent_all_they_can_fill
  • test_app_journeys::test_hmrc_records_fill_only_what_the_app_did_not_send

DAT-05 Reading for the extra capabilities

IDCriterionTests
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
  • test_acceptance_criteria::test_the_tax_so_far_api_reads_pay_so_far_from_hmrc_records
  • test_journeys::test_journey[J65]
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
  • test_journeys::test_journey[J72]
  • test_journeys::test_journey[J76]
  • test_mtd::test_explain_hmrcs_calculation_for_leah
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
  • test_forecast::test_hmrc_account_adapter_reads_charges_credit_and_overdue
  • test_journeys::test_journey[J31]

DAT-06 What is never done

IDCriterionTests
DAT-06.1 Nothing is ever written to HMRC.
1 test for DAT-06.1
  • test_acceptance_criteria::test_records_are_only_ever_read_never_written
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
  • test_integrations::test_dvla_lookup_uses_published_contract
  • test_integrations::test_hmrc_authorization_url_has_state_and_scope
  • test_journeys::test_journey[J09]
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
  • test_acceptance_criteria::test_figures_read_through_the_api_are_not_kept
  • test_background::test_answers_are_deleted_once_a_session_is_unused_for_15_minutes

OPT-01 Payment plan amounts

IDCriterionTests
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
  • test_forecast::test_plan_pays_every_bill_on_time
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
  • test_forecast::test_forecast_persona_engine[B01-Asha]
  • test_forecast::test_forecast_persona_engine[B02-Asha]
  • test_forecast::test_forecast_persona_engine[B03-Ben]
  • test_forecast::test_forecast_persona_engine[B04-Cara]
  • test_forecast::test_forecast_persona_engine[B05-Dev]
  • test_forecast::test_forecast_persona_engine[B06-Ela]
  • test_forecast::test_forecast_persona_engine[B07-Finn]
  • test_forecast::test_forecast_persona_engine[B08-Gita]
  • test_forecast::test_forecast_persona_engine[B09-Hari]
  • test_forecast::test_forecast_persona_engine[B10-Ivy]
  • test_forecast::test_forecast_persona_engine[B11-Jon]
  • test_forecast::test_forecast_persona_engine[B12-Kai]
  • test_forecast::test_forecast_persona_engine[B13-Lia]
  • test_forecast::test_forecast_persona_engine[B14-Mo]
  • test_forecast::test_forecast_persona_engine[B15-Nia]
  • test_forecast::test_forecast_persona_engine[B16-Omar]
  • test_forecast::test_forecast_persona_engine[B17-Pip]
  • test_forecast::test_forecast_persona_engine[B18-Rosa]
  • test_forecast::test_forecast_persona_engine[B19-Sam]
  • test_forecast::test_forecast_persona_engine[B20-Tara]
  • test_forecast::test_forecast_persona_engine[B21-Una]
  • test_forecast::test_forecast_persona_engine[B22-Vic]
  • test_forecast::test_forecast_persona_engine[B23-Wes]
  • test_forecast::test_low_and_high_amounts_bracket_the_central_amount
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
  • test_forecast::test_bank_holidays_and_working_days
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
  • test_forecast::test_forecast_persona_engine[B01-Asha]
  • test_forecast::test_forecast_persona_engine[B02-Asha]
  • test_forecast::test_forecast_persona_engine[B03-Ben]
  • test_forecast::test_forecast_persona_engine[B04-Cara]
  • test_forecast::test_forecast_persona_engine[B05-Dev]
  • test_forecast::test_forecast_persona_engine[B06-Ela]
  • test_forecast::test_forecast_persona_engine[B07-Finn]
  • test_forecast::test_forecast_persona_engine[B08-Gita]
  • test_forecast::test_forecast_persona_engine[B09-Hari]
  • test_forecast::test_forecast_persona_engine[B10-Ivy]
  • test_forecast::test_forecast_persona_engine[B11-Jon]
  • test_forecast::test_forecast_persona_engine[B12-Kai]
  • test_forecast::test_forecast_persona_engine[B13-Lia]
  • test_forecast::test_forecast_persona_engine[B14-Mo]
  • test_forecast::test_forecast_persona_engine[B15-Nia]
  • test_forecast::test_forecast_persona_engine[B16-Omar]
  • test_forecast::test_forecast_persona_engine[B17-Pip]
  • test_forecast::test_forecast_persona_engine[B18-Rosa]
  • test_forecast::test_forecast_persona_engine[B19-Sam]
  • test_forecast::test_forecast_persona_engine[B20-Tara]
  • test_forecast::test_forecast_persona_engine[B21-Una]
  • test_forecast::test_forecast_persona_engine[B22-Vic]
  • test_forecast::test_forecast_persona_engine[B23-Wes]
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
  • test_journeys::test_journey[J22]
  • test_payment_plan::test_overdue_account_goes_to_time_to_pay
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
  • test_acceptance_criteria::test_a_payment_plan_amount_through_the_api_points_to_hmrc_and_keeps_nothing

OPT-02 Tax so far this year

IDCriterionTests
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
  • test_tax_so_far::test_the_method
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
  • test_journeys::test_journey[J65]
  • test_tax_so_far::test_the_method
OPT-02.3 Every step is shown on the result page and returned to apps in explanation.
1 test for OPT-02.3
  • test_tax_so_far::test_the_method

OPT-03 Making Tax Digital for Income Tax helpers

IDCriterionTests
OPT-03.1 Given a helper is used, then nothing is ever sent to HMRC.
1 test for OPT-03.1
  • test_acceptance_criteria::test_records_are_only_ever_read_never_written
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
  • test_mtd_pages::test_answers_carry_over_to_the_next_helper
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
  • test_journeys::test_journey[J77]
  • test_mtd::test_reminders_before_each_deadline

OPT-04 Tax tools

IDCriterionTests
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
  • test_filing_check::test_the_pages_from_start_to_result
  • test_govuk_patterns::test_tool_pages_follow_govuk_patterns
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
  • test_corporation_tax::test_the_pages_and_the_api
  • test_filing_check::test_the_api_gives_the_same_answer_and_refuses_what_is_wrong
  • test_vat::test_the_pages_and_the_api
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
  • test_app_journeys::test_a_tool_inside_an_app_uses_the_answers_the_app_sent
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[benefits0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[benefits1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[capital-gains-tax-on-a-uk-home]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[check-if-you-need-a-tax-return]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[check-your-paye-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[corporation-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[director-salary-or-dividends]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[inheritance-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[partnership-profits]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[payroll]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[tax-on-buying-property2]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[trust-income-tax]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat0]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat1]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat2]
  • test_app_journeys::test_every_tool_works_inside_an_app_and_gives_its_result_back[vat3]

OPT-05 Document reading

IDCriterionTests
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
  • test_documents::test_customer_fills_in_pay_from_a_p60
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
  • test_documents::test_a_p60_from_payroll_software_is_read_on_the_service
  • test_documents::test_reader_choice
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
  • test_documents::test_a_p60_from_payroll_software_is_read_on_the_service
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
  • test_documents::test_other_statements_are_read_by_their_usual_wording
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
  • test_documents::test_a_scan_or_photo_is_not_read_without_ocr
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
  • test_documents::test_no_document_is_asked_for_figures_hmrc_records_gave
OPT-05.7 The test site reads only its sample documents, in the same way.
1 test for OPT-05.7
  • test_documents::test_the_sample_documents_are_read_the_same_way

OPT-06 Customer accounts

IDCriterionTests
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
  • test_journeys::test_journey[J30]
  • test_saas::test_create_account_set_up_and_see_forecast
  • test_saas::test_password_rules_and_duplicate_accounts
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
  • test_journeys::test_journey[J30]
  • test_saas::test_upload_transactions_prefills_figures_for_checking
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
  • test_journeys::test_journey[J35]
  • test_saas::test_recalculate_queues_a_message_when_the_amount_changes
  • test_saas_email::test_forecast_change_email
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
  • test_journeys::test_journey[J37]
  • test_saas::test_download_and_delete_account
  • test_saas::test_purge_deletes_accounts_not_used_for_two_years
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
  • test_saas::test_sign_in_lockout_does_not_reveal_accounts

PLN-01 Asking for a plan

IDCriterionTests
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
  • test_journey_planner::test_a_plan_for_an_employee_narrows_the_questions_and_says_why
  • test_journeys::test_journey[J95]
PLN-01.2 Given the planner is off for the organisation's API, then 403.
1 test for PLN-01.2
  • test_journey_planner::test_the_planner_is_only_reached_where_the_settings_switch_it_on

PLN-02 Starting a planned journey

IDCriterionTests
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
  • test_journey_planner::test_a_planned_journey_asks_only_what_the_plan_says
  • test_journeys::test_journey[J95]
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
  • test_journey_planner::test_other_calculations_and_what_is_refused
PLN-02.3 Given the planner is off inside the organisation's app, then 403.
1 test for PLN-02.3
  • test_journey_planner::test_the_planner_is_only_reached_where_the_settings_switch_it_on

PLN-03 The calculation

IDCriterionTests
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
  • test_journey_planner::test_other_calculations_and_what_is_refused
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
  • test_journey_planner::test_other_calculations_and_what_is_refused

PLN-04 The tax year

IDCriterionTests
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
  • test_journey_planner::test_the_tax_year_rules
PLN-04.2 Given nothing about the year, and only one year offered, then that year is used.
1 test for PLN-04.2
  • test_journey_planner::test_the_tax_year_rules
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
  • test_journey_planner::test_the_tax_year_rules

PLN-05 The questions

IDCriterionTests
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
  • test_journey_planner::test_a_plan_for_an_employee_narrows_the_questions_and_says_why
  • test_journey_planner::test_a_planned_journey_asks_only_what_the_plan_says
  • test_journeys::test_journey[J95]
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
  • test_journey_planner::test_without_a_complete_list_the_customer_is_asked_about_their_income
PLN-05.3 Given the app sent figures for a part, then that part is always kept.
1 test for PLN-05.3
  • test_acceptance_criteria::test_planner_rules_for_kept_parts_records_and_checks
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
  • test_journey_planner::test_a_plan_for_an_employee_narrows_the_questions_and_says_why
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
  • test_journey_planner::test_a_planned_journey_asks_only_what_the_plan_says

PLN-06 HMRC records

IDCriterionTests
PLN-06.1 The customer agreed in the app.
1 test for PLN-06.1
  • test_journey_planner::test_records_are_offered_only_when_the_customer_agreed
PLN-06.2 The organisation reads records inside its app.
1 test for PLN-06.2
  • test_acceptance_criteria::test_planner_rules_for_kept_parts_records_and_checks
PLN-06.3 A switched-on source can fill something the app did not send.
1 test for PLN-06.3
  • test_acceptance_criteria::test_planner_rules_for_kept_parts_records_and_checks

PLN-07 Checking the app's answers

IDCriterionTests
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
  • test_acceptance_criteria::test_planner_rules_for_kept_parts_records_and_checks
PLN-07.2 Otherwise, questions the app's answers fill are skipped.
1 test for PLN-07.2
  • test_journey_planner::test_a_planned_journey_asks_only_what_the_plan_says

PLN-08 Never wider, and no AI

IDCriterionTests
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
  • test_journey_planner::test_a_plan_never_widens_the_settings
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
  • test_acceptance_criteria::test_planner_rules_for_kept_parts_records_and_checks

PLN-09 Switching it on and off

IDCriterionTests
PLN-09.1 Given the feature is switched off for the service, then its API returns 404.
1 test for PLN-09.1
  • test_journey_planner::test_the_planner_is_only_reached_where_the_settings_switch_it_on
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
  • test_journey_planner::test_the_planner_is_only_reached_where_the_settings_switch_it_on
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
  • test_journey_planner::test_the_calculators_own_pages_are_untouched

PLN-10 Questions for an app with its own screens

IDCriterionTests
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
  • test_journey_planner::test_a_page_describes_its_questions_for_the_app_to_draw
  • test_journey_planner::test_an_app_with_its_own_screens_asks_the_planners_questions
  • test_journeys::test_journey[J96]
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
  • test_journey_planner::test_an_app_with_its_own_screens_asks_the_planners_questions
  • test_journeys::test_journey[J96]
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
  • test_journey_planner::test_a_page_describes_its_questions_for_the_app_to_draw
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
  • test_journey_planner::test_an_app_with_its_own_screens_asks_the_planners_questions
  • test_journeys::test_journey[J96]
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
  • test_journey_planner::test_own_screens_are_for_the_tax_estimate_and_need_the_planner_for_the_api
PLN-10.6 Given the planner is off for the organisation's API calculations, then 403.
1 test for PLN-10.6
  • test_journey_planner::test_own_screens_are_for_the_tax_estimate_and_need_the_planner_for_the_api

PLN-11 HMRC records for an app with its own screens

IDCriterionTests
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
  • test_journey_planner::test_own_screens_fill_from_hmrc_records_only_what_the_app_did_not_send
PLN-11.2 Given the app sent a figure, then a figure from the records never replaces it.
1 test for PLN-11.2
  • test_journey_planner::test_own_screens_fill_from_hmrc_records_only_what_the_app_did_not_send

Is this page not working properly? (opens in new tab)