Skip to content

Commit 7167f45

Browse files
authored
Merge pull request #890 from NHSDigital/feature/eema1-NRL-1285-emptySegmentinOptionalFieldReturns400
NRL-1285 validate that doc ref cant be created with empty fields
2 parents 05d5b9a + c28069f commit 7167f45

File tree

14 files changed

+213
-308
lines changed

14 files changed

+213
-308
lines changed

api/producer/createDocumentReference/tests/test_create_document_reference.py

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,50 @@ def test_create_document_reference_invalid_body():
384384
}
385385

386386

387+
def test_create_document_reference_empty_fields_in_body():
388+
doc_ref = load_document_reference("Y05868-736253002-Valid")
389+
doc_ref.author = []
390+
doc_ref.custodian = {"identifier": {}, "reference": None}
391+
doc_ref.category = [{"coding": [{"system": "", "code": None}]}]
392+
doc_ref.text = ""
393+
394+
event = create_test_api_gateway_event(
395+
headers=create_headers(),
396+
body=doc_ref.model_dump_json(exclude_none=True),
397+
)
398+
result = handler(event, create_mock_context())
399+
body = result.pop("body")
400+
401+
assert result == {
402+
"statusCode": "400",
403+
"headers": default_response_headers(),
404+
"isBase64Encoded": False,
405+
}
406+
407+
parsed_body = json.loads(body)
408+
409+
assert parsed_body == {
410+
"resourceType": "OperationOutcome",
411+
"issue": [
412+
{
413+
"severity": "error",
414+
"code": "invalid",
415+
"details": {
416+
"coding": [
417+
{
418+
"code": "MESSAGE_NOT_WELL_FORMED",
419+
"display": "Message not well formed",
420+
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
421+
}
422+
],
423+
},
424+
"diagnostics": "Request body could not be parsed (DocumentReference: Value error, The following fields are empty: text, author, custodian.reference, custodian.identifier, category[0].coding[0].system, category[0].coding[0].code)",
425+
"expression": ["DocumentReference"],
426+
}
427+
],
428+
}
429+
430+
387431
def test_create_document_reference_invalid_resource():
388432
doc_ref = load_document_reference("Y05868-736253002-Valid")
389433
doc_ref.custodian = None
@@ -781,9 +825,7 @@ def test_create_document_reference_cannot_set_status_to_not_current(repository):
781825
def test_create_document_reference_no_relatesto_target():
782826
doc_ref = load_document_reference("Y05868-736253002-Valid")
783827
doc_ref.relatesTo = [
784-
DocumentReferenceRelatesTo(
785-
code="transforms", target=Reference(reference=None, identifier=None)
786-
)
828+
DocumentReferenceRelatesTo(code="transforms", target=Reference())
787829
]
788830

789831
event = create_test_api_gateway_event(
@@ -795,7 +837,7 @@ def test_create_document_reference_no_relatesto_target():
795837
body = result.pop("body")
796838

797839
assert result == {
798-
"statusCode": "422",
840+
"statusCode": "400",
799841
"headers": default_response_headers(),
800842
"isBase64Encoded": False,
801843
}
@@ -807,18 +849,18 @@ def test_create_document_reference_no_relatesto_target():
807849
"issue": [
808850
{
809851
"severity": "error",
810-
"code": "business-rule",
852+
"code": "invalid",
811853
"details": {
812854
"coding": [
813855
{
814-
"code": "UNPROCESSABLE_ENTITY",
815-
"display": "Unprocessable Entity",
856+
"code": "MESSAGE_NOT_WELL_FORMED",
857+
"display": "Message not well formed",
816858
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
817859
}
818-
]
860+
],
819861
},
820-
"diagnostics": "No identifier value provided for relatesTo target",
821-
"expression": ["relatesTo[0].target.identifier.value"],
862+
"diagnostics": "Request body could not be parsed (DocumentReference: Value error, The following fields are empty: relatesTo[0].target)",
863+
"expression": ["DocumentReference"],
822864
}
823865
],
824866
}
@@ -829,9 +871,7 @@ def test_create_document_reference_invalid_relatesto_target_producer_id():
829871
doc_ref.relatesTo = [
830872
DocumentReferenceRelatesTo(
831873
code="transforms",
832-
target=Reference(
833-
reference=None, identifier=Identifier(value="X26-99999-99999-999999")
834-
),
874+
target=Reference(identifier=Identifier(value="X26-99999-99999-999999")),
835875
)
836876
]
837877

@@ -881,7 +921,6 @@ def test_create_document_reference_invalid_relatesto_not_exists(repository):
881921
DocumentReferenceRelatesTo(
882922
code="transforms",
883923
target=Reference(
884-
reference=None,
885924
identifier=Identifier(value="Y05868-123456-123456-123456"),
886925
),
887926
)
@@ -942,9 +981,7 @@ def test_create_document_reference_invalid_relatesto_nhs_number(
942981
doc_ref.relatesTo = [
943982
DocumentReferenceRelatesTo(
944983
code="transforms",
945-
target=Reference(
946-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
947-
),
984+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
948985
)
949986
]
950987

@@ -1004,9 +1041,7 @@ def test_create_document_reference_invalid_relatesto_type(
10041041
doc_ref.relatesTo = [
10051042
DocumentReferenceRelatesTo(
10061043
code="transforms",
1007-
target=Reference(
1008-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1009-
),
1044+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
10101045
)
10111046
]
10121047

@@ -1220,9 +1255,7 @@ def test_create_document_reference_supersede_deletes_old_pointers_replace(
12201255
doc_ref.relatesTo = [
12211256
DocumentReferenceRelatesTo(
12221257
code="replaces",
1223-
target=Reference(
1224-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1225-
),
1258+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
12261259
)
12271260
]
12281261

@@ -1281,9 +1314,7 @@ def test_create_document_reference_supersede_succeeds_with_toggle(
12811314
doc_ref.relatesTo = [
12821315
DocumentReferenceRelatesTo(
12831316
code="replaces",
1284-
target=Reference(
1285-
reference=None, identifier=Identifier(value="Y05868-99999-99999-000000")
1286-
),
1317+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-000000")),
12871318
)
12881319
]
12891320

@@ -1341,9 +1372,7 @@ def test_create_document_reference_supersede_fails_without_toggle(
13411372
doc_ref.relatesTo = [
13421373
DocumentReferenceRelatesTo(
13431374
code="replaces",
1344-
target=Reference(
1345-
reference=None, identifier=Identifier(value="Y05868-99999-99999-000000")
1346-
),
1375+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-000000")),
13471376
)
13481377
]
13491378

@@ -1400,9 +1429,7 @@ def test_create_document_reference_create_relatesto_not_replaces(
14001429
doc_ref.relatesTo = [
14011430
DocumentReferenceRelatesTo(
14021431
code="transforms",
1403-
target=Reference(
1404-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1405-
),
1432+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
14061433
)
14071434
]
14081435

api/producer/updateDocumentReference/tests/test_update_document_reference.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_update_document_reference_happy_path(repository: DocumentPointerReposit
4040
event = create_test_api_gateway_event(
4141
headers=create_headers(),
4242
path_parameters={"id": "Y05868-99999-99999-999999"},
43-
body=doc_ref.model_dump_json(),
43+
body=doc_ref.model_dump_json(exclude_none=True),
4444
)
4545

4646
result = handler(event, create_mock_context())
@@ -109,7 +109,7 @@ def test_update_document_reference_happy_path_with_ssp(
109109
event = create_test_api_gateway_event(
110110
headers=create_headers(),
111111
path_parameters={"id": "Y05868-99999-99999-999999"},
112-
body=doc_ref.model_dump_json(),
112+
body=doc_ref.model_dump_json(exclude_none=True),
113113
)
114114

115115
result = handler(event, create_mock_context())
@@ -580,18 +580,13 @@ def test_update_document_reference_immutable_fields(repository):
580580
repository.create(doc_pointer)
581581

582582
doc_ref.type = CodeableConcept(
583-
id=None,
584583
coding=[
585584
Coding(
586-
id=None,
587585
system="http://snomed.info/sct",
588-
version=None,
589586
code="861421000000109",
590587
display="End of life care coordination summary",
591-
userSelected=None,
592588
)
593589
],
594-
text=None,
595590
)
596591

597592
event = create_test_api_gateway_event(
@@ -861,7 +856,7 @@ def test_update_document_reference_with_meta_lastupdated_ignored(
861856
event = create_test_api_gateway_event(
862857
headers=create_headers(),
863858
path_parameters={"id": "Y05868-99999-99999-999999"},
864-
body=doc_ref.model_dump_json(),
859+
body=doc_ref.model_dump_json(exclude_none=True),
865860
)
866861

867862
result = handler(event, create_mock_context())
@@ -931,7 +926,7 @@ def test_update_document_reference_with_invalid_date_ignored(
931926
event = create_test_api_gateway_event(
932927
headers=create_headers(),
933928
path_parameters={"id": "Y05868-99999-99999-999999"},
934-
body=doc_ref.model_dump_json(),
929+
body=doc_ref.model_dump_json(exclude_none=True),
935930
)
936931

937932
result = handler(event, create_mock_context())

api/producer/upsertDocumentReference/tests/test_upsert_document_reference.py

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -748,9 +748,7 @@ def test_upsert_document_reference_pointer_type_not_allowed(
748748
def test_upsert_document_reference_no_relatesto_target():
749749
doc_ref = load_document_reference("Y05868-736253002-Valid")
750750
doc_ref.relatesTo = [
751-
DocumentReferenceRelatesTo(
752-
code="transforms", target=Reference(reference=None, identifier=None)
753-
)
751+
DocumentReferenceRelatesTo(code="transforms", target=Reference())
754752
]
755753

756754
event = create_test_api_gateway_event(
@@ -762,7 +760,7 @@ def test_upsert_document_reference_no_relatesto_target():
762760
body = result.pop("body")
763761

764762
assert result == {
765-
"statusCode": "422",
763+
"statusCode": "400",
766764
"headers": default_response_headers(),
767765
"isBase64Encoded": False,
768766
}
@@ -774,18 +772,18 @@ def test_upsert_document_reference_no_relatesto_target():
774772
"issue": [
775773
{
776774
"severity": "error",
777-
"code": "business-rule",
775+
"code": "invalid",
778776
"details": {
779777
"coding": [
780778
{
781-
"code": "UNPROCESSABLE_ENTITY",
782-
"display": "Unprocessable Entity",
779+
"code": "MESSAGE_NOT_WELL_FORMED",
780+
"display": "Message not well formed",
783781
"system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1",
784782
}
785-
]
783+
],
786784
},
787-
"diagnostics": "No identifier value provided for relatesTo target",
788-
"expression": ["relatesTo[0].target.identifier.value"],
785+
"diagnostics": "Request body could not be parsed (DocumentReference: Value error, The following fields are empty: relatesTo[0].target)",
786+
"expression": ["DocumentReference"],
789787
}
790788
],
791789
}
@@ -796,9 +794,7 @@ def test_upsert_document_reference_invalid_relatesto_target_producer_id():
796794
doc_ref.relatesTo = [
797795
DocumentReferenceRelatesTo(
798796
code="transforms",
799-
target=Reference(
800-
reference=None, identifier=Identifier(value="X26-99999-99999-999999")
801-
),
797+
target=Reference(identifier=Identifier(value="X26-99999-99999-999999")),
802798
)
803799
]
804800

@@ -848,7 +844,6 @@ def test_upsert_document_reference_invalid_relatesto_not_exists(repository):
848844
DocumentReferenceRelatesTo(
849845
code="transforms",
850846
target=Reference(
851-
reference=None,
852847
identifier=Identifier(value="Y05868-99999-99999-999999"),
853848
),
854849
)
@@ -902,7 +897,6 @@ def test_upsert_document_reference_invalid_relatesto_not_exists_still_creates_wi
902897
DocumentReferenceRelatesTo(
903898
code="transforms",
904899
target=Reference(
905-
reference=None,
906900
identifier=Identifier(value="Y05868-99999-99999-999999"),
907901
),
908902
)
@@ -967,9 +961,7 @@ def test_upsert_document_reference_invalid_relatesto_nhs_number(
967961
doc_ref.relatesTo = [
968962
DocumentReferenceRelatesTo(
969963
code="transforms",
970-
target=Reference(
971-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
972-
),
964+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
973965
)
974966
]
975967

@@ -1029,9 +1021,7 @@ def test_upsert_document_reference_invalid_relatesto_type(
10291021
doc_ref.relatesTo = [
10301022
DocumentReferenceRelatesTo(
10311023
code="transforms",
1032-
target=Reference(
1033-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1034-
),
1024+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
10351025
)
10361026
]
10371027

@@ -1244,9 +1234,7 @@ def test_upsert_document_reference_supersede_deletes_old_pointers_replace(
12441234
doc_ref.relatesTo = [
12451235
DocumentReferenceRelatesTo(
12461236
code="replaces",
1247-
target=Reference(
1248-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1249-
),
1237+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
12501238
)
12511239
]
12521240

@@ -1304,9 +1292,7 @@ def test_upsert_document_reference_supersede_succeeds_with_toggle(
13041292
doc_ref.relatesTo = [
13051293
DocumentReferenceRelatesTo(
13061294
code="replaces",
1307-
target=Reference(
1308-
reference=None, identifier=Identifier(value="Y05868-99999-99999-000000")
1309-
),
1295+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-000000")),
13101296
)
13111297
]
13121298

@@ -1364,9 +1350,7 @@ def test_upsert_document_reference_supersede_fails_without_toggle(
13641350
doc_ref.relatesTo = [
13651351
DocumentReferenceRelatesTo(
13661352
code="replaces",
1367-
target=Reference(
1368-
reference=None, identifier=Identifier(value="Y05868-99999-99999-000000")
1369-
),
1353+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-000000")),
13701354
)
13711355
]
13721356

@@ -1422,9 +1406,7 @@ def test_upsert_document_reference_create_relatesto_not_replaces(
14221406
doc_ref.relatesTo = [
14231407
DocumentReferenceRelatesTo(
14241408
code="transforms",
1425-
target=Reference(
1426-
reference=None, identifier=Identifier(value="Y05868-99999-99999-999999")
1427-
),
1409+
target=Reference(identifier=Identifier(value="Y05868-99999-99999-999999")),
14281410
)
14291411
]
14301412

layer/nrlf/core/errors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ def append_value_set_url(loc_string: str) -> str:
3535

3636
def diag_for_error(error: ErrorDetails) -> str:
3737
loc_string = format_error_location(error["loc"])
38-
msg = f"{loc_string or 'root'}: {error['msg']}"
38+
msg = f"{loc_string or 'DocumentReference'}: {error['msg']}"
3939
msg += append_value_set_url(loc_string)
4040
return msg
4141

4242

4343
def expression_for_error(error: ErrorDetails) -> Optional[str]:
44-
return format_error_location(error["loc"]) or "root"
44+
return format_error_location(error["loc"]) or "DocumentReference"
4545

4646

4747
class OperationOutcomeError(Exception):

0 commit comments

Comments
 (0)