From d946923215ab26862080872dfb62e88f36897eb2 Mon Sep 17 00:00:00 2001 From: eesa456 Date: Fri, 13 Dec 2024 07:03:43 +0000 Subject: [PATCH 1/4] NRL-1076 add integration and unit tests for identifier accession number and error message fix --- .../search_document_reference.py | 2 +- ...test_search_document_reference_consumer.py | 44 +++++++++++++++++++ .../search_post_document_reference.py | 2 +- .../search_document_reference.py | 2 +- .../search_post_document_reference.py | 2 +- .../searchDocumentReference-failure.feature | 30 ++++++++++++- .../searchDocumentReference-success.feature | 38 ++++++++++++++++ ...earchPostDocumentReference-failure.feature | 30 ++++++++++++- tests/features/steps/3_assert.py | 8 ++++ tests/features/utils/data.py | 6 +++ 10 files changed, 158 insertions(+), 6 deletions(-) diff --git a/api/consumer/searchDocumentReference/search_document_reference.py b/api/consumer/searchDocumentReference/search_document_reference.py index ae590e0f8..d847e9ef4 100644 --- a/api/consumer/searchDocumentReference/search_document_reference.py +++ b/api/consumer/searchDocumentReference/search_document_reference.py @@ -53,7 +53,7 @@ def handler( pointer_types=metadata.pointer_types, ) return SpineErrorResponse.INVALID_CODE_SYSTEM( - diagnostics="Invalid query parameter (The provided type system does not match the allowed types for this organisation)", + diagnostics="Invalid query parameter (The provided type does not match the allowed types for this organisation)", expression="type", ) diff --git a/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py b/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py index 1f30aafc5..0453eea2c 100644 --- a/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py +++ b/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py @@ -59,6 +59,50 @@ def test_search_document_reference_happy_path(repository: DocumentPointerReposit } +@mock_aws +@mock_repository +def test_search_document_reference_accession_number_in_pointer( + repository: DocumentPointerRepository, +): + doc_ref = load_document_reference("Y05868-736253002-Valid") + doc_ref.identifier = [ + {"type": {"text": "Accession-Number"}, "value": "Y05868.123456789"} + ] + doc_pointer = DocumentPointer.from_document_reference(doc_ref) + repository.create(doc_pointer) + + event = create_test_api_gateway_event( + headers=create_headers(), + query_string_parameters={ + "subject:identifier": "https://fhir.nhs.uk/Id/nhs-number|6700028191", + }, + ) + + result = handler(event, create_mock_context()) + body = result.pop("body") + + assert result == { + "statusCode": "200", + "headers": default_response_headers(), + "isBase64Encoded": False, + } + + parsed_body = json.loads(body) + assert parsed_body == { + "resourceType": "Bundle", + "type": "searchset", + "total": 1, + "entry": [{"resource": doc_ref.model_dump(exclude_none=True)}], + } + + created_doc_pointer = repository.get_by_id("Y05868-99999-99999-999999") + + assert created_doc_pointer is not None + assert json.loads(created_doc_pointer.document)["identifier"] == [ + {"type": {"text": "Accession-Number"}, "value": "Y05868.123456789"} + ] + + @mock_aws @mock_repository def test_search_document_reference_happy_path_with_custodian( diff --git a/api/consumer/searchPostDocumentReference/search_post_document_reference.py b/api/consumer/searchPostDocumentReference/search_post_document_reference.py index 35f91366c..5ea555cf0 100644 --- a/api/consumer/searchPostDocumentReference/search_post_document_reference.py +++ b/api/consumer/searchPostDocumentReference/search_post_document_reference.py @@ -57,7 +57,7 @@ def handler( pointer_types=metadata.pointer_types, ) return SpineErrorResponse.INVALID_CODE_SYSTEM( - diagnostics="Invalid type (The provided type system does not match the allowed types for this organisation)", + diagnostics="Invalid type (The provided type does not match the allowed types for this organisation)", expression="type", ) diff --git a/api/producer/searchDocumentReference/search_document_reference.py b/api/producer/searchDocumentReference/search_document_reference.py index eb980f80c..e961e7b9f 100644 --- a/api/producer/searchDocumentReference/search_document_reference.py +++ b/api/producer/searchDocumentReference/search_document_reference.py @@ -55,7 +55,7 @@ def handler( pointer_types=metadata.pointer_types, ) return SpineErrorResponse.INVALID_CODE_SYSTEM( - diagnostics="Invalid query parameter (The provided type system does not match the allowed types for this organisation)", + diagnostics="Invalid query parameter (The provided type does not match the allowed types for this organisation)", expression="type", ) diff --git a/api/producer/searchPostDocumentReference/search_post_document_reference.py b/api/producer/searchPostDocumentReference/search_post_document_reference.py index fc6d8b535..023dcfe7c 100644 --- a/api/producer/searchPostDocumentReference/search_post_document_reference.py +++ b/api/producer/searchPostDocumentReference/search_post_document_reference.py @@ -49,7 +49,7 @@ def handler( pointer_types=metadata.pointer_types, ) return SpineErrorResponse.INVALID_CODE_SYSTEM( - diagnostics="The provided type system does not match the allowed types for this organisation", + diagnostics="The provided type does not match the allowed types for this organisation", expression="type", ) diff --git a/tests/features/consumer/searchDocumentReference-failure.feature b/tests/features/consumer/searchDocumentReference-failure.feature index 1de20623a..161e12bcd 100644 --- a/tests/features/consumer/searchDocumentReference-failure.feature +++ b/tests/features/consumer/searchDocumentReference-failure.feature @@ -77,7 +77,35 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios "display": "Invalid code system" }] }, - "diagnostics": "Invalid query parameter (The provided type system does not match the allowed types for this organisation)", + "diagnostics": "Invalid query parameter (The provided type does not match the allowed types for this organisation)", + "expression": ["type"] + } + """ + + Scenario: Search rejects request with type they are not allowed to use + Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + And the organisation 'RX898' is authorised to access pointer types: + | system | value | + | http://snomed.info/sct | 736253002 | + When consumer 'RX898' searches for DocumentReferences with parameters: + | parameter | value | + | subject | 9278693472 | + | type | http://snomed.info/sct\|887701000000100 | + Then the response status code is 400 + And the response is an OperationOutcome with 1 issue + And the OperationOutcome contains the issue: + """ + { + "severity": "error", + "code": "code-invalid", + "details": { + "coding": [{ + "system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1", + "code": "INVALID_CODE_SYSTEM", + "display": "Invalid code system" + }] + }, + "diagnostics": "Invalid query parameter (The provided type does not match the allowed types for this organisation)", "expression": ["type"] } """ diff --git a/tests/features/consumer/searchDocumentReference-success.feature b/tests/features/consumer/searchDocumentReference-success.feature index ead47a40e..1fd296127 100644 --- a/tests/features/consumer/searchDocumentReference-success.feature +++ b/tests/features/consumer/searchDocumentReference-success.feature @@ -36,6 +36,44 @@ Feature: Consumer - searchDocumentReference - Success Scenarios | custodian | 02V | | author | 02V | + Scenario: Search for a DocumentReference and Accession Number is in response + Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + And the organisation 'RX898' is authorised to access pointer types: + | system | value | + | http://snomed.info/sct | 736253002 | + And a DocumentReference resource exists with values: + | property | value | + | id | 02V-1111111111-SearchDocRefTest | + | subject | 9278693472 | + | status | current | + | type | 736253002 | + | category | 734163000 | + | contentType | application/pdf | + | url | https://example.org/my-doc.pdf | + | custodian | 02V | + | author | 02V | + | identifier | 02V.123456789 | + When consumer 'RX898' searches for DocumentReferences with parameters: + | parameter | value | + | subject | 9278693472 | + Then the response status code is 200 + And the response is a searchset Bundle + And the Bundle has a self link matching 'DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|9278693472' + And the Bundle has a total of 1 + And the Bundle has 1 entry + And the Bundle contains an DocumentReference with values + | property | value | + | id | 02V-1111111111-SearchDocRefTest | + | subject | 9278693472 | + | status | current | + | type | 736253002 | + | category | 734163000 | + | contentType | application/pdf | + | url | https://example.org/my-doc.pdf | + | custodian | 02V | + | author | 02V | + | identifier | 02V.123456789 | + Scenario: Search for a DocumentReference by NHS Number and Custodian where both search parameters match Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API And the organisation 'RX898' is authorised to access pointer types: diff --git a/tests/features/consumer/searchPostDocumentReference-failure.feature b/tests/features/consumer/searchPostDocumentReference-failure.feature index 91380c764..c798af6ec 100644 --- a/tests/features/consumer/searchPostDocumentReference-failure.feature +++ b/tests/features/consumer/searchPostDocumentReference-failure.feature @@ -77,7 +77,35 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios "display": "Invalid code system" }] }, - "diagnostics": "Invalid type (The provided type system does not match the allowed types for this organisation)", + "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", + "expression": ["type"] + } + """ + + Scenario: Search rejects request with type they are not allowed to use + Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API + And the organisation 'RX898' is authorised to access pointer types: + | system | value | + | http://snomed.info/sct | 736253002 | + When consumer 'RX898' searches for DocumentReferences using POST with request body: + | key | value | + | subject | 9278693472 | + | type | http://snomed.info/sct\|887701000000100 | + Then the response status code is 400 + And the response is an OperationOutcome with 1 issue + And the OperationOutcome contains the issue: + """ + { + "severity": "error", + "code": "code-invalid", + "details": { + "coding": [{ + "system": "https://fhir.nhs.uk/ValueSet/Spine-ErrorOrWarningCode-1", + "code": "INVALID_CODE_SYSTEM", + "display": "Invalid code system" + }] + }, + "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", "expression": ["type"] } """ diff --git a/tests/features/steps/3_assert.py b/tests/features/steps/3_assert.py index 1ce9c82f8..445f2268d 100644 --- a/tests/features/steps/3_assert.py +++ b/tests/features/steps/3_assert.py @@ -218,6 +218,14 @@ def assert_document_reference_matches_value( context.response.json(), ) + if identifier := items.get("identifier"): + assert doc_ref.identifier[0].value == identifier, format_error( + "DocumentReference Identifier does not match", + identifier, + doc_ref.identifier[0].value, + context.response.json(), + ) + @then("the Bundle contains an DocumentReference with values") def assert_bundle_contains_documentreference_values_step(context: Context): diff --git a/tests/features/utils/data.py b/tests/features/utils/data.py index 5bc300585..f6a672eb0 100644 --- a/tests/features/utils/data.py +++ b/tests/features/utils/data.py @@ -128,6 +128,12 @@ def create_test_document_reference(items: dict) -> DocumentReference: ), ) ] + if items.get("identifier"): + base_doc_ref.identifier = [ + Identifier( + type=CodeableConcept(text="Accession-Number"), value=items["identifier"] + ) + ] return base_doc_ref From 4abb3e3724ccce686c68812c02021eb52615f301 Mon Sep 17 00:00:00 2001 From: eesa456 Date: Fri, 13 Dec 2024 07:16:42 +0000 Subject: [PATCH 2/4] NRL-1076 fix tests --- .../tests/test_search_document_reference_consumer.py | 8 +++++++- .../tests/test_search_post_document_reference_consumer.py | 2 +- .../tests/test_search_document_reference_producer.py | 2 +- .../tests/test_search_post_document_reference_producer.py | 2 +- layer/nrlf/core/validators.py | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py b/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py index 0453eea2c..88d1757c8 100644 --- a/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py +++ b/api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py @@ -92,6 +92,12 @@ def test_search_document_reference_accession_number_in_pointer( "resourceType": "Bundle", "type": "searchset", "total": 1, + "link": [ + { + "relation": "self", + "url": "https://pytest.api.service.nhs.uk/record-locator/consumer/FHIR/R4/DocumentReference?subject:identifier=https://fhir.nhs.uk/Id/nhs-number|6700028191", + } + ], "entry": [{"resource": doc_ref.model_dump(exclude_none=True)}], } @@ -495,7 +501,7 @@ def test_search_document_reference_invalid_type(repository: DocumentPointerRepos } ] }, - "diagnostics": "Invalid query parameter (The provided type system does not match the allowed types for this organisation)", + "diagnostics": "Invalid query parameter (The provided type does not match the allowed types for this organisation)", "expression": ["type"], } ], diff --git a/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py b/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py index 4e3ed4e4d..3e50b535b 100644 --- a/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py +++ b/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py @@ -424,7 +424,7 @@ def test_search_post_document_reference_invalid_type( } ] }, - "diagnostics": "Invalid type (The provided type system does not match the allowed types for this organisation)", + "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", "expression": ["type"], } ], diff --git a/api/producer/searchDocumentReference/tests/test_search_document_reference_producer.py b/api/producer/searchDocumentReference/tests/test_search_document_reference_producer.py index d7a46ece7..b577f7754 100644 --- a/api/producer/searchDocumentReference/tests/test_search_document_reference_producer.py +++ b/api/producer/searchDocumentReference/tests/test_search_document_reference_producer.py @@ -201,7 +201,7 @@ def test_search_document_reference_invalid_type(repository: DocumentPointerRepos } ] }, - "diagnostics": "Invalid query parameter (The provided type system does not match the allowed types for this organisation)", + "diagnostics": "Invalid query parameter (The provided type does not match the allowed types for this organisation)", "expression": ["type"], } ], diff --git a/api/producer/searchPostDocumentReference/tests/test_search_post_document_reference_producer.py b/api/producer/searchPostDocumentReference/tests/test_search_post_document_reference_producer.py index f17de3fb1..8340ee0d3 100644 --- a/api/producer/searchPostDocumentReference/tests/test_search_post_document_reference_producer.py +++ b/api/producer/searchPostDocumentReference/tests/test_search_post_document_reference_producer.py @@ -206,7 +206,7 @@ def test_search_document_reference_invalid_type(repository: DocumentPointerRepos } ] }, - "diagnostics": "The provided type system does not match the allowed types for this organisation", + "diagnostics": "The provided type does not match the allowed types for this organisation", "expression": ["type"], } ], diff --git a/layer/nrlf/core/validators.py b/layer/nrlf/core/validators.py index bef650299..f75edb41f 100644 --- a/layer/nrlf/core/validators.py +++ b/layer/nrlf/core/validators.py @@ -26,7 +26,7 @@ def validate_type(type_: Optional[RequestQueryType], pointer_types: List[str]) -> bool: """ - Validates if the given type system is present in the list of pointer types. + Validates if the given type is present in the list of pointer types. """ if not type_: return True From 1754771ae617e936e67824a6bd239b4487ce4e9b Mon Sep 17 00:00:00 2001 From: eesa456 Date: Fri, 13 Dec 2024 09:47:08 +0000 Subject: [PATCH 3/4] NRL-1202 standardise message --- .../search_post_document_reference.py | 2 +- .../tests/test_search_post_document_reference_consumer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/consumer/searchPostDocumentReference/search_post_document_reference.py b/api/consumer/searchPostDocumentReference/search_post_document_reference.py index 5ea555cf0..6cb9b7e8c 100644 --- a/api/consumer/searchPostDocumentReference/search_post_document_reference.py +++ b/api/consumer/searchPostDocumentReference/search_post_document_reference.py @@ -57,7 +57,7 @@ def handler( pointer_types=metadata.pointer_types, ) return SpineErrorResponse.INVALID_CODE_SYSTEM( - diagnostics="Invalid type (The provided type does not match the allowed types for this organisation)", + diagnostics="The provided type does not match the allowed types for this organisation", expression="type", ) diff --git a/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py b/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py index 3e50b535b..6616ec51c 100644 --- a/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py +++ b/api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py @@ -424,7 +424,7 @@ def test_search_post_document_reference_invalid_type( } ] }, - "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", + "diagnostics": "The provided type does not match the allowed types for this organisation", "expression": ["type"], } ], From 123f8379b53a5c5f1384e92dd60164f470df3cff Mon Sep 17 00:00:00 2001 From: eesa456 Date: Fri, 13 Dec 2024 10:42:16 +0000 Subject: [PATCH 4/4] NRL-1202 fix int tests --- .../consumer/searchPostDocumentReference-failure.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/features/consumer/searchPostDocumentReference-failure.feature b/tests/features/consumer/searchPostDocumentReference-failure.feature index c798af6ec..3c76f708a 100644 --- a/tests/features/consumer/searchPostDocumentReference-failure.feature +++ b/tests/features/consumer/searchPostDocumentReference-failure.feature @@ -77,7 +77,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios "display": "Invalid code system" }] }, - "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", + "diagnostics": "The provided type does not match the allowed types for this organisation", "expression": ["type"] } """ @@ -105,7 +105,7 @@ Feature: Consumer - searchDocumentReference - Failure Scenarios "display": "Invalid code system" }] }, - "diagnostics": "Invalid type (The provided type does not match the allowed types for this organisation)", + "diagnostics": "The provided type does not match the allowed types for this organisation", "expression": ["type"] } """