Skip to content

Commit d4a17e9

Browse files
committed
Added unit tests for AuditContext
1 parent 4a29b3e commit d4a17e9

4 files changed

Lines changed: 133 additions & 5 deletions

File tree

src/eligibility_signposting_api/audit_context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ def append_audit_condition(
132132

133133
@staticmethod
134134
def add_response_details(response) -> None:
135-
g.audit_log.response.response_id = str(response.response_id)
136-
g.audit_log.response.last_updated = str(response.meta.last_updated)
135+
g.audit_log.response.response_id = response.response_id
136+
g.audit_log.response.last_updated = response.meta.last_updated
137137

138138
@staticmethod
139139
def write_to_firehose(service: AuditService, response) -> None:

src/eligibility_signposting_api/audit_models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dataclasses import dataclass, field
22
from datetime import datetime
3+
from uuid import UUID
34

45

56
@dataclass
@@ -19,7 +20,7 @@ class RequestAuditQueryParams:
1920

2021
@dataclass
2122
class RequestAuditData:
22-
request_timestamp: datetime = field(default_factory=datetime.utcnow)
23+
request_timestamp: datetime = field(default_factory=datetime.utcnow) # TODO: fix use of deprecated datetime.now()
2324
headers: RequestAuditHeader = field(default_factory=RequestAuditHeader)
2425
query_params: RequestAuditQueryParams = field(default_factory=RequestAuditQueryParams)
2526
nhs_number: str | None = None
@@ -86,7 +87,7 @@ class AuditCondition:
8687

8788
@dataclass
8889
class ResponseAuditData:
89-
response_id: str | None = None
90+
response_id: UUID | None = None
9091
last_updated: str | None = None
9192
condition: list[AuditCondition] = field(default_factory=list)
9293

tests/integration/lambda/test_app_running_as_lambda.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import base64
22
import json
33
import logging
4-
import time
54
from http import HTTPStatus
65

76
import httpx

tests/unit/test_audit_context.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import uuid
2+
import pytest
3+
from datetime import datetime
4+
5+
from flask import g, request, Flask
6+
7+
from eligibility_signposting_api.audit_context import AuditContext
8+
from eligibility_signposting_api.audit_models import AuditEvent
9+
from eligibility_signposting_api.model.eligibility import SuggestedActions, ConditionName, IterationResult, \
10+
CohortGroupResult, SuggestedAction, ActionCode, ActionType, ActionDescription, UrlLink, UrlLabel, Reason, RuleName, \
11+
RuleDescription, RulePriority, Status
12+
from eligibility_signposting_api.model.rules import Iteration, CampaignID, CampaignVersion, \
13+
RuleType
14+
from fixtures.builders.model.rule import IterationFactory
15+
from fixtures.builders.views.response_model.eligibility import EligibilityResponseFactory
16+
17+
18+
@pytest.fixture
19+
def app():
20+
app = Flask(__name__)
21+
return app
22+
23+
24+
def test_add_request_details_sets_audit_log_on_g(app):
25+
headers = {
26+
"X-Request-ID": "test-x-request-id",
27+
"X-Correlation-ID": "test-x-correlation-id",
28+
"NHSD-End-User-Organisation-ODS": "test-org",
29+
"nhsd-application-id": "test-app-id",
30+
}
31+
32+
nhs_number = "1234567890"
33+
url = "/patient-check?includeActions=Y"
34+
35+
with app.test_request_context(url, headers=headers, method="GET"):
36+
request.view_args = {'nhs_number': nhs_number}
37+
AuditContext.add_request_details(request)
38+
39+
assert hasattr(g, "audit_log")
40+
audit_req = g.audit_log.request
41+
assert audit_req.nhs_number == nhs_number
42+
assert audit_req.headers.x_request_id == "test-x-request-id"
43+
assert audit_req.headers.x_correlation_id == "test-x-correlation-id"
44+
assert audit_req.headers.nhsd_end_user_organisation_ods == "test-org"
45+
assert audit_req.headers.nhsd_application_id == "test-app-id"
46+
assert audit_req.query_params.include_actions == "Y"
47+
assert isinstance(audit_req.request_timestamp, datetime)
48+
49+
50+
def test_add_request_details_when_headers_are_empty_sets_audit_log_on_g(app):
51+
nhs_number = "1234567890"
52+
url = "/patient-check?includeActions=Y"
53+
54+
with app.test_request_context(url, method="GET"):
55+
request.view_args = {'nhs_number': nhs_number}
56+
AuditContext.add_request_details(request)
57+
58+
assert hasattr(g, "audit_log")
59+
audit_req = g.audit_log.request
60+
assert audit_req.nhs_number == nhs_number
61+
assert audit_req.headers.x_request_id is None
62+
assert audit_req.headers.x_correlation_id is None
63+
assert audit_req.headers.nhsd_end_user_organisation_ods is None
64+
assert audit_req.headers.nhsd_application_id is None
65+
assert audit_req.query_params.include_actions == "Y"
66+
assert isinstance(audit_req.request_timestamp, datetime)
67+
68+
69+
def test_append_audit_condition_adds_condition_to_audit_log(app):
70+
suggested_actions: SuggestedActions | None
71+
condition_name: ConditionName
72+
best_results: tuple[Iteration, IterationResult, dict[str, CohortGroupResult]]
73+
campaign_details: tuple[CampaignID | None, CampaignVersion | None]
74+
redirect_rule_details: tuple[RulePriority | None, RuleName | None]
75+
76+
suggested_actions = SuggestedActions(actions=[SuggestedAction(
77+
action_code=ActionCode("ActionCode1"),
78+
action_type=ActionType("ActionType1"),
79+
action_description=ActionDescription("ActionDescription1"),
80+
url_link=UrlLink("https://www.example.com"),
81+
url_label=UrlLabel("ActionLabel1")
82+
)])
83+
84+
condition_name = ConditionName("Condition1")
85+
iteration = IterationFactory.build()
86+
audit_rules = [Reason(
87+
rule_type=RuleType.filter,
88+
rule_name=RuleName("FilterRuleName1"),
89+
rule_description=RuleDescription("FilterRuleDescription1"),
90+
matcher_matched=True,
91+
rule_priority=RulePriority("1")
92+
)]
93+
cohort_group_result = CohortGroupResult(status=Status.actionable, cohort_code="CohortCode1",
94+
description="CohortDescription1", audit_rules=audit_rules,
95+
reasons=audit_rules)
96+
iteration_result = IterationResult(status=Status.actionable, cohort_results=[cohort_group_result],
97+
actions=suggested_actions)
98+
best_results = (iteration, iteration_result, {"CohortCode1": cohort_group_result})
99+
campaign_details = (CampaignID("CampaignID1"), CampaignVersion("CampaignVersion1"))
100+
redirect_rule_details = (RulePriority("1"), RuleName("RedirectRuleName1"))
101+
102+
with app.app_context():
103+
g.audit_log = AuditEvent()
104+
105+
AuditContext.append_audit_condition(suggested_actions, condition_name, best_results, campaign_details,
106+
redirect_rule_details)
107+
108+
assert g.audit_log.response.condition, condition_name
109+
cond = g.audit_log.response.condition[0]
110+
assert cond.condition_name == condition_name
111+
assert cond.campaign_id == campaign_details[0]
112+
assert cond.status == best_results[1].status.name
113+
assert cond.status_text == best_results[1].status.name
114+
115+
def test_add_response_details_adds_to_audit_log(app):
116+
eligibility_response = EligibilityResponseFactory.build(response_id=uuid.uuid4(),
117+
meta={"last_updated": datetime(2023, 1, 1, 0, 0)},
118+
processed_suggestions=[])
119+
120+
with app.app_context():
121+
g.audit_log = AuditEvent()
122+
123+
AuditContext.add_response_details(eligibility_response)
124+
125+
assert g.audit_log.response.response_id == eligibility_response.response_id
126+
assert g.audit_log.response.last_updated is eligibility_response.meta.last_updated
127+
128+

0 commit comments

Comments
 (0)