diff --git a/.github/actions/acceptance-tests/action.yml b/.github/actions/acceptance-tests/action.yml index dcf3ddb29..0ac177dab 100644 --- a/.github/actions/acceptance-tests/action.yml +++ b/.github/actions/acceptance-tests/action.yml @@ -25,7 +25,7 @@ runs: steps: - name: Run component tests - if: ${{ inputs.testType != 'e2e' }} + if: ${{ inputs.testType == 'component' }} uses: ./.github/actions/acceptance-tests-component with: testType: ${{ inputs.testType }} @@ -33,7 +33,7 @@ runs: targetComponent: ${{ inputs.targetComponent }} - name: Run e2e tests - if: ${{ inputs.testType == 'e2e' && inputs.targetEnvironment == 'main' }} + if: ${{ inputs.testType == 'e2e' }} uses: ./.github/actions/acceptance-tests-e2e with: targetEnvironment: ${{ inputs.targetEnvironment }} diff --git a/.github/actions/build-proxies/action.yml b/.github/actions/build-proxies/action.yml index 728edf4bc..23c5005c3 100644 --- a/.github/actions/build-proxies/action.yml +++ b/.github/actions/build-proxies/action.yml @@ -118,4 +118,5 @@ runs: --apimEnvironment "${{ env.APIM_ENV }}" \ --boundedContext "notify-supplier" \ --targetDomain "$TARGET_DOMAIN" \ - --version "${{ inputs.version }}" + --version "${{ inputs.version }}" \ + --internalRef "feature/CCM-17012" # TO BE REMOVED - used to trigger workflow until internal branch merges diff --git a/.github/workflows/deploy-dynamic-env-proxy.yaml b/.github/workflows/deploy-dynamic-env-proxy.yaml index 5c4607ae0..7a4313ad1 100644 --- a/.github/workflows/deploy-dynamic-env-proxy.yaml +++ b/.github/workflows/deploy-dynamic-env-proxy.yaml @@ -1,3 +1,4 @@ +# Test name: Deploy dynamic PR environment proxy run-name: Deploy proxy for PR environment on internal-dev by @${{ github.actor }} diff --git a/Makefile b/Makefile index c7915eb31..a0368e2f0 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # the project as automated steps to be executed on locally and in the CD pipeline. include scripts/init.mk +-include .env # Load environment variables from .env file if it exists # ============================================================================== @@ -130,11 +131,14 @@ ${VERBOSE}.SILENT: \ # E2E Test commands # ##################### +# https://pytest-xdist.readthedocs.io/en/stable/known-limitations.html#output-stdout-and-stderr-from-workers means pytest won't print to stdout even with -s +PYTEST_WORKERS := 4 # set to 0 to see stdout/stderr when debugging e2e tests + TEST_CMD := APIGEE_ACCESS_TOKEN="$(APIGEE_ACCESS_TOKEN)" \ STATUS_ENDPOINT_API_KEY="$(STATUS_ENDPOINT_API_KEY)" \ PYTHONPATH=. poetry run pytest --disable-warnings -vv \ --color=yes \ - -n 4 \ + -n $(PYTEST_WORKERS) \ --api-name=nhs-notify-supplier \ --proxy-name="$(PROXY_NAME)" \ -s \ @@ -145,7 +149,6 @@ TEST_CMD := APIGEE_ACCESS_TOKEN="$(APIGEE_ACCESS_TOKEN)" \ --only-rerun 'AssertionError: Unexpected 502' \ --junitxml=test-report.xml - .internal-dev-test: @cd tests/e2e-tests && \ $(TEST_CMD) \ @@ -161,7 +164,7 @@ TEST_CMD := APIGEE_ACCESS_TOKEN="$(APIGEE_ACCESS_TOKEN)" \ PROD_CMD := APIGEE_ACCESS_TOKEN="$(APIGEE_ACCESS_TOKEN)" \ PYTHONPATH=. poetry run pytest --disable-warnings -vv \ --color=yes \ - -n 4 \ + -n $(PYTEST_WORKERS) \ --api-name=nhs-notify-supplier \ --proxy-name="$(PROXY_NAME)" \ -s \ diff --git a/package-lock.json b/package-lock.json index 6d9347d30..f3b0abe38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,12 @@ "tests", "tests/contracts/*" ], + "dependencies": { + "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.2", + "@nhsdigital/notify-digital-letters-consumer-contracts": "^1.0.1", + "@pact-foundation/pact": "^16.4.0", + "@pact-foundation/pact-core": "^19.2.0" + }, "devDependencies": { "@aws-sdk/client-api-gateway": "^3.906.0", "@aws-sdk/client-kinesis": "^3.939.0", @@ -259,6 +265,15 @@ "zod": "^4.1.11" } }, + "lambdas/supplier-allocator/node_modules/@nhsdigital/nhs-notify-event-schemas-letter-rendering": { + "version": "2.0.1", + "resolved": "https://npm.pkg.github.com/download/@nhsdigital/nhs-notify-event-schemas-letter-rendering/2.0.1/23a5011fb0addd3da400f798bb1e4340440d62a5", + "integrity": "sha512-U2AWQEBcTDSxA3RX29fdmwjaOPQvwrCQP5rVCgLgtlPGes4Wl695VLw7tDxgpyLY1p9ct3HHrx3Wc6k/QGeW7g==", + "license": "MIT", + "dependencies": { + "zod": "^4.0.17" + } + }, "lambdas/supplier-allocator/node_modules/pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -326,6 +341,15 @@ "zod": "^4.1.11" } }, + "lambdas/upsert-letter/node_modules/@nhsdigital/nhs-notify-event-schemas-letter-rendering": { + "version": "2.0.1", + "resolved": "https://npm.pkg.github.com/download/@nhsdigital/nhs-notify-event-schemas-letter-rendering/2.0.1/23a5011fb0addd3da400f798bb1e4340440d62a5", + "integrity": "sha512-U2AWQEBcTDSxA3RX29fdmwjaOPQvwrCQP5rVCgLgtlPGes4Wl695VLw7tDxgpyLY1p9ct3HHrx3Wc6k/QGeW7g==", + "license": "MIT", + "dependencies": { + "zod": "^4.0.17" + } + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "11.9.3", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", @@ -5131,9 +5155,9 @@ } }, "node_modules/@nhsdigital/nhs-notify-event-schemas-letter-rendering": { - "version": "2.0.1", - "resolved": "https://npm.pkg.github.com/download/@nhsdigital/nhs-notify-event-schemas-letter-rendering/2.0.1/23a5011fb0addd3da400f798bb1e4340440d62a5", - "integrity": "sha512-U2AWQEBcTDSxA3RX29fdmwjaOPQvwrCQP5rVCgLgtlPGes4Wl695VLw7tDxgpyLY1p9ct3HHrx3Wc6k/QGeW7g==", + "version": "2.0.2", + "resolved": "https://npm.pkg.github.com/download/@nhsdigital/nhs-notify-event-schemas-letter-rendering/2.0.2/a72687375c465d68104b52e58ec67ed59bd99447", + "integrity": "sha512-iSXx98XLFUdz7R4ffy+WoMPi2GEZdJOMA3WHgfR5w+VNPd4aN73oNfNMwqXLViNA6M9HC1JPmudZUueqJQ2KxQ==", "license": "MIT", "dependencies": { "zod": "^4.0.17" @@ -5612,12 +5636,12 @@ } }, "node_modules/@pact-foundation/pact": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact/-/pact-16.2.0.tgz", - "integrity": "sha512-PFedoP49sR9EKEvhREsXiDTb+rS3yv016DIlufey6pXC6ssQKhgq78ngZDRGl7mc6PqLJdOBCZUDPUrR890k2A==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact/-/pact-16.4.0.tgz", + "integrity": "sha512-nf+xA6cvWlIpwsJ8gDAw69lGRlkqbiU9Ui6ie+ALH8N6+12Ukj7idYod0Zl643FCsActBVWytr5j28dEG0rEQg==", "license": "MIT", "dependencies": { - "@pact-foundation/pact-core": "^18.1.0", + "@pact-foundation/pact-core": "^19.2.0", "axios": "^1.12.2", "body-parser": "^2.2.0", "chalk": "4.1.2", @@ -5638,9 +5662,9 @@ } }, "node_modules/@pact-foundation/pact-core": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core/-/pact-core-17.1.0.tgz", - "integrity": "sha512-0yAUBpLP9ggibw3uX8FW8gHj6zbxCiGNDh1K9oG9b6opzqD3ZsGD8YaKYOHOLTQSoQRsB//Kkeztvi4IfWO3iQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core/-/pact-core-19.2.0.tgz", + "integrity": "sha512-7EB2e850hmBzGnwOYTRj4TCFCJQa9zaOy53bK+ybzEDx801olf0gVlYqMYHt1EsHUZzmtS5uDybpr9UMcZQxgg==", "cpu": [ "x64", "ia32", @@ -5658,25 +5682,25 @@ "node-gyp-build": "^4.6.0", "pino": "^10.0.0", "pino-pretty": "^13.1.1", - "underscore": "1.13.7" + "underscore": "1.13.8" }, "engines": { "node": ">=20" }, "optionalDependencies": { - "@pact-foundation/pact-core-darwin-arm64": "17.1.0", - "@pact-foundation/pact-core-darwin-x64": "17.1.0", - "@pact-foundation/pact-core-linux-arm64-glibc": "17.1.0", - "@pact-foundation/pact-core-linux-arm64-musl": "17.1.0", - "@pact-foundation/pact-core-linux-x64-glibc": "17.1.0", - "@pact-foundation/pact-core-linux-x64-musl": "17.1.0", - "@pact-foundation/pact-core-windows-x64": "17.1.0" + "@pact-foundation/pact-core-darwin-arm64": "19.2.0", + "@pact-foundation/pact-core-darwin-x64": "19.2.0", + "@pact-foundation/pact-core-linux-arm64-glibc": "19.2.0", + "@pact-foundation/pact-core-linux-arm64-musl": "19.2.0", + "@pact-foundation/pact-core-linux-x64-glibc": "19.2.0", + "@pact-foundation/pact-core-linux-x64-musl": "19.2.0", + "@pact-foundation/pact-core-windows-x64": "19.2.0" } }, "node_modules/@pact-foundation/pact-core-darwin-arm64": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-arm64/-/pact-core-darwin-arm64-17.1.0.tgz", - "integrity": "sha512-S4+VgqpuG2/0V7JRdDA9HvdOh38h45mEGr0m5Dqdh23hOvhRQHF25f3ylBpem6of+LacNIqJ+eyBEm4k/0H8MQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-arm64/-/pact-core-darwin-arm64-19.2.0.tgz", + "integrity": "sha512-cQvvWfJKS7iMzkunzh/kdgmyVLhAxyr/BQ8fOnMco2M/1+GHR+sOXvhrR1tes+NAYd1xjE3fbg1K2Flno8aDBw==", "cpu": [ "arm64" ], @@ -5687,9 +5711,9 @@ ] }, "node_modules/@pact-foundation/pact-core-darwin-x64": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-x64/-/pact-core-darwin-x64-17.1.0.tgz", - "integrity": "sha512-Ex7kykXXq4kyu9NHxvKzwV6yItXZduTF+Ui4dR316xaw7hzTQ+WWnHs0fPFlYFroO/LbWCFBzO5zUUkdU1UknQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-x64/-/pact-core-darwin-x64-19.2.0.tgz", + "integrity": "sha512-UltPXDZ+h1r3JqgIpEBP16bQzB90otd1QbcoeM3XakF9khCrYhW4y9llSuaosyqPFYwCk+mLaZTl/4iitJJaow==", "cpu": [ "x64" ], @@ -5700,9 +5724,9 @@ ] }, "node_modules/@pact-foundation/pact-core-linux-arm64-glibc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-glibc/-/pact-core-linux-arm64-glibc-17.1.0.tgz", - "integrity": "sha512-bz34LVZz9DNJWUCwIkq71ZBkSSstjr4febDpnOy/JXPvxuDbVZ6OIy8L8vV24c6JJNTxC1E7z194yxz/zuGAKw==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-glibc/-/pact-core-linux-arm64-glibc-19.2.0.tgz", + "integrity": "sha512-amiv4COurH1FRa7DSH3ks4UPQCb5J3x4GKrArf8UsTOkNhVGFUWVl83LOELj9Gtk67GwJ96iF7/fQps8I/iFIA==", "cpu": [ "arm64" ], @@ -5713,9 +5737,9 @@ ] }, "node_modules/@pact-foundation/pact-core-linux-arm64-musl": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-musl/-/pact-core-linux-arm64-musl-17.1.0.tgz", - "integrity": "sha512-NE+1rEMhheBNo8UbUi2bUfjvLwhV9QkY+k/6M+VUvGMVoeNhTXAYBMqz13lWkCcMh4IUbjCaVm6GQrMnV6DV5g==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-musl/-/pact-core-linux-arm64-musl-19.2.0.tgz", + "integrity": "sha512-tGWF7dP72Ho1A1PApyUqUMRI/e+gfbPxfaXxwWMXNh8JLK2jQQnP4bWymGwHQ4vxL7wn8ayx8I5y6x1vk/2+rA==", "cpu": [ "arm64" ], @@ -5726,9 +5750,9 @@ ] }, "node_modules/@pact-foundation/pact-core-linux-x64-glibc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-glibc/-/pact-core-linux-x64-glibc-17.1.0.tgz", - "integrity": "sha512-FgTeIVV+/2fCZaKEQN7MCXTNuHzBAT0d8TBGwiQXt6AzxNG9WvqqxpJIzH0mzjVmot3Q+8K4pySiSin/n4Y5CA==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-glibc/-/pact-core-linux-x64-glibc-19.2.0.tgz", + "integrity": "sha512-/ZNuWKuFJSBRZH09t7FXqKLy5koCaMIZ4RdbockLYlNo8uWF2ALfRCllj+SbXPLK+T+lVnBrs5s94X2cu4Rc7A==", "cpu": [ "x64" ], @@ -5739,9 +5763,9 @@ ] }, "node_modules/@pact-foundation/pact-core-linux-x64-musl": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-musl/-/pact-core-linux-x64-musl-17.1.0.tgz", - "integrity": "sha512-2wB65MO1QxH6HvXSVjj8Ii6nRrvEh5Y2O5b7vy7xHAPCbXBR67A/mUw9cxTZLdomAZEaOZN/34p+KXAoTA9JHg==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-musl/-/pact-core-linux-x64-musl-19.2.0.tgz", + "integrity": "sha512-n0m39CzVkq8J2alir1redm0rAdUVQzkKJqYBQdRmhEIa+QeGjUrJq+gmakUysoJxfSY4UthnJ9jS8SoyiZ+k6A==", "cpu": [ "x64" ], @@ -5752,136 +5776,9 @@ ] }, "node_modules/@pact-foundation/pact-core-windows-x64": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-windows-x64/-/pact-core-windows-x64-17.1.0.tgz", - "integrity": "sha512-iKpoKzUkcMUcdc5AbwLJDGNTv64DC0hZEh1xlyysIw6dbQkCcmgAx0Sjw8j7nBH/VQNxrCOaaN54fHzYgVmL9g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core/-/pact-core-18.1.0.tgz", - "integrity": "sha512-QWdntTsTT32r3SOTDaKjB9QyEbbgfsshsY2X/OwBJaNq28jKYEw50t2lYrITN+SdhkgfkEZJ9Y0XNfxtOUDVnA==", - "cpu": [ - "x64", - "ia32", - "arm64" - ], - "license": "MIT", - "os": [ - "darwin", - "linux", - "win32" - ], - "dependencies": { - "check-types": "11.2.3", - "detect-libc": "^2.0.3", - "node-gyp-build": "^4.6.0", - "pino": "^10.0.0", - "pino-pretty": "^13.1.1", - "underscore": "1.13.7" - }, - "engines": { - "node": ">=20" - }, - "optionalDependencies": { - "@pact-foundation/pact-core-darwin-arm64": "18.1.0", - "@pact-foundation/pact-core-darwin-x64": "18.1.0", - "@pact-foundation/pact-core-linux-arm64-glibc": "18.1.0", - "@pact-foundation/pact-core-linux-arm64-musl": "18.1.0", - "@pact-foundation/pact-core-linux-x64-glibc": "18.1.0", - "@pact-foundation/pact-core-linux-x64-musl": "18.1.0", - "@pact-foundation/pact-core-windows-x64": "18.1.0" - } - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-darwin-arm64": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-arm64/-/pact-core-darwin-arm64-18.1.0.tgz", - "integrity": "sha512-j1GSx7zN011xOveWeBP8RJ77bryFSLHIhe1ZcepfhMiB6VoUjGq1BNQ9rbhO4FSF2HBUCddMAw2/Xa+scHQJvQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-darwin-x64": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-x64/-/pact-core-darwin-x64-18.1.0.tgz", - "integrity": "sha512-KV08M7WJm/uuXv2qES4s8oJw8uTgFjQXmHLq4tKGT8HkaYCuSoQAhWYafxBJ/sMHeZ1LoGfv4nJkUr8bNakCYg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-linux-arm64-glibc": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-glibc/-/pact-core-linux-arm64-glibc-18.1.0.tgz", - "integrity": "sha512-BeJqmtBR6IdOg2IU0Y+N1NsH1pzr5H3PeOJ+vTSgNiTnV/wYkKk6GZDT1dzwUVi+OjfarGbK86022EoHk/WpkQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-linux-arm64-musl": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-musl/-/pact-core-linux-arm64-musl-18.1.0.tgz", - "integrity": "sha512-twakwextRNwkAKntYnSBBAs3yugORGDZwgihVm9p+eYqded/agFTu2v4/E7xksLEotGoFlewnAvLSCTvyNf0uw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-linux-x64-glibc": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-glibc/-/pact-core-linux-x64-glibc-18.1.0.tgz", - "integrity": "sha512-rhR5iZS77Ie0ocJmtoTub82lyMQmjjn15UPhD5Tv1i2kYkbLCVPSYZpTrKak/OCDm5/AM0Lb7YqIZlOipMm/mA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-linux-x64-musl": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-musl/-/pact-core-linux-x64-musl-18.1.0.tgz", - "integrity": "sha512-u0N5uU3hwupGCkSmIiehR4yw5Foln+qqkUWXjtKdnttsj8Dz065K8osNGy18jmPRWr5XfRZurnnmw0+tFyaZPA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pact-foundation/pact/node_modules/@pact-foundation/pact-core-windows-x64": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-windows-x64/-/pact-core-windows-x64-18.1.0.tgz", - "integrity": "sha512-ST7XNlI78c2MCvWvqv7on9M+DmNGlrihiD3Uk5jwZIAWEXeXEVinpfnM/Z5qFik4m3UCDe/Zu/1aNNiY1RN3dQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-windows-x64/-/pact-core-windows-x64-19.2.0.tgz", + "integrity": "sha512-WZSDBL1Sn8y5+YJTK+HDiS/Fn9th1M4QJW2dflQ8UFwoaIh6yb0TrJjtuWbDGIwNeD4Sv8CJ5jJOf1nyNjFLfg==", "cpu": [ "x64" ], @@ -23278,9 +23175,9 @@ "@aws-sdk/client-lambda": "^3.986.0", "@aws-sdk/client-sns": "^3.984.0", "@aws-sdk/lib-dynamodb": "^3.1008.0", - "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.1", + "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.2", "@nhsdigital/notify-digital-letters-consumer-contracts": "^1.0.1", - "@pact-foundation/pact": "^16.0.4", + "@pact-foundation/pact": "^16.4.0", "@pact-foundation/pact-core": "^17.1.0", "@playwright/test": "^1.57.0", "allure-js-commons": "^3.3.3", @@ -23312,6 +23209,133 @@ "@pact-foundation/pact": "^16.0.4" } }, + "tests/node_modules/@pact-foundation/pact-core": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core/-/pact-core-17.1.0.tgz", + "integrity": "sha512-0yAUBpLP9ggibw3uX8FW8gHj6zbxCiGNDh1K9oG9b6opzqD3ZsGD8YaKYOHOLTQSoQRsB//Kkeztvi4IfWO3iQ==", + "cpu": [ + "x64", + "ia32", + "arm64" + ], + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32" + ], + "dependencies": { + "check-types": "11.2.3", + "detect-libc": "^2.0.3", + "node-gyp-build": "^4.6.0", + "pino": "^10.0.0", + "pino-pretty": "^13.1.1", + "underscore": "1.13.7" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "@pact-foundation/pact-core-darwin-arm64": "17.1.0", + "@pact-foundation/pact-core-darwin-x64": "17.1.0", + "@pact-foundation/pact-core-linux-arm64-glibc": "17.1.0", + "@pact-foundation/pact-core-linux-arm64-musl": "17.1.0", + "@pact-foundation/pact-core-linux-x64-glibc": "17.1.0", + "@pact-foundation/pact-core-linux-x64-musl": "17.1.0", + "@pact-foundation/pact-core-windows-x64": "17.1.0" + } + }, + "tests/node_modules/@pact-foundation/pact-core-darwin-arm64": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-arm64/-/pact-core-darwin-arm64-17.1.0.tgz", + "integrity": "sha512-S4+VgqpuG2/0V7JRdDA9HvdOh38h45mEGr0m5Dqdh23hOvhRQHF25f3ylBpem6of+LacNIqJ+eyBEm4k/0H8MQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-darwin-x64": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-darwin-x64/-/pact-core-darwin-x64-17.1.0.tgz", + "integrity": "sha512-Ex7kykXXq4kyu9NHxvKzwV6yItXZduTF+Ui4dR316xaw7hzTQ+WWnHs0fPFlYFroO/LbWCFBzO5zUUkdU1UknQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-linux-arm64-glibc": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-glibc/-/pact-core-linux-arm64-glibc-17.1.0.tgz", + "integrity": "sha512-bz34LVZz9DNJWUCwIkq71ZBkSSstjr4febDpnOy/JXPvxuDbVZ6OIy8L8vV24c6JJNTxC1E7z194yxz/zuGAKw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-linux-arm64-musl": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-arm64-musl/-/pact-core-linux-arm64-musl-17.1.0.tgz", + "integrity": "sha512-NE+1rEMhheBNo8UbUi2bUfjvLwhV9QkY+k/6M+VUvGMVoeNhTXAYBMqz13lWkCcMh4IUbjCaVm6GQrMnV6DV5g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-linux-x64-glibc": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-glibc/-/pact-core-linux-x64-glibc-17.1.0.tgz", + "integrity": "sha512-FgTeIVV+/2fCZaKEQN7MCXTNuHzBAT0d8TBGwiQXt6AzxNG9WvqqxpJIzH0mzjVmot3Q+8K4pySiSin/n4Y5CA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-linux-x64-musl": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-linux-x64-musl/-/pact-core-linux-x64-musl-17.1.0.tgz", + "integrity": "sha512-2wB65MO1QxH6HvXSVjj8Ii6nRrvEh5Y2O5b7vy7xHAPCbXBR67A/mUw9cxTZLdomAZEaOZN/34p+KXAoTA9JHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "tests/node_modules/@pact-foundation/pact-core-windows-x64": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pact-foundation/pact-core-windows-x64/-/pact-core-windows-x64-17.1.0.tgz", + "integrity": "sha512-iKpoKzUkcMUcdc5AbwLJDGNTv64DC0hZEh1xlyysIw6dbQkCcmgAx0Sjw8j7nBH/VQNxrCOaaN54fHzYgVmL9g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "tests/node_modules/dotenv": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", @@ -23323,6 +23347,12 @@ "funding": { "url": "https://dotenvx.com" } + }, + "tests/node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "license": "MIT" } } } diff --git a/package.json b/package.json index 747493a93..6f1faf765 100644 --- a/package.json +++ b/package.json @@ -135,5 +135,11 @@ "scripts/utilities/*", "tests", "tests/contracts/*" - ] + ], + "dependencies": { + "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.2", + "@nhsdigital/notify-digital-letters-consumer-contracts": "^1.0.1", + "@pact-foundation/pact": "^16.4.0", + "@pact-foundation/pact-core": "^19.2.0" + } } diff --git a/tests/component-tests/integration-tests/urgent-letter-priority.spec.ts b/tests/component-tests/integration-tests/urgent-letter-priority.spec.ts index 2a2f2858c..f4cb2c65c 100644 --- a/tests/component-tests/integration-tests/urgent-letter-priority.spec.ts +++ b/tests/component-tests/integration-tests/urgent-letter-priority.spec.ts @@ -1,7 +1,6 @@ import { expect, test } from "@playwright/test"; import getRestApiGatewayBaseUrl from "tests/helpers/aws-gateway-helper"; import { pollForLetterStatus } from "tests/helpers/poll-for-letters-helper"; -import { getLettersFromQueueViaIndex } from "tests/helpers/generate-fetch-test-data"; import { getVariantsWithUrgency, sendEventsForVariants, @@ -44,12 +43,6 @@ test.describe("Urgent Letter Priority Tests", () => { await verifyAllocationLogsContainPriority(urgencyNineLetterIds, 9); await verifyAllocationLogsContainPriority(urgencyTenLetterIds, 10); - const lettersFromQueue = await getLettersFromQueueViaIndex(supplier); - - const letterIdsFromQueue = lettersFromQueue.map( - (letter) => letter.letterId, - ); - const header = createValidRequestHeaders(supplier); const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { headers: header, @@ -63,10 +56,9 @@ test.describe("Urgent Letter Priority Tests", () => { GetLettersResponseSchema.parse(responseBody); const letterIds = getLettersResponse.data.map((letter) => letter.id); - expect(letterIds).toEqual(letterIdsFromQueue); verifyIndexPositionOfLetterVariants( - letterIdsFromQueue, + letterIds, urgencyTenLetterIds, urgencyNineLetterIds, ); diff --git a/tests/constants/api-constants.ts b/tests/constants/api-constants.ts index 608fb75d8..0afe02ca3 100644 --- a/tests/constants/api-constants.ts +++ b/tests/constants/api-constants.ts @@ -5,7 +5,7 @@ export const AWS_REGION = "eu-west-2"; export const envName = process.env.TARGET_ENVIRONMENT ?? "main"; export const API_NAME = `nhs-${envName}-supapi`; export const LETTERSTABLENAME = `nhs-${envName}-supapi-letters`; -export const SUPPLIERID = "TestSupplier1"; +export const SUPPLIERID = "supplier1"; export const MI_ENDPOINT = "mi"; export const SUPPLIERTABLENAME = `nhs-${envName}-supapi-suppliers`; export const UPSERT_LETTER_LAMBDA_ARN = `arn:aws:lambda:eu-west-2:820178564574:function:nhs-${envName}-supapi-upsertletter`; diff --git a/tests/e2e-tests/api/data/test_get_letter_data.py b/tests/e2e-tests/api/data/test_get_letter_data.py index 42bfc0bef..94b865079 100644 --- a/tests/e2e-tests/api/data/test_get_letter_data.py +++ b/tests/e2e-tests/api/data/test_get_letter_data.py @@ -11,28 +11,17 @@ @pytest.mark.devtest @pytest.mark.inttest @pytest.mark.prodtest -def test_200_get_letter_status(url, authentication_secret): +def test_200_get_letter_data(url, authentication_secret): headers = Generators.generate_valid_headers(authentication_secret) ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=1) - get_letter_data = requests.get(f"{url}/{LETTERS_ENDPOINT}/{ids[0]}/data", headers=headers) + print(f"calling GET {url}{LETTERS_ENDPOINT}/{ids[0]}/data with headers {headers}") + get_letter_data = requests.get(f"{url}{LETTERS_ENDPOINT}/{ids[0]}/data", headers=headers) ErrorHandler.handle_retry(get_letter_data) assert get_letter_data.status_code == 200, f"Response: {get_letter_data.status_code}: {get_letter_data.text}" assert get_letter_data.headers.get("Content-Type") == "application/pdf" -@pytest.mark.test -@pytest.mark.devtest -@pytest.mark.inttest -@pytest.mark.prodtest -def test_404_letter_does_not_exist(url, authentication_secret): - headers = Generators.generate_valid_headers(authentication_secret) - get_message_response = requests.get(f"{url}/{LETTERS_ENDPOINT}/xx", headers=headers) - - ErrorHandler.handle_retry(get_message_response) - assert get_message_response.status_code == 404 - assert get_message_response.json().get("errors")[0].get("detail") == "No resource found with that ID" - @pytest.mark.test @pytest.mark.devtest @pytest.mark.inttest @@ -40,7 +29,9 @@ def test_404_letter_does_not_exist(url, authentication_secret): def test_404_letter_does_not_exist(url, authentication_secret): letter_id = uuid.uuid4().hex headers = Generators.generate_valid_headers(authentication_secret) - get_message_response = requests.get(f"{url}/{LETTERS_ENDPOINT}/{letter_id}/data", headers=headers) + + print(f"calling GET {url}{LETTERS_ENDPOINT}/{letter_id}/data with headers {headers}") + get_message_response = requests.get(f"{url}{LETTERS_ENDPOINT}/{letter_id}/data", headers=headers) ErrorHandler.handle_retry(get_message_response) assert get_message_response.status_code == 404 diff --git a/tests/e2e-tests/api/headers/test_x_request_id.py b/tests/e2e-tests/api/headers/test_x_request_id.py index 827b8549d..7adaa7dcb 100644 --- a/tests/e2e-tests/api/headers/test_x_request_id.py +++ b/tests/e2e-tests/api/headers/test_x_request_id.py @@ -20,7 +20,7 @@ def test_header_letters_endpoint( ): auth_header = {"apikey": authentication_secret.value} if authentication_secret.auth_type == "apikey" \ else {"Authorization": authentication_secret.value} - resp = getattr(requests, method)(f"{url}/{endpoints}", headers={ + resp = getattr(requests, method)(f"{url}{endpoints}", headers={ **auth_header, "X-Request-ID": None }) @@ -38,7 +38,7 @@ def test_header_mi_endpoint( ): auth_header = {"apikey": authentication_secret.value} if authentication_secret.auth_type == "apikey" \ else {"Authorization": authentication_secret.value} - resp = getattr(requests, "post")(f"{url}/{MI_ENDPOINT}", headers={ + resp = getattr(requests, "post")(f"{url}{MI_ENDPOINT}", headers={ **auth_header, "X-Request-ID": "" }) diff --git a/tests/e2e-tests/api/letters/test_get_letter_status.py b/tests/e2e-tests/api/letters/test_get_letter_status.py index c55af8820..9cfa22175 100644 --- a/tests/e2e-tests/api/letters/test_get_letter_status.py +++ b/tests/e2e-tests/api/letters/test_get_letter_status.py @@ -16,19 +16,21 @@ def test_200_get_letter_status(url, authentication_secret): ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=1) letter_id = ids[0] - get_message_response = requests.get(f"{url}/{LETTERS_ENDPOINT}/{letter_id}", headers=headers) + print(f"calling GET {url}{LETTERS_ENDPOINT}/{letter_id} with headers {headers}") + get_message_response = requests.get(f"{url}{LETTERS_ENDPOINT}/{letter_id}", headers=headers) ErrorHandler.handle_retry(get_message_response) assert get_message_response.status_code == 200, f"Response: {get_message_response.status_code}: {get_message_response.text}" - @pytest.mark.test @pytest.mark.devtest @pytest.mark.inttest @pytest.mark.prodtest def test_404_letter_does_not_exist(url, authentication_secret): headers = Generators.generate_valid_headers(authentication_secret) - get_message_response = requests.get(f"{url}/{LETTERS_ENDPOINT}/xx", headers=headers) + + print(f"calling GET {url}{LETTERS_ENDPOINT}/xx with headers {headers}") + get_message_response = requests.get(f"{url}{LETTERS_ENDPOINT}/xx", headers=headers) ErrorHandler.handle_retry(get_message_response) assert get_message_response.status_code == 404, f"Response: {get_message_response.status_code}: {get_message_response.text}" diff --git a/tests/e2e-tests/api/letters/test_get_list_of_letters.py b/tests/e2e-tests/api/letters/test_get_list_of_letters.py index 275d255a6..1c67edb91 100644 --- a/tests/e2e-tests/api/letters/test_get_list_of_letters.py +++ b/tests/e2e-tests/api/letters/test_get_list_of_letters.py @@ -12,5 +12,6 @@ def test_200_get_letters(url, authentication_secret): headers = Generators.generate_valid_headers(authentication_secret) ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=1) + assert ids, "Expected at least one PENDING letter" assert len(ids) == 1 diff --git a/tests/e2e-tests/api/letters/test_multiple_letter_status.py b/tests/e2e-tests/api/letters/test_multiple_letter_status.py index 744fbb8d4..51fe72ddf 100644 --- a/tests/e2e-tests/api/letters/test_multiple_letter_status.py +++ b/tests/e2e-tests/api/letters/test_multiple_letter_status.py @@ -18,8 +18,9 @@ def test_202_with_valid_headers(url, authentication_secret): ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=2) data = Generators.generate_multiple_valid_request(ids) + print(f"calling POST {url}{LETTERS_ENDPOINT} with headers {headers} and body {data}") update_letter_status = requests.post( - f"{url}/{LETTERS_ENDPOINT}", + f"{url}{LETTERS_ENDPOINT}", headers=headers, json=data, ) @@ -37,8 +38,9 @@ def test_400_duplicates_in_request_body(url, authentication_secret): ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=2) data = Generators.generate_duplicate_request(ids) + print(f"calling POST {url}{LETTERS_ENDPOINT} with headers {headers} and body {data}") update_letter_status = requests.post( - f"{url}/{LETTERS_ENDPOINT}", + f"{url}{LETTERS_ENDPOINT}", headers=headers, json=data, ) @@ -57,8 +59,9 @@ def test_400_invalid_status_in_request_body(url, authentication_secret): ids = get_pending_letter_ids(url, headers, LETTERS_ENDPOINT, limit=3) data = Generators.generate_invalid_status_request(ids) + print(f"calling POST {url}{LETTERS_ENDPOINT} with headers {headers} and body {data}") update_letter_status = requests.post( - f"{url}/{LETTERS_ENDPOINT}", + f"{url}{LETTERS_ENDPOINT}", headers=headers, json=data, ) diff --git a/tests/e2e-tests/api/letters/test_update_letter_status.py b/tests/e2e-tests/api/letters/test_update_letter_status.py index 28a61c3ff..98200ec22 100644 --- a/tests/e2e-tests/api/letters/test_update_letter_status.py +++ b/tests/e2e-tests/api/letters/test_update_letter_status.py @@ -19,8 +19,10 @@ def test_202_with_valid_headers(url, authentication_secret): letter_id = ids[0] data = Generators.generate_valid_message_body("ACCEPTED", letter_id) + + print(f"calling PATCH {url}{LETTERS_ENDPOINT}/{letter_id} with headers {headers} and body {data}") update_letter_status = requests.patch( - f"{url}/{LETTERS_ENDPOINT}/{letter_id}", + f"{url}{LETTERS_ENDPOINT}/{letter_id}", headers=headers, json=data, ) @@ -35,8 +37,10 @@ def test_202_with_rejected_status(url, authentication_secret): letter_id = ids[0] data = Generators.generate_valid_message_rejected("REJECTED", letter_id) + + print(f"calling PATCH {url}{LETTERS_ENDPOINT}/{letter_id} with headers {headers} and body {data}") update_letter_status = requests.patch( - f"{url}/{LETTERS_ENDPOINT}/{letter_id}", + f"{url}{LETTERS_ENDPOINT}/{letter_id}", headers=headers, json=data, ) @@ -55,8 +59,10 @@ def test_400_with_invalid_status(url, authentication_secret): letter_id = ids[0] data = Generators.generate_valid_message_body("", letter_id) + + print(f"calling PATCH {url}{LETTERS_ENDPOINT}/{letter_id} with headers {headers} and body {data}") update_letter_status = requests.patch( - f"{url}/{LETTERS_ENDPOINT}/{letter_id}", + f"{url}{LETTERS_ENDPOINT}/{letter_id}", headers=headers, json=data, ) @@ -75,8 +81,10 @@ def test_400_id_mismatch_with_request(url, authentication_secret): letter_id = ids[0] data = Generators.generate_valid_message_body("ACCEPTED", "letter1") + + print(f"calling PATCH {url}{LETTERS_ENDPOINT}/{letter_id} with headers {headers} and body {data}") update_letter_status = requests.patch( - f"{url}/{LETTERS_ENDPOINT}/{letter_id}", + f"{url}{LETTERS_ENDPOINT}/{letter_id}", headers=headers, json=data, ) diff --git a/tests/e2e-tests/lib/letters.py b/tests/e2e-tests/lib/letters.py index cabd8f458..4a1774ecb 100644 --- a/tests/e2e-tests/lib/letters.py +++ b/tests/e2e-tests/lib/letters.py @@ -8,7 +8,7 @@ _REPO_ROOT = pathlib.Path(__file__).resolve().parents[3] _CLI_WORKSPACE = "nhs-notify-supplier-api-letter-test-data-utility" -_SUPPLIER_ID = "TestSupplier1" +_SUPPLIER_ID = "supplier1" # This should be the same id registered in the Apigee App to which the proxy will be associated def create_test_data(count: int = 10) -> None: @@ -68,17 +68,19 @@ def get_pending_letter_ids( deadline = time.monotonic() + timeout_s data = [] while time.monotonic() < deadline: + # Retrieves letters based on the supplier registered in the Apigee App response = requests.get( - f"{url}/{letters_endpoint}?limit={limit}", headers=headers + f"{url}{letters_endpoint}?limit={limit}", headers=headers ) ErrorHandler.handle_retry(response) response.raise_for_status() data.extend(response.json().get("data", [])) if len(data) >= limit: + print(f"Created and found letters with IDs {[item.get('id') for item in data]} for supplier registered in the Apigee App, to which the proxy is associated") return [item.get("id") for item in data] time.sleep(interval_s) raise TimeoutError( f"Timed out after {retries} retries waiting for {limit} PENDING letter(s) at " - f"{url}/{letters_endpoint}" + f"{url}{letters_endpoint}" ) diff --git a/tests/package.json b/tests/package.json index c096908da..fba34ec03 100644 --- a/tests/package.json +++ b/tests/package.json @@ -7,9 +7,9 @@ "@aws-sdk/client-lambda": "^3.986.0", "@aws-sdk/client-sns": "^3.984.0", "@aws-sdk/lib-dynamodb": "^3.1008.0", - "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.1", + "@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.2", "@nhsdigital/notify-digital-letters-consumer-contracts": "^1.0.1", - "@pact-foundation/pact": "^16.0.4", + "@pact-foundation/pact": "^16.4.0", "@pact-foundation/pact-core": "^17.1.0", "@playwright/test": "^1.57.0", "allure-js-commons": "^3.3.3", diff --git a/tests/pact-tests/consumer/letter-request-prepared.consumer.pact.test.ts b/tests/pact-tests/consumer/letter-request-prepared.consumer.pact.test.ts index b73de11f3..c4c2a51cf 100644 --- a/tests/pact-tests/consumer/letter-request-prepared.consumer.pact.test.ts +++ b/tests/pact-tests/consumer/letter-request-prepared.consumer.pact.test.ts @@ -37,7 +37,7 @@ describe("Pact Message Consumer - LetterRequestPrepared Event", () => { datacontenttype: "application/json", dataschema: MatchersV3.regex( /^https:\/\/notify\.nhs\.uk\/cloudevents\/schemas\/letter-rendering\/letter-request\.prepared\.2\.\d+\.\d+\.schema\.json$/, - "https://notify.nhs.uk/cloudevents/schemas/letter-rendering/letter-request.prepared.2.0.1.schema.json", + "https://notify.nhs.uk/cloudevents/schemas/letter-rendering/letter-request.prepared.2.0.2.schema.json", ), dataschemaversion: MatchersV3.regex(/\d+\.\d+\.\d+/, "2.0.0"), traceparent: MatchersV3.string( diff --git a/tests/pact-tests/provider/letter-request-prepared.provider.pact.test.ts b/tests/pact-tests/provider/letter-request-prepared.provider.pact.test.ts index 9fbf33842..d9c2d4b65 100644 --- a/tests/pact-tests/provider/letter-request-prepared.provider.pact.test.ts +++ b/tests/pact-tests/provider/letter-request-prepared.provider.pact.test.ts @@ -1,6 +1,6 @@ import path from "node:path"; import { MessageProviderPact } from "@pact-foundation/pact"; -import LetterRequestPreparedEvent from "@nhsdigital/nhs-notify-event-schemas-letter-rendering/examples/LetterRequestPrepared/v2.0.1.json"; +import LetterRequestPreparedEvent from "@nhsdigital/nhs-notify-event-schemas-letter-rendering/examples/LetterRequestPrepared/v2.0.2.json"; describe("Letter rendering message provider tests", () => { test("verify pacts", async () => {