From cdae3501aa264cd8a99a95eb2e680c9d9adab7a1 Mon Sep 17 00:00:00 2001 From: Megan Date: Fri, 21 Nov 2025 16:40:57 +0000 Subject: [PATCH 01/21] [NDR-293] Use EICAR file in virus test --- .../api/fhir/test_upload_document_fhir_api.py | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py index e80f92f33..251212084 100644 --- a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py +++ b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py @@ -91,10 +91,7 @@ def test_create_document_presign_fails(): def test_create_document_virus(test_data): - record = { - "ods": "H81109", - "nhs_number": "9730154260", - } + record = {"ods": "H81109", "nhs_number": "9730154260"} payload = pdm_data_helper.create_upload_payload(record) raw_upload_response = upload_document(payload) @@ -102,25 +99,37 @@ def test_create_document_virus(test_data): record["id"] = raw_upload_response.json()["id"].split("~")[1] test_data.append(record) - # Presigned upload upload_response = raw_upload_response.json() presign_uri = upload_response["content"][0]["attachment"]["url"] del upload_response["content"][0]["attachment"]["url"] - sample_pdf_path = os.path.join(os.path.dirname(__file__), "files", "dummy.pdf") - with open(sample_pdf_path, "rb") as f: - presign_response = requests.put(presign_uri, files={"file": f}) - assert presign_response.status_code == 200 - - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" - - raw_retrieve_response = retrieve_document_with_retry( - upload_response["id"], condition - ) - retrieve_response = raw_retrieve_response.json() - assert retrieve_response["docStatus"] == "cancelled" + try: + # Create EICAR file + eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") + eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" + with open(eicar_path, "wb") as f: + f.write(base64.b64decode(eicar_base64)) + + # Upload EICAR file to presigned URL + with open(eicar_path, "rb") as f: + presign_response = requests.put(presign_uri, files={"file": f}) + assert presign_response.status_code == 200 + + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus", False) == "cancelled" + + raw_retrieve_response = retrieve_document_with_retry( + upload_response["id"], condition + ) + retrieve_response = raw_retrieve_response.json() + + assert retrieve_response["docStatus"] == "cancelled" + + finally: + # Delete the EICAR file + if os.path.exists(eicar_path): + os.remove(eicar_path) @pytest.mark.parametrize( From 3791fc4b71f785a4a4c759f873f7ab775b71c0d8 Mon Sep 17 00:00:00 2001 From: Megan Date: Fri, 28 Nov 2025 16:23:52 +0000 Subject: [PATCH 02/21] [NDR-293] Add Eicar to LG E2E test --- .../tests/e2e/api/test_upload_document_api.py | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/lambdas/tests/e2e/api/test_upload_document_api.py b/lambdas/tests/e2e/api/test_upload_document_api.py index a6b2f545e..74ab9ac58 100644 --- a/lambdas/tests/e2e/api/test_upload_document_api.py +++ b/lambdas/tests/e2e/api/test_upload_document_api.py @@ -175,25 +175,36 @@ def test_create_document_virus(test_data, snapshot_json): presign_uri = upload_response["content"][0]["attachment"]["url"] del upload_response["content"][0]["attachment"]["url"] - sample_pdf_path = os.path.join(os.path.dirname(__file__), "files", "dummy.pdf") - with open(sample_pdf_path, "rb") as f: - files = {"file": f} - presign_response = requests.put(presign_uri, files=files) - assert presign_response.status_code == 200 + try: + # Create EICAR file + eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") + eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" + with open(eicar_path, "wb") as f: + f.write(base64.b64decode(eicar_base64)) + + # Upload EICAR file to presigned URL + with open(eicar_path, "rb") as f: + presign_response = requests.put(presign_uri, files={"file": f}) + assert presign_response.status_code == 200 + + retrieve_url = ( + f"https://{API_ENDPOINT}/FhirDocumentReference/{upload_response['id']}" + ) - retrieve_url = ( - f"https://{API_ENDPOINT}/FhirDocumentReference/{upload_response['id']}" - ) + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus", False) == "cancelled" - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" + raw_retrieve_response = fetch_with_retry(retrieve_url, condition) + retrieve_response = raw_retrieve_response.json() - raw_retrieve_response = fetch_with_retry(retrieve_url, condition) - retrieve_response = raw_retrieve_response.json() + assert upload_response == snapshot_json(exclude=paths("id", "date")) + assert retrieve_response == snapshot_json(exclude=paths("id", "date")) - assert upload_response == snapshot_json(exclude=paths("id", "date")) - assert retrieve_response == snapshot_json(exclude=paths("id", "date")) + finally: + # Delete the EICAR file + if os.path.exists(eicar_path): + os.remove(eicar_path) def test_create_document_does_not_save_raw(test_data): From 5c24a1e32eaef7203d3d6a5fbb11fc984ee26c9c Mon Sep 17 00:00:00 2001 From: Megan Date: Fri, 28 Nov 2025 16:30:43 +0000 Subject: [PATCH 03/21] [NDR-293] Temp workflow change to test pre-prod run --- .github/workflows/ndr-e2e-test-sandbox.yml | 42 +++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ndr-e2e-test-sandbox.yml b/.github/workflows/ndr-e2e-test-sandbox.yml index 65e66df54..c8732dc17 100644 --- a/.github/workflows/ndr-e2e-test-sandbox.yml +++ b/.github/workflows/ndr-e2e-test-sandbox.yml @@ -24,20 +24,30 @@ permissions: contents: read jobs: - services-e2etest: - uses: ./.github/workflows/base-e2e-backendtest.yml - with: - build_branch: ${{ inputs.build_branch }} - environment: ${{ inputs.environment }} - sandbox: ${{ inputs.sandbox }} - secrets: - AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} + pre-prod-check: + runs-on: ubuntu-latest + steps: + - name: Print selected environment + run: | + echo "✅ Workflow triggered manually" + echo "Branch: ${{ github.event.inputs.build_branch }}" + echo "Sandbox: ${{ github.event.inputs.sandbox }}" + echo "Environment: ${{ github.event.inputs.environment }}" + + # services-e2etest: + # uses: ./.github/workflows/base-e2e-backendtest.yml + # with: + # build_branch: ${{ inputs.build_branch }} + # environment: ${{ inputs.environment }} + # sandbox: ${{ inputs.sandbox }} + # secrets: + # AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} - services-fhir-api-e2etest: - uses: ./.github/workflows/base-e2e-fhir-backendtest.yml - with: - build_branch: ${{ inputs.build_branch }} - environment: ${{ inputs.environment }} - sandbox: ${{ inputs.sandbox }} - secrets: - AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} \ No newline at end of file + # services-fhir-api-e2etest: + # uses: ./.github/workflows/base-e2e-fhir-backendtest.yml + # with: + # build_branch: ${{ inputs.build_branch }} + # environment: ${{ inputs.environment }} + # sandbox: ${{ inputs.sandbox }} + # secrets: + # AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} \ No newline at end of file From f0bdb416f23e6c209f491f9663d8b0d87dcc7819 Mon Sep 17 00:00:00 2001 From: Megan Date: Thu, 4 Dec 2025 10:56:31 +0000 Subject: [PATCH 04/21] [NDR-293] Temp workflow change to run fhir backend tests on preprod --- .github/workflows/ndr-e2e-test-sandbox.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ndr-e2e-test-sandbox.yml b/.github/workflows/ndr-e2e-test-sandbox.yml index c8732dc17..7a188ac63 100644 --- a/.github/workflows/ndr-e2e-test-sandbox.yml +++ b/.github/workflows/ndr-e2e-test-sandbox.yml @@ -43,11 +43,11 @@ jobs: # secrets: # AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} - # services-fhir-api-e2etest: - # uses: ./.github/workflows/base-e2e-fhir-backendtest.yml - # with: - # build_branch: ${{ inputs.build_branch }} - # environment: ${{ inputs.environment }} - # sandbox: ${{ inputs.sandbox }} - # secrets: - # AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} \ No newline at end of file + services-fhir-api-e2etest: + uses: ./.github/workflows/base-e2e-fhir-backendtest.yml + with: + build_branch: ${{ inputs.build_branch }} + environment: ${{ inputs.environment }} + sandbox: ${{ inputs.sandbox }} + secrets: + AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} \ No newline at end of file From 600e1cbf0d57c6a10956e574b1cdefe37728b164 Mon Sep 17 00:00:00 2001 From: Megan Date: Thu, 4 Dec 2025 14:38:14 +0000 Subject: [PATCH 05/21] [NDR-293] Revert EICAR virus for testing --- .../api/fhir/test_upload_document_fhir_api.py | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py index 251212084..e80f92f33 100644 --- a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py +++ b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py @@ -91,7 +91,10 @@ def test_create_document_presign_fails(): def test_create_document_virus(test_data): - record = {"ods": "H81109", "nhs_number": "9730154260"} + record = { + "ods": "H81109", + "nhs_number": "9730154260", + } payload = pdm_data_helper.create_upload_payload(record) raw_upload_response = upload_document(payload) @@ -99,37 +102,25 @@ def test_create_document_virus(test_data): record["id"] = raw_upload_response.json()["id"].split("~")[1] test_data.append(record) + # Presigned upload upload_response = raw_upload_response.json() presign_uri = upload_response["content"][0]["attachment"]["url"] del upload_response["content"][0]["attachment"]["url"] + sample_pdf_path = os.path.join(os.path.dirname(__file__), "files", "dummy.pdf") + with open(sample_pdf_path, "rb") as f: + presign_response = requests.put(presign_uri, files={"file": f}) + assert presign_response.status_code == 200 + + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus", False) == "cancelled" + + raw_retrieve_response = retrieve_document_with_retry( + upload_response["id"], condition + ) + retrieve_response = raw_retrieve_response.json() - try: - # Create EICAR file - eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") - eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" - with open(eicar_path, "wb") as f: - f.write(base64.b64decode(eicar_base64)) - - # Upload EICAR file to presigned URL - with open(eicar_path, "rb") as f: - presign_response = requests.put(presign_uri, files={"file": f}) - assert presign_response.status_code == 200 - - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" - - raw_retrieve_response = retrieve_document_with_retry( - upload_response["id"], condition - ) - retrieve_response = raw_retrieve_response.json() - - assert retrieve_response["docStatus"] == "cancelled" - - finally: - # Delete the EICAR file - if os.path.exists(eicar_path): - os.remove(eicar_path) + assert retrieve_response["docStatus"] == "cancelled" @pytest.mark.parametrize( From 01f79aec786f4f359e527529cc973240e1f69772 Mon Sep 17 00:00:00 2001 From: Megan Date: Mon, 8 Dec 2025 16:46:43 +0000 Subject: [PATCH 06/21] [NDR-293] Set apim endpoint for pre-prod --- lambdas/tests/e2e/conftest.py | 2 +- scripts/test/set-e2e-env-vars.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lambdas/tests/e2e/conftest.py b/lambdas/tests/e2e/conftest.py index d108e47ab..36ff464cb 100644 --- a/lambdas/tests/e2e/conftest.py +++ b/lambdas/tests/e2e/conftest.py @@ -15,7 +15,7 @@ LG_UNSTITCHED_TABLE = os.environ.get("LG_UNSTITCHED_TABLE") BULK_REPORT_TABLE = os.environ.get("BULK_REPORT_TABLE") LLOYD_GEORGE_S3_BUCKET = data_helper.s3_bucket -APIM_ENDPOINT = "internal-dev.api.service.nhs.uk" +APIM_ENDPOINT = os.environ.get("APIM_ENDPOINT") PDM_SNOMED = 717391000000106 MTLS_ENDPOINT = os.environ.get("MTLS_ENDPOINT") CLIENT_CERT_PATH = os.environ.get("CLIENT_CERT_PATH") diff --git a/scripts/test/set-e2e-env-vars.sh b/scripts/test/set-e2e-env-vars.sh index e4a99f757..a82957ab3 100644 --- a/scripts/test/set-e2e-env-vars.sh +++ b/scripts/test/set-e2e-env-vars.sh @@ -19,6 +19,9 @@ fi # Set environment variables export AWS_WORKSPACE="${WORKSPACE}" export MTLS_ENDPOINT="mtls.${WORKSPACE}.${DOMAIN}" +if "WORKSPACE = "pre-prod""; then + export APIM_ENDPOINT="int.api.service.nhs.uk" +fi # Ensure Client certificates in place if ! make download-api-certs WORKSPACE="${WORKSPACE}"; then From 99fc21725a628bf63c330f39d0cdf0dc23ae0a95 Mon Sep 17 00:00:00 2001 From: Megan Date: Mon, 8 Dec 2025 16:49:11 +0000 Subject: [PATCH 07/21] [NDR-293] Upload virus --- .../api/fhir/test_upload_document_fhir_api.py | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py index e80f92f33..cffb93e03 100644 --- a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py +++ b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py @@ -102,25 +102,37 @@ def test_create_document_virus(test_data): record["id"] = raw_upload_response.json()["id"].split("~")[1] test_data.append(record) - # Presigned upload upload_response = raw_upload_response.json() presign_uri = upload_response["content"][0]["attachment"]["url"] del upload_response["content"][0]["attachment"]["url"] - sample_pdf_path = os.path.join(os.path.dirname(__file__), "files", "dummy.pdf") - with open(sample_pdf_path, "rb") as f: - presign_response = requests.put(presign_uri, files={"file": f}) - assert presign_response.status_code == 200 - - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" - - raw_retrieve_response = retrieve_document_with_retry( - upload_response["id"], condition - ) - retrieve_response = raw_retrieve_response.json() - assert retrieve_response["docStatus"] == "cancelled" + try: + # Create EICAR file + eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") + eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" + with open(eicar_path, "wb") as f: + f.write(base64.b64decode(eicar_base64)) + + # Upload EICAR file to presigned URL + with open(eicar_path, "rb") as f: + presign_response = requests.put(presign_uri, files={"file": f}) + assert presign_response.status_code == 200 + + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus", False) == "cancelled" + + raw_retrieve_response = retrieve_document_with_retry( + upload_response["id"], condition + ) + retrieve_response = raw_retrieve_response.json() + + assert retrieve_response["docStatus"] == "cancelled" + + finally: + # Delete the EICAR file + if os.path.exists(eicar_path): + os.remove(eicar_path) @pytest.mark.parametrize( From 4f61f5cd1aa3278a47711b1bf112994da98852f7 Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 11:58:42 +0000 Subject: [PATCH 08/21] [NDR-293] Upload virus --- .../api/fhir/test_upload_document_fhir_api.py | 46 +++++++------------ scripts/test/run-e2e-fhir-api-tests.sh | 1 + scripts/test/set-e2e-env-vars.sh | 2 +- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py index cffb93e03..2cb901a84 100644 --- a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py +++ b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py @@ -95,44 +95,32 @@ def test_create_document_virus(test_data): "ods": "H81109", "nhs_number": "9730154260", } + + # Attach EICAR data + eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" + record["data"] = eicar_base64 payload = pdm_data_helper.create_upload_payload(record) raw_upload_response = upload_document(payload) assert raw_upload_response.status_code == 200 - record["id"] = raw_upload_response.json()["id"].split("~")[1] + upload_response = raw_upload_response.json() + record["id"] = upload_response["id"].split("~")[1] test_data.append(record) - upload_response = raw_upload_response.json() - presign_uri = upload_response["content"][0]["attachment"]["url"] - del upload_response["content"][0]["attachment"]["url"] - - try: - # Create EICAR file - eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") - eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" - with open(eicar_path, "wb") as f: - f.write(base64.b64decode(eicar_base64)) - - # Upload EICAR file to presigned URL - with open(eicar_path, "rb") as f: - presign_response = requests.put(presign_uri, files={"file": f}) - assert presign_response.status_code == 200 - - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" - - raw_retrieve_response = retrieve_document_with_retry( - upload_response["id"], condition + # Poll until processing/scan completes + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus") in ( + "cancelled", + "final", ) - retrieve_response = raw_retrieve_response.json() - assert retrieve_response["docStatus"] == "cancelled" + raw_retrieve_response = retrieve_document_with_retry( + upload_response["id"], condition + ) + retrieve_response = raw_retrieve_response.json() - finally: - # Delete the EICAR file - if os.path.exists(eicar_path): - os.remove(eicar_path) + assert retrieve_response["docStatus"] == "cancelled" @pytest.mark.parametrize( diff --git a/scripts/test/run-e2e-fhir-api-tests.sh b/scripts/test/run-e2e-fhir-api-tests.sh index 5c1ec4467..38bacb195 100755 --- a/scripts/test/run-e2e-fhir-api-tests.sh +++ b/scripts/test/run-e2e-fhir-api-tests.sh @@ -36,6 +36,7 @@ source ./scripts/test/set-e2e-env-vars.sh $WORKSPACE echo "Running FHIR api E2E tests on workspace $AWS_WORKSPACE with:" echo "MTLS_ENDPOINT=$MTLS_ENDPOINT" +echo "APIM_ENDPOINT=${APIM_ENDPOINT:-N/A}" echo "CLIENT_CERT_PATH=$CLIENT_CERT_PATH" echo "CLIENT_KEY_PATH=$CLIENT_KEY_PATH" echo "UNAUTHORISED_CLIENT_CERT_PATH=$UNAUTHORISED_CLIENT_CERT_PATH" diff --git a/scripts/test/set-e2e-env-vars.sh b/scripts/test/set-e2e-env-vars.sh index a82957ab3..248702258 100644 --- a/scripts/test/set-e2e-env-vars.sh +++ b/scripts/test/set-e2e-env-vars.sh @@ -19,7 +19,7 @@ fi # Set environment variables export AWS_WORKSPACE="${WORKSPACE}" export MTLS_ENDPOINT="mtls.${WORKSPACE}.${DOMAIN}" -if "WORKSPACE = "pre-prod""; then +if [[ "$WORKSPACE" = "pre-prod" ]]; then export APIM_ENDPOINT="int.api.service.nhs.uk" fi From 2bd316d7ea3ff2875b8a478c1d5b501f01f88e97 Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 15:02:33 +0000 Subject: [PATCH 09/21] [NDR-293] Use raw string --- lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py index 2cb901a84..0e70f675c 100644 --- a/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py +++ b/lambdas/tests/e2e/api/fhir/test_upload_document_fhir_api.py @@ -97,8 +97,8 @@ def test_create_document_virus(test_data): } # Attach EICAR data - eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" - record["data"] = eicar_base64 + eicar_string = r"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" + record["data"] = base64.b64encode(eicar_string.encode()).decode() payload = pdm_data_helper.create_upload_payload(record) raw_upload_response = upload_document(payload) From 20d9bc1792255de31c978a13f3c86a99442faf72 Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 15:54:36 +0000 Subject: [PATCH 10/21] [NDR-293] Update LG tests --- .../tests/e2e/api/test_upload_document_api.py | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/lambdas/tests/e2e/api/test_upload_document_api.py b/lambdas/tests/e2e/api/test_upload_document_api.py index 74ab9ac58..63ed74274 100644 --- a/lambdas/tests/e2e/api/test_upload_document_api.py +++ b/lambdas/tests/e2e/api/test_upload_document_api.py @@ -164,6 +164,10 @@ def test_create_document_virus(test_data, snapshot_json): lloyd_george_record["nhs_number"] = "9730154260" + # Attach EICAR data + eicar_string = r"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" + lloyd_george_record["data"] = base64.b64encode(eicar_string.encode()).decode() + payload = create_upload_payload(lloyd_george_record) url = f"https://{API_ENDPOINT}/FhirDocumentReference" headers = {"Authorization": "Bearer 123", "X-Api-Key": API_KEY} @@ -172,39 +176,25 @@ def test_create_document_virus(test_data, snapshot_json): upload_response = retrieve_response.json() lloyd_george_record["id"] = upload_response["id"].split("~")[1] test_data.append(lloyd_george_record) - presign_uri = upload_response["content"][0]["attachment"]["url"] - del upload_response["content"][0]["attachment"]["url"] - - try: - # Create EICAR file - eicar_path = os.path.join(os.path.dirname(__file__), "files", "eicar.com") - eicar_base64 = "WDVPIVAlQEFQWzRcUFpYNTRQXlkyQ0MpN30kRUlDQVItU1RBTkRBUkQtQU5USVZJUlUtVEVTVC1GSUxFISRIK0gq" - with open(eicar_path, "wb") as f: - f.write(base64.b64decode(eicar_base64)) - # Upload EICAR file to presigned URL - with open(eicar_path, "rb") as f: - presign_response = requests.put(presign_uri, files={"file": f}) - assert presign_response.status_code == 200 + retrieve_url = ( + f"https://{API_ENDPOINT}/FhirDocumentReference/{upload_response['id']}" + ) - retrieve_url = ( - f"https://{API_ENDPOINT}/FhirDocumentReference/{upload_response['id']}" + # Poll until processing/scan completes + def condition(response_json): + logging.info(response_json) + return response_json.get("docStatus") in ( + "cancelled", + "final", ) - def condition(response_json): - logging.info(response_json) - return response_json.get("docStatus", False) == "cancelled" - - raw_retrieve_response = fetch_with_retry(retrieve_url, condition) - retrieve_response = raw_retrieve_response.json() + raw_retrieve_response = fetch_with_retry(retrieve_url, condition) + retrieve_response = raw_retrieve_response.json() - assert upload_response == snapshot_json(exclude=paths("id", "date")) - assert retrieve_response == snapshot_json(exclude=paths("id", "date")) + assert upload_response == snapshot_json(exclude=paths("id", "date")) + assert retrieve_response == snapshot_json(exclude=paths("id", "date")) - finally: - # Delete the EICAR file - if os.path.exists(eicar_path): - os.remove(eicar_path) def test_create_document_does_not_save_raw(test_data): From 4cf1624b3256c98643a3fbf8a7587d7cb01a1c70 Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 16:06:04 +0000 Subject: [PATCH 11/21] [NDR-293] Update pre-prod env vars for LG tests --- .github/workflows/base-e2e-backendtest.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/base-e2e-backendtest.yml b/.github/workflows/base-e2e-backendtest.yml index b482216c7..dc1dc9527 100644 --- a/.github/workflows/base-e2e-backendtest.yml +++ b/.github/workflows/base-e2e-backendtest.yml @@ -80,6 +80,11 @@ jobs: API_URL="api-${SANDBOX}.access-request-fulfilment.patient-deductions.nhs.uk" echo "NDR_API_ENDPOINT=$API_URL" >> $GITHUB_ENV echo "AWS_WORKSPACE=$AWS_WORKSPACE" >> $GITHUB_ENV + + # Set APIM_ENDPOINT for pre-prod + if [[ "$SANDBOX" = "pre-prod" ]]; then + echo "APIM_ENDPOINT=int.api.service.nhs.uk" >> "$GITHUB_ENV" + fi env: SANDBOX: ${{ inputs.sandbox }} From c721711a689a2147109c3ebe861ca772aa98f83c Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 16:16:11 +0000 Subject: [PATCH 12/21] [NDR-293] Handle apim endpoint --- .github/workflows/base-e2e-backendtest.yml | 4 ++++ scripts/test/run-e2e-fhir-api-tests.sh | 2 +- scripts/test/set-e2e-env-vars.sh | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/base-e2e-backendtest.yml b/.github/workflows/base-e2e-backendtest.yml index dc1dc9527..cd05e1354 100644 --- a/.github/workflows/base-e2e-backendtest.yml +++ b/.github/workflows/base-e2e-backendtest.yml @@ -84,6 +84,10 @@ jobs: # Set APIM_ENDPOINT for pre-prod if [[ "$SANDBOX" = "pre-prod" ]]; then echo "APIM_ENDPOINT=int.api.service.nhs.uk" >> "$GITHUB_ENV" + elif [[ "$SANDBOX" == "ndr-test" ]]; then + echo "APIM_ENDPOINT=internal-qa.api.service.nhs.uk" >> "$GITHUB_ENV" + else + echo "APIM_ENDPOINT=internal-dev.api.service.nhs.uk" >> "$GITHUB_ENV" fi env: SANDBOX: ${{ inputs.sandbox }} diff --git a/scripts/test/run-e2e-fhir-api-tests.sh b/scripts/test/run-e2e-fhir-api-tests.sh index 38bacb195..7e87d25d4 100755 --- a/scripts/test/run-e2e-fhir-api-tests.sh +++ b/scripts/test/run-e2e-fhir-api-tests.sh @@ -36,7 +36,7 @@ source ./scripts/test/set-e2e-env-vars.sh $WORKSPACE echo "Running FHIR api E2E tests on workspace $AWS_WORKSPACE with:" echo "MTLS_ENDPOINT=$MTLS_ENDPOINT" -echo "APIM_ENDPOINT=${APIM_ENDPOINT:-N/A}" +echo "APIM_ENDPOINT=${APIM_ENDPOINT}" echo "CLIENT_CERT_PATH=$CLIENT_CERT_PATH" echo "CLIENT_KEY_PATH=$CLIENT_KEY_PATH" echo "UNAUTHORISED_CLIENT_CERT_PATH=$UNAUTHORISED_CLIENT_CERT_PATH" diff --git a/scripts/test/set-e2e-env-vars.sh b/scripts/test/set-e2e-env-vars.sh index 248702258..3e2bb2085 100644 --- a/scripts/test/set-e2e-env-vars.sh +++ b/scripts/test/set-e2e-env-vars.sh @@ -21,6 +21,10 @@ export AWS_WORKSPACE="${WORKSPACE}" export MTLS_ENDPOINT="mtls.${WORKSPACE}.${DOMAIN}" if [[ "$WORKSPACE" = "pre-prod" ]]; then export APIM_ENDPOINT="int.api.service.nhs.uk" +elif [[ "$WORKSPACE" = "ndr-test" ]]; then + export APIM_ENDPOINT="internal-qa.api.service.nhs.uk" +else + export APM_ENDPOINT="internal-dev.api.service.nhs.uk" fi # Ensure Client certificates in place From 15849e26c823fb44ccd1bd735b8914834c96367b Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 16:17:41 +0000 Subject: [PATCH 13/21] [NDR-293] Update comment --- .github/workflows/base-e2e-backendtest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/base-e2e-backendtest.yml b/.github/workflows/base-e2e-backendtest.yml index cd05e1354..0b1b1e101 100644 --- a/.github/workflows/base-e2e-backendtest.yml +++ b/.github/workflows/base-e2e-backendtest.yml @@ -81,7 +81,7 @@ jobs: echo "NDR_API_ENDPOINT=$API_URL" >> $GITHUB_ENV echo "AWS_WORKSPACE=$AWS_WORKSPACE" >> $GITHUB_ENV - # Set APIM_ENDPOINT for pre-prod + # Set APIM_ENDPOINT if [[ "$SANDBOX" = "pre-prod" ]]; then echo "APIM_ENDPOINT=int.api.service.nhs.uk" >> "$GITHUB_ENV" elif [[ "$SANDBOX" == "ndr-test" ]]; then From 3ff11311f26bf9865c4d65cc50a83ec41f59fb40 Mon Sep 17 00:00:00 2001 From: Megan Date: Tue, 9 Dec 2025 16:24:18 +0000 Subject: [PATCH 14/21] [NDR-293] Remove whitespace --- lambdas/tests/e2e/api/test_upload_document_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lambdas/tests/e2e/api/test_upload_document_api.py b/lambdas/tests/e2e/api/test_upload_document_api.py index 63ed74274..b2e2fa785 100644 --- a/lambdas/tests/e2e/api/test_upload_document_api.py +++ b/lambdas/tests/e2e/api/test_upload_document_api.py @@ -196,7 +196,6 @@ def condition(response_json): assert retrieve_response == snapshot_json(exclude=paths("id", "date")) - def test_create_document_does_not_save_raw(test_data): lloyd_george_record = {} lloyd_george_record["ods"] = "H81109" From eea16b4e4354740808b8ebe72796e9b9ba8dab26 Mon Sep 17 00:00:00 2001 From: Megan Date: Wed, 10 Dec 2025 09:21:27 +0000 Subject: [PATCH 15/21] [NDR-293] Reset workflow --- .github/workflows/ndr-e2e-test-sandbox.yml | 26 +++++++--------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ndr-e2e-test-sandbox.yml b/.github/workflows/ndr-e2e-test-sandbox.yml index 7a188ac63..7f05df261 100644 --- a/.github/workflows/ndr-e2e-test-sandbox.yml +++ b/.github/workflows/ndr-e2e-test-sandbox.yml @@ -24,25 +24,15 @@ permissions: contents: read jobs: - pre-prod-check: - runs-on: ubuntu-latest - steps: - - name: Print selected environment - run: | - echo "✅ Workflow triggered manually" - echo "Branch: ${{ github.event.inputs.build_branch }}" - echo "Sandbox: ${{ github.event.inputs.sandbox }}" - echo "Environment: ${{ github.event.inputs.environment }}" + services-e2etest: + uses: ./.github/workflows/base-e2e-backendtest.yml + with: + build_branch: ${{ inputs.build_branch }} + environment: ${{ inputs.environment }} + sandbox: ${{ inputs.sandbox }} + secrets: + AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} - # services-e2etest: - # uses: ./.github/workflows/base-e2e-backendtest.yml - # with: - # build_branch: ${{ inputs.build_branch }} - # environment: ${{ inputs.environment }} - # sandbox: ${{ inputs.sandbox }} - # secrets: - # AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} - services-fhir-api-e2etest: uses: ./.github/workflows/base-e2e-fhir-backendtest.yml with: From bef0a595246a8b3be42d10a1ec27ed68c563e19e Mon Sep 17 00:00:00 2001 From: Megan Date: Wed, 10 Dec 2025 09:22:49 +0000 Subject: [PATCH 16/21] [NDR-293] Remove whitespace --- .github/workflows/ndr-e2e-test-sandbox.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ndr-e2e-test-sandbox.yml b/.github/workflows/ndr-e2e-test-sandbox.yml index 7f05df261..8cfb95bed 100644 --- a/.github/workflows/ndr-e2e-test-sandbox.yml +++ b/.github/workflows/ndr-e2e-test-sandbox.yml @@ -32,7 +32,6 @@ jobs: sandbox: ${{ inputs.sandbox }} secrets: AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} - services-fhir-api-e2etest: uses: ./.github/workflows/base-e2e-fhir-backendtest.yml with: From 0cbefeab864fc712f923b5dfbf678f4dffcd5cc0 Mon Sep 17 00:00:00 2001 From: Megan Date: Wed, 10 Dec 2025 09:29:24 +0000 Subject: [PATCH 17/21] [NDR-293] Fix typo --- .github/workflows/ndr-e2e-test-sandbox.yml | 1 + scripts/test/set-e2e-env-vars.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ndr-e2e-test-sandbox.yml b/.github/workflows/ndr-e2e-test-sandbox.yml index 8cfb95bed..7f05df261 100644 --- a/.github/workflows/ndr-e2e-test-sandbox.yml +++ b/.github/workflows/ndr-e2e-test-sandbox.yml @@ -32,6 +32,7 @@ jobs: sandbox: ${{ inputs.sandbox }} secrets: AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }} + services-fhir-api-e2etest: uses: ./.github/workflows/base-e2e-fhir-backendtest.yml with: diff --git a/scripts/test/set-e2e-env-vars.sh b/scripts/test/set-e2e-env-vars.sh index 3e2bb2085..820d1ccdb 100644 --- a/scripts/test/set-e2e-env-vars.sh +++ b/scripts/test/set-e2e-env-vars.sh @@ -24,7 +24,7 @@ if [[ "$WORKSPACE" = "pre-prod" ]]; then elif [[ "$WORKSPACE" = "ndr-test" ]]; then export APIM_ENDPOINT="internal-qa.api.service.nhs.uk" else - export APM_ENDPOINT="internal-dev.api.service.nhs.uk" + export APIM_ENDPOINT="internal-dev.api.service.nhs.uk" fi # Ensure Client certificates in place From cd478458b4fbab77e5abf3834e17afd22562f6ae Mon Sep 17 00:00:00 2001 From: Megan Date: Wed, 10 Dec 2025 13:21:15 +0000 Subject: [PATCH 18/21] [NDR-293] Update test --- lambdas/tests/e2e/api/test_upload_document_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambdas/tests/e2e/api/test_upload_document_api.py b/lambdas/tests/e2e/api/test_upload_document_api.py index b2e2fa785..e2181977b 100644 --- a/lambdas/tests/e2e/api/test_upload_document_api.py +++ b/lambdas/tests/e2e/api/test_upload_document_api.py @@ -192,7 +192,7 @@ def condition(response_json): raw_retrieve_response = fetch_with_retry(retrieve_url, condition) retrieve_response = raw_retrieve_response.json() - assert upload_response == snapshot_json(exclude=paths("id", "date")) + assert upload_response == snapshot_json(exclude=paths("id", "date", "content.0.attachment.url")) assert retrieve_response == snapshot_json(exclude=paths("id", "date")) From 3573814ebb1547bfdc097577c322f5c549890550 Mon Sep 17 00:00:00 2001 From: Megan Date: Wed, 10 Dec 2025 15:33:40 +0000 Subject: [PATCH 19/21] [NDR-293] Update readme --- lambdas/tests/e2e/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lambdas/tests/e2e/README.md b/lambdas/tests/e2e/README.md index 4a9fc82cb..cf33e17cc 100644 --- a/lambdas/tests/e2e/README.md +++ b/lambdas/tests/e2e/README.md @@ -76,6 +76,7 @@ In order to execute the E2E tests without mTLS (i.e. `make test-api-e2e`) you wi | `NDR_API_ENDPOINT` | The URI string used to connect to the NDR API. | | `AWS_WORKSPACE` | The workspace that is being tested. | | `MOCK_CIS2_KEY` | The value of the Mock CIS2 Key. Found in Parameter Store: /auth/password/MOCK_KEY | +| `APIM_URL` | The value of the APIM url e.g. `internal-dev.api.service.nhs.uk` | After updating your shell config, reload it: From 29854a617c2bb8523c307defd8892cc8c3c683aa Mon Sep 17 00:00:00 2001 From: Megan Date: Thu, 11 Dec 2025 09:19:07 +0000 Subject: [PATCH 20/21] [NDR-293] Set apim url dynamically --- .github/workflows/base-e2e-backendtest.yml | 9 --------- lambdas/tests/e2e/conftest.py | 2 +- lambdas/tests/e2e/helpers/data_helper.py | 9 +++++++++ scripts/test/run-e2e-fhir-api-tests.sh | 1 - scripts/test/set-e2e-env-vars.sh | 7 ------- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/.github/workflows/base-e2e-backendtest.yml b/.github/workflows/base-e2e-backendtest.yml index 0b1b1e101..b482216c7 100644 --- a/.github/workflows/base-e2e-backendtest.yml +++ b/.github/workflows/base-e2e-backendtest.yml @@ -80,15 +80,6 @@ jobs: API_URL="api-${SANDBOX}.access-request-fulfilment.patient-deductions.nhs.uk" echo "NDR_API_ENDPOINT=$API_URL" >> $GITHUB_ENV echo "AWS_WORKSPACE=$AWS_WORKSPACE" >> $GITHUB_ENV - - # Set APIM_ENDPOINT - if [[ "$SANDBOX" = "pre-prod" ]]; then - echo "APIM_ENDPOINT=int.api.service.nhs.uk" >> "$GITHUB_ENV" - elif [[ "$SANDBOX" == "ndr-test" ]]; then - echo "APIM_ENDPOINT=internal-qa.api.service.nhs.uk" >> "$GITHUB_ENV" - else - echo "APIM_ENDPOINT=internal-dev.api.service.nhs.uk" >> "$GITHUB_ENV" - fi env: SANDBOX: ${{ inputs.sandbox }} diff --git a/lambdas/tests/e2e/conftest.py b/lambdas/tests/e2e/conftest.py index 36ff464cb..be0105915 100644 --- a/lambdas/tests/e2e/conftest.py +++ b/lambdas/tests/e2e/conftest.py @@ -15,7 +15,7 @@ LG_UNSTITCHED_TABLE = os.environ.get("LG_UNSTITCHED_TABLE") BULK_REPORT_TABLE = os.environ.get("BULK_REPORT_TABLE") LLOYD_GEORGE_S3_BUCKET = data_helper.s3_bucket -APIM_ENDPOINT = os.environ.get("APIM_ENDPOINT") +APIM_ENDPOINT = data_helper.apim_url PDM_SNOMED = 717391000000106 MTLS_ENDPOINT = os.environ.get("MTLS_ENDPOINT") CLIENT_CERT_PATH = os.environ.get("CLIENT_CERT_PATH") diff --git a/lambdas/tests/e2e/helpers/data_helper.py b/lambdas/tests/e2e/helpers/data_helper.py index 6f362ddd4..c64e1890c 100644 --- a/lambdas/tests/e2e/helpers/data_helper.py +++ b/lambdas/tests/e2e/helpers/data_helper.py @@ -24,6 +24,7 @@ def __init__( self.record_type = record_type self.dynamo_service = DynamoDBService() self.s3_service = S3Service() + self.apim_url = None self.build_env(table_name, bucket_name) @@ -33,6 +34,14 @@ def build_env(self, table_name, bucket_name): self.dynamo_table = f"{self.workspace}_{table_name}" self.s3_bucket = f"{self.workspace}-{bucket_name}" + apim_map = { + "pre-prod": "int.api.service.nhs.uk", + "ndr-test": "internal-qa.api.service.nhs.uk", + "ndr-dev": "internal-dev.api.service.nhs.uk", + } + self.apim_url = apim_map.get(str(self.workspace), "internal-dev.api.service.nhs.uk") + + def build_record( self, nhs_number="9912003071", data=None, doc_status=None, size=None ): diff --git a/scripts/test/run-e2e-fhir-api-tests.sh b/scripts/test/run-e2e-fhir-api-tests.sh index 7e87d25d4..5c1ec4467 100755 --- a/scripts/test/run-e2e-fhir-api-tests.sh +++ b/scripts/test/run-e2e-fhir-api-tests.sh @@ -36,7 +36,6 @@ source ./scripts/test/set-e2e-env-vars.sh $WORKSPACE echo "Running FHIR api E2E tests on workspace $AWS_WORKSPACE with:" echo "MTLS_ENDPOINT=$MTLS_ENDPOINT" -echo "APIM_ENDPOINT=${APIM_ENDPOINT}" echo "CLIENT_CERT_PATH=$CLIENT_CERT_PATH" echo "CLIENT_KEY_PATH=$CLIENT_KEY_PATH" echo "UNAUTHORISED_CLIENT_CERT_PATH=$UNAUTHORISED_CLIENT_CERT_PATH" diff --git a/scripts/test/set-e2e-env-vars.sh b/scripts/test/set-e2e-env-vars.sh index 820d1ccdb..e4a99f757 100644 --- a/scripts/test/set-e2e-env-vars.sh +++ b/scripts/test/set-e2e-env-vars.sh @@ -19,13 +19,6 @@ fi # Set environment variables export AWS_WORKSPACE="${WORKSPACE}" export MTLS_ENDPOINT="mtls.${WORKSPACE}.${DOMAIN}" -if [[ "$WORKSPACE" = "pre-prod" ]]; then - export APIM_ENDPOINT="int.api.service.nhs.uk" -elif [[ "$WORKSPACE" = "ndr-test" ]]; then - export APIM_ENDPOINT="internal-qa.api.service.nhs.uk" -else - export APIM_ENDPOINT="internal-dev.api.service.nhs.uk" -fi # Ensure Client certificates in place if ! make download-api-certs WORKSPACE="${WORKSPACE}"; then From 753ae6491d091a1dd628592064906f98a736ac83 Mon Sep 17 00:00:00 2001 From: Megan Date: Thu, 11 Dec 2025 09:20:38 +0000 Subject: [PATCH 21/21] [NDR-293] Remove readme addition --- lambdas/tests/e2e/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/lambdas/tests/e2e/README.md b/lambdas/tests/e2e/README.md index cf33e17cc..4a9fc82cb 100644 --- a/lambdas/tests/e2e/README.md +++ b/lambdas/tests/e2e/README.md @@ -76,7 +76,6 @@ In order to execute the E2E tests without mTLS (i.e. `make test-api-e2e`) you wi | `NDR_API_ENDPOINT` | The URI string used to connect to the NDR API. | | `AWS_WORKSPACE` | The workspace that is being tested. | | `MOCK_CIS2_KEY` | The value of the Mock CIS2 Key. Found in Parameter Store: /auth/password/MOCK_KEY | -| `APIM_URL` | The value of the APIM url e.g. `internal-dev.api.service.nhs.uk` | After updating your shell config, reload it: