Skip to content

Commit a228100

Browse files
committed
VED-746: search by identifier backward compatibility
1 parent 8a3169b commit a228100

File tree

1 file changed

+32
-134
lines changed

1 file changed

+32
-134
lines changed

e2e/test_search_by_identifier.py

Lines changed: 32 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,13 @@ def test_search_imms(self):
2929
with self.subTest(imms_api):
3030
# Given two patients each with one covid_19
3131
covid_19_p1 = generate_imms_resource()
32-
covid_19_p2 = generate_imms_resource()
3332
rsv_p1 = generate_imms_resource()
34-
rsv_p2 = generate_imms_resource()
35-
covid_ids = self.store_records(covid_19_p1, covid_19_p2)
36-
rsv_ids = self.store_records(rsv_p1, rsv_p2)
33+
covid_ids = self.store_records(covid_19_p1)
34+
rsv_ids = self.store_records(rsv_p1)
3735

3836
# Retrieve the resources to get the identifier system and value via read API
39-
covid_resource = imms_api.get_immunization_by_id(covid_ids[0])
40-
rsv_resource = imms_api.get_immunization_by_id(rsv_ids[0])
37+
covid_resource = imms_api.get_immunization_by_id(covid_ids).json()
38+
rsv_resource = imms_api.get_immunization_by_id(rsv_ids).json()
4139

4240
# Extract identifier components safely for covid resource
4341
identifiers = covid_resource.get("identifier", [])
@@ -70,29 +68,15 @@ def test_search_imms(self):
7068
self.assertTrue(entries, "Expected at least one match in Bundle.entry")
7169
self.assertEqual(len(entries), 1, f"Expected exactly one match, got {len(entries)}")
7270

73-
def test_search_patient_multiple_diseases(self):
74-
# Given patient has two vaccines
75-
covid_19 = generate_imms_resource(valid_nhs_number1, VaccineTypes.covid_19)
76-
flu = generate_imms_resource(valid_nhs_number1, VaccineTypes.flu)
77-
covid_19_id, flu_id = self.store_records(covid_19, flu)
78-
79-
# When
80-
response = self.default_imms_api.search_immunizations(valid_nhs_number1, VaccineTypes.covid_19)
81-
82-
# Then
83-
self.assertEqual(response.status_code, 200, response.text)
84-
body = response.json()
85-
86-
resource_ids = [entity["resource"]["id"] for entity in body["entry"]]
87-
self.assertIn(covid_19_id, resource_ids)
88-
self.assertNotIn(flu_id, resource_ids)
89-
9071
def test_search_backwards_compatible(self):
91-
"""Test that SEARCH 200 response body is backwards compatible with Immunisation History FHIR API"""
72+
"""Test that SEARCH 200 response body is backwards compatible with Immunisation History FHIR API.
73+
This test proves that the search endpoint’s response is still shaped exactly like the
74+
Immunisation History FHIR API expects (“backwards compatible”), not just that it returns a 200
75+
"""
9276
for imms_api in self.imms_apis:
9377
with self.subTest(imms_api):
94-
# Given that the patient has a covid_19 vaccine event stored in the IEDS
95-
stored_imms_resource = generate_imms_resource(valid_nhs_number1, VaccineTypes.covid_19)
78+
79+
stored_imms_resource = generate_imms_resource()
9680
imms_identifier_value = stored_imms_resource["identifier"][0]["value"]
9781
imms_id = self.store_records(stored_imms_resource)
9882

@@ -107,8 +91,16 @@ def test_search_backwards_compatible(self):
10791
expected_imms_resource["id"] = imms_id
10892
expected_imms_resource["meta"] = {"versionId": "1"}
10993

94+
# Retrieve the resource to get the identifier system and value via READ API
95+
imms_resource = imms_api.get_immunization_by_id(imms_id).json()
96+
identifiers = imms_resource.get("identifier", [])
97+
identifier_system = identifiers[0].get("system")
98+
identifier_value = identifiers[0].get("value")
99+
self.assertIsNotNone(identifier_system, "Identifier system is None")
100+
self.assertIsNotNone(identifier_value, "Identifier value is None")
101+
110102
# When
111-
response = imms_api.search_immunizations(valid_nhs_number1, VaccineTypes.covid_19)
103+
response = imms_api.search_immunization_by_identifier(identifier_system, identifier_value)
112104

113105
# Then
114106
self.assertEqual(response.status_code, 200, response.text)
@@ -127,53 +119,28 @@ def test_search_backwards_compatible(self):
127119

128120
# Check that entry only contains a patient and immunizations
129121
self.assertEqual(len(response_other_entries), 0)
130-
self.assertEqual(len(response_patients), 1)
131-
132-
# Check patient structure
133-
response_patient = response_patients[0]
134-
self.assertEqual(response_patient["search"], {"mode": "include"})
135-
self.assertTrue(response_patient["fullUrl"].startswith("urn:uuid:"))
136-
self.assertTrue(uuid.UUID(response_patient["fullUrl"].split(":")[2]))
137-
expected_patient_resource_keys = ["resourceType", "id", "identifier"]
138-
self.assertEqual(sorted(response_patient["resource"].keys()), sorted(expected_patient_resource_keys))
139-
self.assertEqual(response_patient["resource"]["id"], valid_nhs_number1)
140-
patient_identifier = response_patient["resource"]["identifier"]
141-
# NOTE: If PDS response ever changes to send more than one identifier then the below will break
142-
self.assertEqual(len(patient_identifier), 1, "PDS did not return 1 identifier")
143-
self.assertEqual(sorted(patient_identifier[0].keys()), sorted(["system", "value"]))
144-
self.assertEqual(patient_identifier[0]["system"], "https://fhir.nhs.uk/Id/nhs-number")
145-
self.assertEqual(patient_identifier[0]["value"], valid_nhs_number1)
122+
self.assertEqual(len(response_patients), 0)
123+
124+
# Check Immunization structure
125+
for entry in response_imms:
126+
self.assertEqual(entry["search"], {"mode": "match"})
127+
self.assertTrue(entry["fullUrl"].startswith("https://"))
128+
self.assertEqual(entry["resource"]["resourceType"], "Immunization")
129+
imms_identifier = entry["resource"]["identifier"]
130+
self.assertEqual(len(imms_identifier), 1, "Immunization did not have exactly 1 identifier")
131+
self.assertEqual(imms_identifier[0]["system"], identifier_system)
132+
self.assertEqual(imms_identifier[0]["value"], identifier_value)
146133

147134
# Check structure of one of the imms resources
148-
expected_imms_resource["patient"]["reference"] = response_patient["fullUrl"]
135+
# expected_imms_resource["patient"]["reference"] = response_patient["fullUrl"]
149136
response_imm = next(item for item in entries if item["resource"]["id"] == imms_id)
150137
self.assertEqual(
151138
response_imm["fullUrl"], f"{get_service_base_path()}/Immunization/{imms_id}"
152139
)
153140
self.assertEqual(response_imm["search"], {"mode": "match"})
141+
expected_imms_resource["patient"]["reference"] = response_imm["resource"]["patient"]["reference"]
154142
self.assertEqual(response_imm["resource"], expected_imms_resource)
155143

156-
def test_search_ignore_deleted(self):
157-
# Given patient has three vaccines and the last one is deleted
158-
mmr1 = generate_imms_resource(valid_nhs_number1, VaccineTypes.mmr)
159-
mmr2 = generate_imms_resource(valid_nhs_number1, VaccineTypes.mmr)
160-
mmr1_id, mmr2_id = self.store_records(mmr1, mmr2)
161-
162-
to_delete_mmr = generate_imms_resource(valid_nhs_number1, VaccineTypes.mmr)
163-
deleted_mmr = self.default_imms_api.create_a_deleted_immunization_resource(to_delete_mmr)
164-
165-
# When
166-
response = self.default_imms_api.search_immunizations(valid_nhs_number1, VaccineTypes.mmr)
167-
168-
# Then
169-
self.assertEqual(response.status_code, 200, response.text)
170-
body = response.json()
171-
172-
resource_ids = [entity["resource"]["id"] for entity in body["entry"]]
173-
self.assertTrue(mmr1_id in resource_ids)
174-
self.assertTrue(mmr2_id in resource_ids)
175-
self.assertTrue(deleted_mmr["id"] not in resource_ids)
176-
177144
def test_search_immunization_parameter_smoke_tests(self):
178145
time_1 = "2024-01-30T13:28:17.271+00:00"
179146
time_2 = "2024-02-01T13:28:17.271+00:00"
@@ -361,72 +328,3 @@ class SearchTestParams(NamedTuple):
361328
assert len(created_and_returned_ids) == len(search.expected_indexes)
362329
for expected_index in search.expected_indexes:
363330
assert created_resource_ids[expected_index] in result_ids
364-
365-
def test_search_immunization_accepts_include_and_provides_patient(self):
366-
"""it should accept the _include parameter of "Immunization:patient" and return the patient."""
367-
368-
# Arrange
369-
imms_obj = generate_imms_resource(valid_nhs_number1, VaccineTypes.mmr)
370-
imms_obj_id = self.store_records(imms_obj)
371-
372-
response = self.default_imms_api.search_immunizations_full(
373-
"POST",
374-
f"patient.identifier={valid_patient_identifier1}&-immunization.target={VaccineTypes.mmr}"
375-
+ "&_include=Immunization:patient",
376-
body=None,
377-
)
378-
379-
assert response.ok
380-
result = response.json()
381-
entries = result["entry"]
382-
383-
entry_ids = [result["resource"]["id"] for result in result["entry"]]
384-
assert imms_obj_id in entry_ids
385-
386-
patient_entry = next(entry for entry in entries if entry["resource"]["resourceType"] == "Patient")
387-
assert patient_entry["search"]["mode"] == "include"
388-
389-
assert patient_entry["resource"]["identifier"][0]["system"] == "https://fhir.nhs.uk/Id/nhs-number"
390-
assert patient_entry["resource"]["identifier"][0]["value"] == valid_nhs_number1
391-
392-
response_without_include = self.default_imms_api.search_immunizations_full(
393-
"POST",
394-
f"patient.identifier={valid_patient_identifier1}&-immunization.target={VaccineTypes.mmr}",
395-
body=None
396-
)
397-
398-
assert response_without_include.ok
399-
result_without_include = response_without_include.json()
400-
401-
# Matches Immunisation History API in that it doesn't matter if you don't pass "_include".
402-
403-
# Ignore link, patient full url and immunisation patient reference as these will always differ.
404-
result["link"] = []
405-
result_without_include["link"] = []
406-
407-
for entry in result["entry"]:
408-
if entry["resource"]["resourceType"] == "Immunization":
409-
entry["resource"]["patient"]["reference"] = "MOCK VALUE"
410-
elif entry["resource"]["resourceType"] == "Patient":
411-
entry["fullUrl"] = "MOCK VALUE"
412-
413-
for entry in result_without_include["entry"]:
414-
if entry["resource"]["resourceType"] == "Immunization":
415-
entry["resource"]["patient"]["reference"] = "MOCK VALUE"
416-
elif entry["resource"]["resourceType"] == "Patient":
417-
entry["fullUrl"] = "MOCK VALUE"
418-
419-
self.assertEqual(result, result_without_include)
420-
421-
def test_search_reject_tbc(self):
422-
# Given patient has a vaccine with no NHS number
423-
imms = generate_imms_resource("TBC", VaccineTypes.mmr)
424-
del imms["contained"][1]["identifier"][0]["value"]
425-
self.store_records(imms)
426-
427-
# When
428-
response = self.default_imms_api.search_immunizations("TBC", f"{VaccineTypes.mmr}",
429-
expected_status_code=400)
430-
431-
# Then
432-
self.assert_operation_outcome(response, 400)

0 commit comments

Comments
 (0)