Skip to content

Commit 83e6ea4

Browse files
New: [AEA-5899] - Expand PfP coverage (#504)
## Summary - ✨ New Feature ### Details Extend PfP test coverage --------- Signed-off-by: Connor Avery <[email protected]>
1 parent 42b3138 commit 83e6ea4

File tree

5 files changed

+269
-3
lines changed

5 files changed

+269
-3
lines changed

features/pfp/view_prescriptions.feature

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,62 @@ Feature: I can see my prescriptions
88
When I am authenticated with PFP-APIGEE app
99
And I request my prescriptions
1010
Then I can see my prescription
11+
12+
# Spine defined limit of 25 prescriptions per request
13+
Scenario: I can see a maximum of 25 prescriptions
14+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
15+
And I successfully prepare and sign '26' nominated acute prescriptions
16+
When I am authenticated with PFP-APIGEE app
17+
And I request my prescriptions
18+
Then I can see '25' of my prescriptions
19+
20+
# FLAKY WARNING: We've agreed to rely on NHS random generation to return an NHS number without prescriptions
21+
# This may cause flakiness if the random NHS number happens to have prescriptions
22+
Scenario: I can see no prescriptions
23+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
24+
And I successfully prepare and sign '0' nominated acute prescriptions
25+
When I am authenticated with PFP-APIGEE app
26+
And I request my prescriptions
27+
Then I can see '0' of my prescriptions
28+
29+
Scenario: I cannot see unreleased prescriptions
30+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
31+
And I successfully prepare a nominated acute prescription
32+
When I am authenticated with PFP-APIGEE app
33+
And I request my prescriptions
34+
Then I cannot see my unreleased prescriptions
35+
36+
Scenario: I cannot see eRD prescription items
37+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
38+
And I successfully prepare and sign a nominated eRD prescription
39+
When I am authenticated with PFP-APIGEE app
40+
And I request my prescriptions
41+
Then I do not see an eRD prescription
42+
43+
Scenario: I can see a FHIR compliant response for my prescriptions
44+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
45+
And I successfully prepare and sign a nominated acute prescription
46+
When I am authenticated with PFP-APIGEE app
47+
And I request my prescriptions
48+
Then I validate the prescription matches my prepared prescription
49+
50+
@e2e
51+
Scenario: I can see prescription item status (multiple statuses, multiple items) - acute, repeat
52+
Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
53+
And I successfully prepare and sign '2' nominated acute prescriptions
54+
And I am an authorised dispenser with EPS-FHIR-DISPENSING app
55+
And I release all prescriptions
56+
When I set the statuses I will update through
57+
| Status |
58+
| With Pharmacy |
59+
Then I process the status updates for the prescription items and verify they are returned
60+
61+
# This scenario requires changes to FHIR compliance endpoint to be able to validate PFP responses
62+
# Scenario: I can see prescription item details in FHIR compliant response
63+
# Given I am an authorised prescriber with EPS-FHIR-PRESCRIBING app
64+
# And I successfully prepare and sign a prescription
65+
# When I am authenticated with PFP-APIGEE app
66+
# And I request my prescriptions
67+
# Then I am an authorised prescriber with EPS-FHIR app
68+
# And I validate the response for FHIR compliance
69+
# And the response indicates a success

features/steps/common_steps.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ def indicate_bad_request_response(context):
149149
common.the_expected_response_code_is_returned(context, 400)
150150

151151

152+
@then("the response indicates forbidden")
153+
def indicate_forbidden_response(context):
154+
if "sandbox" in context.config.userdata["env"].lower():
155+
return
156+
common.the_expected_response_code_is_returned(context, 403)
157+
158+
152159
@then("the response indicates not found resource")
153160
def indicate_not_found_response(context):
154161
if "sandbox" in context.config.userdata["env"].lower():

features/steps/eps_api_steps.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
from messages.eps_fhir.dispense_notification import DNProps
2828

2929

30-
def setup_new_prescription(context, nomination, prescription_type):
31-
context.nhs_number = generate_single()
30+
def setup_new_prescription(
31+
context, nomination, prescription_type, generate_nhs_number=True
32+
):
33+
if generate_nhs_number:
34+
context.nhs_number = generate_single()
3235
if nomination == "non-nominated":
3336
context.nomination_code = "0004"
3437
if nomination == "nominated":
@@ -191,6 +194,25 @@ def i_am_an_authorised_user(context, user, app):
191194
context.auth_method = "oauth2"
192195

193196

197+
@given(
198+
"I successfully prepare and sign '{count:d}' {nomination} {prescription_type} prescriptions"
199+
)
200+
def i_successfully_prepare_and_sign_prescriptions(
201+
context, count, nomination, prescription_type
202+
):
203+
context.nhs_number = generate_single()
204+
prescription_ids = []
205+
for _ in range(count):
206+
setup_new_prescription(context, nomination, prescription_type, False)
207+
prepare_prescription(context)
208+
209+
# Capture IDs as object created
210+
prescription_ids.append(context.prescription_id)
211+
create_signed_prescription(context)
212+
213+
context.prescription_ids = prescription_ids
214+
215+
194216
@given("I successfully prepare a {nomination} {prescription_type} prescription")
195217
def i_prepare_a_new_prescription(context, nomination, prescription_type):
196218
setup_new_prescription(context, nomination, prescription_type)
@@ -208,6 +230,14 @@ def i_sign_a_new_prescription(context):
208230
create_signed_prescription(context)
209231

210232

233+
@given("I release all prescriptions")
234+
def i_release_all_prescriptions(context):
235+
for prescription_id in context.prescription_ids:
236+
context.prescription_id = prescription_id
237+
print(f"Releasing prescription ID: {prescription_id}")
238+
release_signed_prescription(context)
239+
240+
211241
@when("I try to release the prescription")
212242
@step("I release the prescription")
213243
def i_release_the_prescription(context):

features/steps/pfp_api_steps.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from methods.api.pfp_api_methods import get_prescriptions
77
from methods.shared.common import assert_that, get_auth
8+
from methods.api.eps_api_methods import call_validator
9+
from messages.eps_fhir.prescription import Prescription
810

911

1012
@when("I am authenticated with {app} app")
@@ -25,6 +27,29 @@ def i_request_my_prescriptions(context):
2527
get_prescriptions(context)
2628

2729

30+
@when("I check the prescription item statuses for '{status}'")
31+
def i_check_the_prescription_item_statuses_for_status(context, status):
32+
json_response = json.loads(context.response.content)
33+
entries = json_response["entry"]
34+
bundles = [
35+
entry for entry in entries if entry["resource"]["resourceType"] == "Bundle"
36+
]
37+
38+
# Extract all status codes from MedicationRequest extensions
39+
status_codes = [
40+
extension["valueCoding"]["code"]
41+
for bundle in bundles
42+
for entry in bundle["resource"]["entry"]
43+
if entry["resource"]["resourceType"] == "MedicationRequest"
44+
for extension in entry["resource"]["extension"][0]["extension"]
45+
if extension["url"] == "status"
46+
]
47+
48+
# Assert all status codes match the expected status
49+
for status_code in status_codes:
50+
assert_that(status_code).is_equal_to(status)
51+
52+
2853
@then("I can see my prescription")
2954
def i_can_see_my_prescription(context):
3055
json_response = json.loads(context.response.content)
@@ -46,3 +71,144 @@ def i_can_see_my_prescription(context):
4671
assert_that(bundle["groupIdentifier"]["value"]).is_equal_to(
4772
expected_prescription_id
4873
)
74+
75+
76+
@then("I can see '{number}' of my prescriptions")
77+
def i_can_see_my_prescriptions(context, number):
78+
json_response = json.loads(context.response.content)
79+
entries = json_response["entry"]
80+
total = json_response["total"]
81+
prescription_bundles = [
82+
entry for entry in entries if entry["resource"]["resourceType"] == "Bundle"
83+
]
84+
85+
assert_that(total).is_equal_to(int(number))
86+
assert_that(len(prescription_bundles)).is_equal_to(int(number))
87+
assert_that(total).is_less_than_or_equal_to(25)
88+
89+
90+
@then("I cannot see my unreleased prescriptions")
91+
def i_cannot_see_my_prescription(context):
92+
json_response = json.loads(context.response.content)
93+
entries = json_response["entry"]
94+
bundle_entries = [
95+
entry for entry in entries if entry["resource"]["resourceType"] == "Bundle"
96+
]
97+
assert_that(len(bundle_entries)).is_equal_to(0)
98+
assert_that(json_response["total"]).is_equal_to(0)
99+
100+
101+
@then("I validate the response for FHIR compliance")
102+
def i_validate_the_response_for_fhir_compliance(context):
103+
context.nomination_code = "0004"
104+
context.intent = "order"
105+
context.type_code = "acute"
106+
validate_body = Prescription(context).body
107+
108+
call_validator(context, "eps_fhir_dispensing", "true", validate_body)
109+
110+
print("validation response:")
111+
print(context.response.content)
112+
print(context.response.status_code)
113+
114+
115+
@then("I do not see an eRD prescription")
116+
def i_do_not_see_an_erd_prescription(context):
117+
json_response = json.loads(context.response.content)
118+
entries = json_response["entry"]
119+
bundle_entries = [
120+
entry for entry in entries if entry["resource"]["resourceType"] == "Bundle"
121+
]
122+
for bundle_entry in bundle_entries:
123+
prescription_type = bundle_entry["resource"]["courseOfTherapyType"]["coding"][
124+
0
125+
]["code"]
126+
assert_that(prescription_type).is_not_equal_to("continuous-repeat-dispensing")
127+
128+
129+
@then("I validate the prescription matches my prepared prescription")
130+
def i_validate_the_response_prescription_matches_my_prepared_prescription(context):
131+
json_response = json.loads(context.response.content)
132+
entries = json_response["entry"]
133+
134+
# Mock prescription construct builds the same "prescription" each time
135+
# so using 0 index is safe for asserting values
136+
bundle = [
137+
entry for entry in entries if entry["resource"]["resourceType"] == "Bundle"
138+
]
139+
140+
prescription = bundle[0]["resource"]["entry"]
141+
142+
# Dynamically test against Medication Requests
143+
expected_entries = json.loads(context.prepare_body)["entry"]
144+
returned_medication_codeable_concepts = [
145+
each
146+
for each in prescription
147+
if each["resource"]["resourceType"] == "MedicationRequest"
148+
]
149+
expected_medication_codeable_concepts = [
150+
each
151+
for each in expected_entries
152+
if each["resource"]["resourceType"] == "MedicationRequest"
153+
]
154+
155+
expected_items = expected_medication_codeable_concepts[0]["resource"][
156+
"medicationCodeableConcept"
157+
]["coding"]
158+
returned_items = returned_medication_codeable_concepts[0]["resource"][
159+
"medicationCodeableConcept"
160+
]["coding"]
161+
for item in expected_items:
162+
for key, value in item.items():
163+
if key != "system":
164+
assert_that(returned_items[0][key]).is_equal_to(value)
165+
else:
166+
# Skip system as the mock prescription uses http vs. PFP returning https address
167+
pass
168+
169+
170+
@when("I set the statuses I will update through")
171+
def set_statuses_for_pfp(context):
172+
context.statuses = [row["Status"] for row in context.table]
173+
174+
175+
@then(
176+
"I process the status updates for the prescription items and verify they are returned"
177+
)
178+
def process_status_updates_and_verify(context):
179+
# For each prescription ID in the scenario, update the status according to data table
180+
# Loop over all available statuses
181+
# DON'T COPY THIS -- It's crude for now until we come back to it.
182+
for status in context.statuses:
183+
print(f"Processing status update to {status} for all prescription IDs")
184+
context.execute_steps(
185+
"""
186+
When I am authorised to send prescription updates
187+
"""
188+
)
189+
for prescription_id in context.prescription_ids:
190+
context.prescription_id = prescription_id
191+
print(f"Processing status update for prescription ID: {prescription_id}")
192+
if (
193+
status.upper() == "COLLECTED"
194+
or status.upper() == "DISPENSED"
195+
or status.upper() == "NOT DISPENSED"
196+
):
197+
terminal = "completed"
198+
else:
199+
terminal = "in-progress"
200+
201+
context.execute_steps(
202+
f"""
203+
When I send an {status} update with a terminal status of {terminal}
204+
"""
205+
)
206+
# Call the PFP API to get the prescriptions and verify the statuses
207+
print(f"Verifying updated prescription statuses to be {status}")
208+
context.execute_steps(
209+
f"""
210+
When I am authenticated with PFP-APIGEE app
211+
And I request my prescriptions
212+
And I check the prescription item statuses for '{status}'
213+
"""
214+
)

features/steps/psu_api_steps.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@ def i_send_an_update(context, status, terminal):
2626
if "e2e" not in context.tags or "sandbox" in context.config.userdata["env"].lower():
2727
context.receiver_ods_code = "FA565"
2828
context.prescription_id = generate_short_form_id(context.receiver_ods_code)
29+
print(f"id from here {context.prescription_id}")
2930
context.prescription_item_id = uuid.uuid4()
3031
context.nhs_number = generate_single()
3132
context.terminal_status = terminal
3233
context.item_status = status
33-
34+
print(
35+
f"""Sending status update: {status} with terminal status: {terminal}
36+
for prescription ID: {context.prescription_id}"""
37+
)
3438
send_status_update(context)
3539

3640

0 commit comments

Comments
 (0)