|
1 | 1 | import json |
| 2 | +from datetime import date, timedelta, datetime, timezone |
2 | 3 | from http import HTTPStatus |
3 | 4 |
|
4 | 5 | import pytest |
|
25 | 26 | from tests.fixtures.builders.model import rule |
26 | 27 | from tests.integration.conftest import UNIQUE_CONSUMER_HEADER |
27 | 28 |
|
| 29 | +today = lambda: datetime.now(timezone.utc).date() |
28 | 30 |
|
29 | 31 | class TestBaseLine: |
30 | 32 | def test_nhs_number_given( |
@@ -1192,10 +1194,11 @@ def test_valid_response_when_consumer_has_a_valid_campaign_config_mapping( # no |
1192 | 1194 | ( |
1193 | 1195 | [ |
1194 | 1196 | # Campaign configs in S3 |
| 1197 | + # Note: Configs are uploaded in order so the start date would be newer down the order. |
1195 | 1198 | ("RSV", "RSV_campaign_id_1"), |
1196 | 1199 | ("RSV", "RSV_campaign_id_2"), |
1197 | | - ("RSV", "RSV_campaign_id_3"), |
1198 | 1200 | ("RSV", "RSV_campaign_id_4"), |
| 1201 | + ("RSV", "RSV_campaign_id_3"), |
1199 | 1202 | ("RSV", "inactive_RSV_campaign_id_5", "inactive"), # inactive iteration |
1200 | 1203 | ("RSV", "RSV_campaign_id_6"), |
1201 | 1204 | ], |
@@ -1223,7 +1226,7 @@ def test_valid_response_when_consumer_has_a_valid_campaign_config_mapping( # no |
1223 | 1226 | ], |
1224 | 1227 | indirect=["campaign_configs", "consumer_mappings"], |
1225 | 1228 | ) |
1226 | | - def test_if_correct_campaign_is_chosen_for_the_consumer_when_multiple_campaign_exists_per_target_giving_same_status( # noqa : PLR0913 |
| 1229 | + def test_if_correct_campaign_is_chosen_for_the_consumer_when_multiple_campaign_exists_per_target_giving_same_status( |
1227 | 1230 | self, |
1228 | 1231 | client: FlaskClient, |
1229 | 1232 | persisted_person: NHSNumber, |
@@ -1379,3 +1382,137 @@ def test_if_campaign_having_best_status_is_chosen_if_there_exists_multiple_campa |
1379 | 1382 | ) |
1380 | 1383 | ), |
1381 | 1384 | ) |
| 1385 | + |
| 1386 | + @pytest.mark.parametrize( |
| 1387 | + ("campaign_1_start_date", "campaign_2_start_date", "postcode_for_comparator", "expected_campaign_id"), |
| 1388 | + [ |
| 1389 | + ( |
| 1390 | + ("RSV_campaign_id_1", today()), |
| 1391 | + ("RSV_campaign_id_2", today() - timedelta(days=1)), |
| 1392 | + "SW19", # postcode for resulting in not-actionable |
| 1393 | + "RSV_campaign_id_1", |
| 1394 | + ), |
| 1395 | + ( |
| 1396 | + ("RSV_campaign_id_1", today() - timedelta(days=1)), |
| 1397 | + ("RSV_campaign_id_2", today()), |
| 1398 | + "SW19", # postcode for resulting in not-actionable |
| 1399 | + "RSV_campaign_id_2", |
| 1400 | + ), |
| 1401 | + ( |
| 1402 | + ("RSV_campaign_id_1", today()), |
| 1403 | + ("RSV_campaign_id_2", today() - timedelta(days=1)), |
| 1404 | + "M4", # postcode for resulting in actionable |
| 1405 | + "RSV_campaign_id_1", |
| 1406 | + ), |
| 1407 | + ( |
| 1408 | + ("RSV_campaign_id_1", today() - timedelta(days=1)), |
| 1409 | + ("RSV_campaign_id_2", today()), |
| 1410 | + "M4", # postcode for resulting in actionable |
| 1411 | + "RSV_campaign_id_2", |
| 1412 | + ), |
| 1413 | + ], |
| 1414 | + ) |
| 1415 | + def test_if_campaign_having_best_status_is_chosen_if_there_exists_multiple_campaign_per_target_diff_start_date( |
| 1416 | + self, |
| 1417 | + client: FlaskClient, |
| 1418 | + persisted_person_pc_sw19: NHSNumber, |
| 1419 | + s3_client: BaseClient, |
| 1420 | + consumer_mapping_bucket: BucketName, |
| 1421 | + rules_bucket: BucketName, |
| 1422 | + audit_bucket: BucketName, |
| 1423 | + secretsmanager_client: BaseClient, # noqa: ARG002 |
| 1424 | + campaign_1_start_date: tuple[str, date], |
| 1425 | + campaign_2_start_date: tuple[str, date], |
| 1426 | + postcode_for_comparator: str, |
| 1427 | + expected_campaign_id: NHSNumber, |
| 1428 | + ): |
| 1429 | + # Given |
| 1430 | + consumer_id = "consumer-n3bs-jo4hn-ce4na" |
| 1431 | + headers = {"nhs-login-nhs-number": str(persisted_person_pc_sw19), UNIQUE_CONSUMER_HEADER: consumer_id} |
| 1432 | + |
| 1433 | + # Consumer Mapping Data |
| 1434 | + s3_client.put_object( |
| 1435 | + Bucket=consumer_mapping_bucket, |
| 1436 | + Key="consumer_mapping_config.json", |
| 1437 | + Body=json.dumps( |
| 1438 | + { |
| 1439 | + consumer_id: [ |
| 1440 | + {"CampaignConfigID": "RSV_campaign_id_1"}, |
| 1441 | + {"CampaignConfigID": "RSV_campaign_id_2"}, |
| 1442 | + ], |
| 1443 | + } |
| 1444 | + ), |
| 1445 | + ContentType="application/json", |
| 1446 | + ) |
| 1447 | + |
| 1448 | + # Campaign configs |
| 1449 | + campaign_1 = rule.CampaignConfigFactory.build( |
| 1450 | + id=campaign_1_start_date[0], |
| 1451 | + target="RSV", |
| 1452 | + start_date=campaign_1_start_date[1], |
| 1453 | + type="V", |
| 1454 | + iterations=[ |
| 1455 | + rule.IterationFactory.build( |
| 1456 | + iteration_rules=[ |
| 1457 | + rule.PostcodeSuppressionRuleFactory.build( |
| 1458 | + name="Exclude M4", comparator=RuleComparator(postcode_for_comparator) |
| 1459 | + ), |
| 1460 | + ], |
| 1461 | + iteration_cohorts=[ |
| 1462 | + rule.IterationCohortFactory.build( |
| 1463 | + cohort_label="cohort1", |
| 1464 | + cohort_group="cohort_group1", |
| 1465 | + positive_description="positive_description", |
| 1466 | + ) |
| 1467 | + ], |
| 1468 | + status_text=None, |
| 1469 | + ) |
| 1470 | + ], |
| 1471 | + ) |
| 1472 | + |
| 1473 | + campaign_2 = rule.CampaignConfigFactory.build( |
| 1474 | + id=campaign_2_start_date[0], |
| 1475 | + target="RSV", |
| 1476 | + type="V", |
| 1477 | + start_date=campaign_2_start_date[1], |
| 1478 | + iterations=[ |
| 1479 | + rule.IterationFactory.build( |
| 1480 | + iteration_rules=[ |
| 1481 | + rule.PostcodeSuppressionRuleFactory.build( |
| 1482 | + name="Exclude M4", comparator=RuleComparator(postcode_for_comparator) |
| 1483 | + ), |
| 1484 | + ], |
| 1485 | + iteration_cohorts=[ |
| 1486 | + rule.IterationCohortFactory.build( |
| 1487 | + cohort_label="cohort1", |
| 1488 | + cohort_group="cohort_group1", |
| 1489 | + positive_description="positive_description", |
| 1490 | + ) |
| 1491 | + ], |
| 1492 | + status_text=None, |
| 1493 | + ) |
| 1494 | + ], |
| 1495 | + ) |
| 1496 | + |
| 1497 | + for campaign in [campaign_1, campaign_2]: |
| 1498 | + s3_client.put_object( |
| 1499 | + Bucket=rules_bucket, |
| 1500 | + Key=f"{campaign.id}.json", |
| 1501 | + Body=json.dumps({"CampaignConfig": campaign.model_dump(by_alias=True)}), |
| 1502 | + ContentType="application/json", |
| 1503 | + ) |
| 1504 | + |
| 1505 | + # When |
| 1506 | + client.get(f"/patient-check/{persisted_person_pc_sw19}", headers=headers) |
| 1507 | + |
| 1508 | + objects = s3_client.list_objects_v2(Bucket=audit_bucket).get("Contents", []) |
| 1509 | + object_keys = [obj["Key"] for obj in objects] |
| 1510 | + latest_key = sorted(object_keys)[-1] |
| 1511 | + audit_data = json.loads(s3_client.get_object(Bucket=audit_bucket, Key=latest_key)["Body"].read()) |
| 1512 | + |
| 1513 | + # Then |
| 1514 | + if expected_campaign_id is not None: |
| 1515 | + assert_that(len(audit_data["response"]["condition"]), equal_to(1)) |
| 1516 | + assert_that(audit_data["response"]["condition"][0].get("campaignId"), equal_to(expected_campaign_id)) |
| 1517 | + else: |
| 1518 | + assert_that(len(audit_data["response"]["condition"]), equal_to(0)) |
0 commit comments