diff --git a/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py b/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py index bc060bbef..a64a8b878 100644 --- a/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py +++ b/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py @@ -62,16 +62,23 @@ class EligibilityCalculator: def active_campaigns(self) -> list[rules.CampaignConfig]: return [cc for cc in self.campaign_configs if cc.campaign_live] - @property def campaigns_grouped_by_condition_name( - self, + self, conditions: list[str], category: str ) -> Iterator[tuple[eligibility.ConditionName, list[rules.CampaignConfig]]]: - """Generator function to iterate over campaign groups by condition name.""" + """Generator that yields campaign groups filtered by condition names and campaign category.""" + + allowed_types = ( + {"V", "S"} if category == "ALL" else {category[0]} if category in {"VACCINATIONS", "SCREENING"} else set() + ) + filter_all_conditions = "ALL" in conditions + for condition_name, campaign_group in groupby( sorted(self.active_campaigns, key=attrgetter("target")), key=attrgetter("target"), ): - yield condition_name, list(campaign_group) + campaigns = list(campaign_group) + if campaigns[0].type in allowed_types and (filter_all_conditions or str(condition_name) in conditions): + yield condition_name, campaigns @property def person_cohorts(self) -> set[str]: @@ -137,13 +144,15 @@ def get_redirect_rules( action_mapper = active_iteration.actions_mapper return redirect_rules, action_mapper, default_comms - def evaluate_eligibility(self, *, include_actions_flag: bool = True) -> eligibility.EligibilityStatus: - """Iterates over campaign groups, evaluates eligibility, and returns a consolidated status.""" + def evaluate_eligibility( + self, include_actions: str, conditions: list[str], category: str + ) -> eligibility.EligibilityStatus: + include_actions_flag = include_actions.upper() == "Y" condition_results: dict[ConditionName, IterationResult] = {} actions: list[SuggestedAction] | None = [] redirect_rule_priority, redirect_rule_name = None, None - for condition_name, campaign_group in self.campaigns_grouped_by_condition_name: + for condition_name, campaign_group in self.campaigns_grouped_by_condition_name(conditions, category): best_active_iteration: Iteration | None best_candidate: IterationResult best_campaign_id: CampaignID | None diff --git a/src/eligibility_signposting_api/services/eligibility_services.py b/src/eligibility_signposting_api/services/eligibility_services.py index c8d9c5b50..48586290b 100644 --- a/src/eligibility_signposting_api/services/eligibility_services.py +++ b/src/eligibility_signposting_api/services/eligibility_services.py @@ -31,7 +31,11 @@ def __init__( self.calculator_factory = calculator_factory def get_eligibility_status( - self, nhs_number: eligibility.NHSNumber | None = None, *, include_actions_flag: bool = True + self, + nhs_number: eligibility.NHSNumber, + include_actions: str, + conditions: list[str], + category: str, ) -> eligibility.EligibilityStatus: """Calculate a person's eligibility for vaccination given an NHS number.""" if nhs_number: @@ -51,6 +55,6 @@ def get_eligibility_status( raise UnknownPersonError from e else: calc: calculator.EligibilityCalculator = self.calculator_factory.get(person_data, campaign_configs) - return calc.evaluate_eligibility(include_actions_flag=include_actions_flag) + return calc.evaluate_eligibility(include_actions, conditions, category) raise UnknownPersonError # pragma: no cover diff --git a/src/eligibility_signposting_api/views/eligibility.py b/src/eligibility_signposting_api/views/eligibility.py index 8c91d7de7..0f507f65c 100644 --- a/src/eligibility_signposting_api/views/eligibility.py +++ b/src/eligibility_signposting_api/views/eligibility.py @@ -2,6 +2,7 @@ import uuid from datetime import UTC, datetime from http import HTTPStatus +from typing import Any from flask import Blueprint, make_response, request from flask.typing import ResponseReturnValue @@ -45,8 +46,12 @@ def check_eligibility( ) -> ResponseReturnValue: logger.info("checking nhs_number %r in %r", nhs_number, eligibility_service, extra={"nhs_number": nhs_number}) try: + query_params = get_or_default_query_params() eligibility_status = eligibility_service.get_eligibility_status( - nhs_number, include_actions_flag=get_include_actions_flag() + nhs_number, + query_params["includeActions"], + query_params["conditions"], + query_params["category"], ) except UnknownPersonError: return handle_unknown_person_error(nhs_number) @@ -58,13 +63,36 @@ def check_eligibility( ) -def get_include_actions_flag() -> bool: - if not request.args.get("includeActions"): - logger.info("Defaulting includeActions query param to Y as no value was provided") - include_actions_flag = True +def get_or_default_query_params() -> dict[str, Any]: + default_query_params = {"category": "ALL", "conditions": ["ALL"], "includeActions": "Y"} + + if not request.args: + logger.info("Defaulting all query params as no value was provided, using values %s", default_query_params) + return default_query_params + + raw_args = request.args.to_dict() + query_params: dict[str, Any] = {} + + include_actions = raw_args.get("includeActions") + query_params["includeActions"] = ( + include_actions.upper() if include_actions else default_query_params["includeActions"] + ) + if include_actions is None: + logger.info("Defaulting includeActions query param to 'Y' as no value was provided") + + category = raw_args.get("category") + query_params["category"] = category.upper() if category else default_query_params["category"] + if category is None: + logger.info("Defaulting category query param to 'ALL' as no value was provided") + + conditions_str = raw_args.get("conditions") + if conditions_str: + query_params["conditions"] = conditions_str.upper().split(",") else: - include_actions_flag = request.args.get("includeActions") == "Y" - return include_actions_flag + query_params["conditions"] = default_query_params["conditions"] + logger.info("Defaulting conditions query param to 'ALL' as no value was provided") + + return query_params def handle_unknown_person_error(nhs_number: NHSNumber) -> ResponseReturnValue: diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index eaeb3251a..75cf97878 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -496,6 +496,7 @@ def multiple_campaign_configs(s3_client: BaseClient, rules_bucket: BucketName) - campaign = rule.CampaignConfigFactory.build( name=f"campaign_{i}", target=targets[i], + type="V", iterations=[ rule.IterationFactory.build( iteration_rules=target_rules_map.get(targets[i]), diff --git a/tests/integration/lambda/test_app_running_as_lambda.py b/tests/integration/lambda/test_app_running_as_lambda.py index 2e712a076..54e0370f8 100644 --- a/tests/integration/lambda/test_app_running_as_lambda.py +++ b/tests/integration/lambda/test_app_running_as_lambda.py @@ -264,7 +264,11 @@ def test_given_nhs_number_in_path_matches_with_nhs_number_in_headers_and_check_i messages = get_log_messages(flask_function, logs_client) assert_that( messages, - has_item(contains_string("Defaulting includeActions query param to Y as no value was provided")), + has_item(contains_string("Defaulting category query param to 'ALL' as no value was provided")), + ) + assert_that( + messages, + has_item(contains_string("Defaulting conditions query param to 'ALL' as no value was provided")), ) @@ -418,7 +422,7 @@ def test_given_person_has_unique_status_for_different_conditions_with_audit( # "nhsd_end_user_organisation_ods": "nhsd_end_user_organisation_ods", "nhsd_application_id": "nhsd_application_id", }, - params={"includeActions": "Y"}, + params={"includeActions": "Y", "category": "VACCINATIONS", "conditions": "COVID,FLU,RSV"}, timeout=10, ) @@ -438,7 +442,7 @@ def test_given_person_has_unique_status_for_different_conditions_with_audit( # "nhsdEndUserOrganisationOds": "nhsd_end_user_organisation_ods", "nhsdApplicationId": "nhsd_application_id", } - expected_query_params = {"category": None, "conditions": None, "includeActions": "Y"} + expected_query_params = {"category": "VACCINATIONS", "conditions": "COVID,FLU,RSV", "includeActions": "Y"} rsv_campaign = multiple_campaign_configs[0] covid_campaign = multiple_campaign_configs[1] diff --git a/tests/unit/services/calculators/test_eligibility_calculator.py b/tests/unit/services/calculators/test_eligibility_calculator.py index 86d7ff487..c93edb77c 100644 --- a/tests/unit/services/calculators/test_eligibility_calculator.py +++ b/tests/unit/services/calculators/test_eligibility_calculator.py @@ -4,7 +4,7 @@ import pytest from faker import Faker from freezegun import freeze_time -from hamcrest import assert_that, contains_exactly, contains_inanyorder, equal_to, has_item, has_items, is_in +from hamcrest import assert_that, contains_exactly, contains_inanyorder, equal_to, has_item, has_items, is_, is_in from pydantic import HttpUrl, ValidationError from eligibility_signposting_api.model import rules @@ -96,7 +96,7 @@ def test_not_base_eligible(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -141,7 +141,7 @@ def test_base_eligible_with_when_magic_cohort_is_present( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -190,7 +190,7 @@ def test_only_live_campaigns_considered(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -215,7 +215,7 @@ def test_campaigns_with_applicable_iteration_types_in_campaign_level_considered( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -248,7 +248,7 @@ def test_campaigns_with_applicable_iteration_types_in_iteration_level_considered calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -304,7 +304,7 @@ def test_base_eligible_and_simple_rule_includes(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -336,7 +336,7 @@ def test_base_eligible_but_simple_rule_excludes(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -383,7 +383,7 @@ def test_simple_rule_only_excludes_from_live_iteration(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -419,7 +419,7 @@ def test_rule_types_cause_correct_statuses(rule_type: rules_model.RuleType, expe calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -463,7 +463,7 @@ def test_multiple_rule_types_cause_correct_status(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -552,7 +552,7 @@ def test_rules_with_same_priority_must_all_match_to_exclude( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -605,7 +605,7 @@ def test_multiple_conditions_where_both_are_actionable(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -686,7 +686,7 @@ def test_multiple_conditions_where_all_give_unique_statuses(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility(include_actions_flag=False) + actual = calculator.evaluate_eligibility("N", ["ALL"], "ALL") # Then assert_that( @@ -770,7 +770,7 @@ def test_multiple_campaigns_for_single_condition( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -817,7 +817,7 @@ def test_base_eligible_and_icb_example( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -901,7 +901,7 @@ def test_status_on_target_based_on_last_successful_date( calculator = EligibilityCalculator(target_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -974,7 +974,7 @@ def test_status_on_cohort_attribute_level( calculator = EligibilityCalculator(person_row_with_extra_items_in_cohort_row, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1020,7 +1020,7 @@ def test_status_if_iteration_rules_contains_cohort_label_field( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1084,7 +1084,7 @@ def test_rules_stop_behavior( calculator = EligibilityCalculator(person_rows, [campaign_config]) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1185,7 +1185,7 @@ def test_eligibility_results_when_multiple_cohorts( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1297,7 +1297,7 @@ def test_cohort_groups_and_their_descriptions_when_magic_cohort_is_present( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1350,7 +1350,7 @@ def test_cohort_groups_and_their_descriptions_when_best_status_is_not_eligible( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1438,7 +1438,7 @@ def test_cohort_groups_and_their_descriptions_and_the_collection_of_s_rules_when calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1520,7 +1520,7 @@ def test_cohort_group_and_descriptions_when_best_status_is_actionable( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1599,7 +1599,7 @@ def test_cohort_group_descriptions_are_selected_based_on_priority_when_cohorts_h calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1730,7 +1730,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -1777,7 +1777,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( [ ( """Rule match: default_comms_routing present, action_mapper present, - return actions from matching comms from rule""", + return actions from matching comms from rule""", "defaultcomms", "InternalBookNBS", {"InternalBookNBS": book_nbs_comms, "defaultcomms": default_comms_detail}, @@ -1794,7 +1794,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing has multiple values, - comms missing in rule, all default comms should be returned in actions""", + comms missing in rule, all default comms should be returned in actions""", "defaultcomms1|defaultcomms2", None, {"defaultcomms1": default_comms_detail, "defaultcomms2": default_comms_detail}, @@ -1819,7 +1819,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing has multiple values, - comms is empty string, all default comms should be returned in actions""", + comms is empty string, all default comms should be returned in actions""", "defaultcomms1", "", {"defaultcomms1": default_comms_detail}, @@ -1836,7 +1836,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing present, - action_mapper missing for matching comms, return default_comms in actions""", + action_mapper missing for matching comms, return default_comms in actions""", "defaultcomms", "InternalBookNBS", {"defaultcomms": default_comms_detail}, @@ -1853,7 +1853,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing present, - rule has an incorrect comms key, return default_comms in actions""", + rule has an incorrect comms key, return default_comms in actions""", "defaultcomms", "InvalidCode", {"defaultcomms": default_comms_detail}, @@ -1870,7 +1870,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: action_mapper present without url, - return actions from matching comms from rule""", + return actions from matching comms from rule""", "defaultcomms", "InternalBookNBS", { @@ -1893,7 +1893,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing missing, - comms present in rule, action_mapper missing, return no actions""", + comms present in rule, action_mapper missing, return no actions""", "", "InternalBookNBS", {}, @@ -1901,7 +1901,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing missing, but action_mapper present, - return actions from matching comms from rule""", + return actions from matching comms from rule""", "", "InternalBookNBS", {"InternalBookNBS": book_nbs_comms}, @@ -1918,7 +1918,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing present, - comms present in rule, but action_mapper missing, return no actions""", + comms present in rule, but action_mapper missing, return no actions""", "defaultcommskeywithoutactionmapper", "InternalBookNBS", {}, @@ -1926,7 +1926,7 @@ def test_cohort_group_descriptions_pick_first_non_empty_if_available( ), ( """Rule match: default_comms_routing has multiple values, - one of the value is invalid, valid values should be returned in actions""", + one of the value is invalid, valid values should be returned in actions""", "defaultcomms1|invaliddefault", None, {"defaultcomms1": default_comms_detail}, @@ -1975,7 +1975,7 @@ def test_correct_actions_determined_from_redirect_r_rules( # noqa: PLR0913 calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -2032,7 +2032,7 @@ def test_cohort_label_not_supported_used_in_r_rules(test_comment: str, redirect_ calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -2101,7 +2101,7 @@ def test_multiple_r_rules_match_with_same_priority(faker: Faker): calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -2168,7 +2168,7 @@ def test_multiple_r_rules_with_same_priority_one_rule_mismatch_should_return_def calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -2242,7 +2242,7 @@ def test_only_highest_priority_rule_is_applied_and_return_actions_only_for_that_ calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility() + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") expected_actions = SuggestedAction( internal_action_code=InternalActionCode("rule_1_comms_routing"), @@ -2298,7 +2298,7 @@ def test_should_include_actions_when_include_actions_flag_is_true_when_status_is calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility(include_actions_flag=True) + actual = calculator.evaluate_eligibility("Y", ["ALL"], "ALL") # Then assert_that( @@ -2358,7 +2358,7 @@ def test_should_not_include_actions_when_include_actions_flag_is_false_when_stat calculator = EligibilityCalculator(person_rows, campaign_configs) # When - actual = calculator.evaluate_eligibility(include_actions_flag=False) + actual = calculator.evaluate_eligibility("N", ["ALL"], "ALL") # Then assert_that( @@ -2372,3 +2372,35 @@ def test_should_not_include_actions_when_include_actions_flag_is_false_when_stat ) ), ) + + +@pytest.mark.parametrize( + ("campaign_target", "campaign_type", "conditions_filter", "category_filter", "expected_result"), + [ + # Multiple matching campaigns under the same condition + ("RSV", "V", ["RSV"], "VACCINATIONS", [("RSV", "V")]), + ("RSV", "V", ["COVID"], "VACCINATIONS", []), + ("RSV", "S", ["RSV"], "ALL", [("RSV", "S")]), + ("RSV", "S", ["ALL"], "ALL", [("RSV", "S")]), + ("RSV", "S", ["RSV"], "VACCINATIONS", []), + # Multiple campaigns with different types under the same condition name + ("RSV", "V", ["RSV"], "ALL", [("RSV", "V")]), + # Campaign is live but condition not in filter (no yield) + ("FLU", "V", ["COVID", "RSV"], "ALL", []), + # Category is ALL and condition filter includes ALL (everything matches) + ("FLU", "S", ["ALL"], "ALL", [("FLU", "S")]), + # Condition filter is unknown (should not match anything) + ("COVID", "V", ["UNKNOWN"], "VACCINATIONS", []), + # Campaign with the target matching one of several condition filters + ("FLU", "V", ["COVID", "FLU"], "VACCINATIONS", [("FLU", "V")]), + ], +) +def test_campaigns_grouped_by_condition_name_filters_correctly( + campaign_target, campaign_type, conditions_filter, category_filter, expected_result +): + campaign = rule_builder.CampaignConfigFactory.build(target=campaign_target, type=campaign_type, campaign_live=True) + + calculator = EligibilityCalculator(person_data=[], campaign_configs=[campaign]) + result = list(calculator.campaigns_grouped_by_condition_name(conditions_filter, category_filter)) + + assert_that([(str(name), group[0].type) for name, group in result], is_(expected_result)) diff --git a/tests/unit/services/test_eligibility_services.py b/tests/unit/services/test_eligibility_services.py index c99f3b73a..872347a00 100644 --- a/tests/unit/services/test_eligibility_services.py +++ b/tests/unit/services/test_eligibility_services.py @@ -18,7 +18,9 @@ def test_eligibility_service_returns_from_repo(): service = EligibilityService(person_repo, campaign_repo, EligibilityCalculatorFactory()) # When - actual = service.get_eligibility_status(NHSNumber("1234567890")) + actual = service.get_eligibility_status( + NHSNumber("1234567890"), include_actions="Y", conditions=["ALL"], category="ALL" + ) # Then assert_that(actual, is_eligibility_status().with_conditions(empty())) @@ -33,4 +35,4 @@ def test_eligibility_service_for_nonexistent_nhs_number(): # When with pytest.raises(UnknownPersonError): - service.get_eligibility_status(NHSNumber("1234567890")) + service.get_eligibility_status(NHSNumber("1234567890"), include_actions="Y", conditions=["ALL"], category="ALL") diff --git a/tests/unit/views/test_eligibility.py b/tests/unit/views/test_eligibility.py index 99b0fac34..cd0dda37b 100644 --- a/tests/unit/views/test_eligibility.py +++ b/tests/unit/views/test_eligibility.py @@ -37,6 +37,7 @@ build_actions, build_eligibility_cohorts, build_suitability_results, + get_or_default_query_params, ) from eligibility_signposting_api.views.response_model import eligibility from tests.fixtures.builders.model.eligibility import ( @@ -60,9 +61,10 @@ def __init__(self): def get_eligibility_status( self, - _: NHSNumber | None = None, - *, - include_actions_flag: bool = False, # noqa: ARG002 + _nhs_number: NHSNumber, + _include_actions: str, + _conditions: list[str], + _category: str, ) -> EligibilityStatus: return EligibilityStatusFactory.build() @@ -73,9 +75,10 @@ def __init__(self): def get_eligibility_status( self, - _: NHSNumber | None = None, - *, - include_actions_flag: bool = False, # noqa: ARG002 + _nhs_number: NHSNumber, + _include_actions: str, + _conditions: list[str], + _category: str, ) -> EligibilityStatus: raise UnknownPersonError @@ -86,9 +89,10 @@ def __init__(self): def get_eligibility_status( self, - _: NHSNumber | None = None, - *, - include_actions_flag: bool = False, # noqa: ARG002 + _nhs_number: NHSNumber, + _include_actions: str, + _conditions: list[str], + _category: str, ) -> EligibilityStatus: raise ValueError @@ -618,3 +622,45 @@ def test_request_id_from_header_logging_variants( assert request_id_logged assert response.status_code == HTTPStatus.OK + + +def test_get_or_default_query_params_with_no_args(app: Flask): + with app.test_request_context("/patient-check"): + result = get_or_default_query_params() + + expected = {"category": "ALL", "conditions": ["ALL"], "includeActions": "Y"} + + assert_that(result, is_(expected)) + + +def test_get_or_default_query_params_with_all_args(app: Flask): + with app.test_request_context("/patient-check?includeActions=Y&category=VACCINATIONS&conditions=FLU"): + result = get_or_default_query_params() + + expected = {"includeActions": "Y", "category": "VACCINATIONS", "conditions": ["FLU"]} + + assert_that(result, is_(expected)) + + +def test_get_or_default_query_params_with_partial_args(app: Flask): + with app.test_request_context("/patient-check?includeActions=N"): + result = get_or_default_query_params() + + expected = {"includeActions": "N", "category": "ALL", "conditions": ["ALL"]} + + assert_that(result, is_(expected)) + + +def test_get_or_default_query_params_with_lowercase_y(app: Flask): + with app.test_request_context("/patient-check?includeActions=y"): + result = get_or_default_query_params() + assert_that(result["includeActions"], is_("Y")) + + +def test_get_or_default_query_params_missing_include_actions(app: Flask): + with app.test_request_context("/patient-check?category=SCREENING&conditions=COVID19,FLU"): + result = get_or_default_query_params() + + expected = {"includeActions": "Y", "category": "SCREENING", "conditions": ["COVID19", "FLU"]} + + assert_that(result, is_(expected))