From 3769590b1578a6ac02e2d4313d7789597355bba0 Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 11:12:57 +0000 Subject: [PATCH 01/15] letter data - auto fix --- .../utilities/letter-test-data/jest.config.ts | 34 +++++----- .../helpers/create_letter_helpers.test.ts | 5 +- .../letter-test-data/src/cli/index.ts | 64 +++++++++++-------- .../src/helpers/create_letter_helpers.ts | 28 ++++---- .../src/helpers/s3_helpers.ts | 18 ++++-- .../src/infrastructure/letter-repo-factory.ts | 13 ++-- 6 files changed, 87 insertions(+), 75 deletions(-) diff --git a/scripts/utilities/letter-test-data/jest.config.ts b/scripts/utilities/letter-test-data/jest.config.ts index cc9a39c9..445325b8 100644 --- a/scripts/utilities/letter-test-data/jest.config.ts +++ b/scripts/utilities/letter-test-data/jest.config.ts @@ -1,7 +1,7 @@ -import type { Config } from 'jest'; +import type { Config } from "jest"; export const baseJestConfig: Config = { - preset: 'ts-jest', + preset: "ts-jest", // Automatically clear mock calls, instances, contexts and results before every test clearMocks: true, @@ -10,10 +10,10 @@ export const baseJestConfig: Config = { collectCoverage: true, // The directory where Jest should output its coverage files - coverageDirectory: './.reports/unit/coverage', + coverageDirectory: "./.reports/unit/coverage", // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'babel', + coverageProvider: "babel", coverageThreshold: { global: { @@ -24,38 +24,38 @@ export const baseJestConfig: Config = { }, }, - coveragePathIgnorePatterns: ['/__tests__/'], - transform: { '^.+\\.ts$': 'ts-jest' }, - testPathIgnorePatterns: ['.build'], - testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + coveragePathIgnorePatterns: ["/__tests__/"], + transform: { "^.+\\.ts$": "ts-jest" }, + testPathIgnorePatterns: [".build"], + testMatch: ["**/?(*.)+(spec|test).[jt]s?(x)"], // Use this configuration option to add custom reporters to Jest reporters: [ - 'default', + "default", [ - 'jest-html-reporter', + "jest-html-reporter", { - pageTitle: 'Test Report', - outputPath: './.reports/unit/test-report.html', + pageTitle: "Test Report", + outputPath: "./.reports/unit/test-report.html", includeFailureMsg: true, }, ], ], // The test environment that will be used for testing - testEnvironment: 'jsdom', + testEnvironment: "jsdom", }; const utilsJestConfig = { ...baseJestConfig, - testEnvironment: 'node', + testEnvironment: "node", coveragePathIgnorePatterns: [ ...(baseJestConfig.coveragePathIgnorePatterns ?? []), - 'cli/index.ts', - 'helpers/s3_helpers.ts', - 'letter-repo-factory.ts', + "cli/index.ts", + "helpers/s3_helpers.ts", + "letter-repo-factory.ts", ], }; diff --git a/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts b/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts index a8b2a0db..bc3c4b73 100644 --- a/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts +++ b/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts @@ -1,6 +1,9 @@ import { LetterRepository } from "@internal/datastore/src/letter-repository"; import { LetterStatusType } from "@internal/datastore"; -import { createLetter, createLetterDto } from "../../helpers/create_letter_helpers"; +import { + createLetter, + createLetterDto, +} from "../../helpers/create_letter_helpers"; import { uploadFile } from "../../helpers/s3_helpers"; jest.mock("../../helpers/s3_helpers"); diff --git a/scripts/utilities/letter-test-data/src/cli/index.ts b/scripts/utilities/letter-test-data/src/cli/index.ts index 915c392b..fba64289 100644 --- a/scripts/utilities/letter-test-data/src/cli/index.ts +++ b/scripts/utilities/letter-test-data/src/cli/index.ts @@ -1,8 +1,11 @@ import { hideBin } from "yargs/helpers"; -import yargs from 'yargs'; +import yargs from "yargs"; import { LetterStatusType } from "@internal/datastore/src/types"; -import { randomUUID } from "crypto"; -import { createLetter, createLetterDto } from "../helpers/create_letter_helpers"; +import { randomUUID } from "node:crypto"; +import { + createLetter, + createLetterDto, +} from "../helpers/create_letter_helpers"; import { createLetterRepository } from "../infrastructure/letter-repo-factory"; import { uploadFile } from "../helpers/s3_helpers"; @@ -60,7 +63,7 @@ async function main() { }, }, async (argv) => { - const supplierId = argv.supplierId; + const { supplierId } = argv; const letterId = argv.letterId ? argv.letterId : randomUUID(); const bucketName = `nhs-${argv.awsAccountId}-eu-west-2-${argv.environment}-supapi-test-letters`; const targetFilename = `${letterId}.pdf`; @@ -68,9 +71,9 @@ async function main() { const specificationId = argv.specificationId ? argv.specificationId : randomUUID(); - const status = argv.status; - const environment = argv.environment; - const ttlHours = argv.ttlHours; + const { status } = argv; + const { environment } = argv; + const { ttlHours } = argv; const letterRepository = createLetterRepository(environment, ttlHours); createLetter({ @@ -114,7 +117,7 @@ async function main() { demandOption: false, default: 336, }, - "count": { + count: { type: "number", demandOption: true, }, @@ -137,41 +140,46 @@ async function main() { }, }, async (argv) => { - // set batch ID const batchId = randomUUID(); // parse args - const supplierId = argv.supplierId; + const { supplierId } = argv; const groupId = argv.groupId ? argv.groupId : randomUUID(); const specificationId = argv.specificationId ? argv.specificationId : randomUUID(); - const status = argv.status; - const environment = argv.environment; - const ttlHours = argv.ttlHours; + const { status } = argv; + const { environment } = argv; + const { ttlHours } = argv; const letterRepository = createLetterRepository(environment, ttlHours); - const count = argv.count; - + const { count } = argv; // Upload a test file for this batch const bucketName = `nhs-${argv.awsAccountId}-eu-west-2-${argv.environment}-supapi-test-letters`; const targetFilename = `${batchId}-${status}.pdf`; const url = `s3://${bucketName}/${batchId}/${targetFilename}`; - await uploadFile(bucketName, batchId, "../../test_letter.pdf", targetFilename); + await uploadFile( + bucketName, + batchId, + "../../test_letter.pdf", + targetFilename, + ); // Create letter DTOs - let letterDtos = []; + const letterDtos = []; for (let i = 0; i < count; i++) { - letterDtos.push(createLetterDto({ - letterId: randomUUID(), - supplierId, - groupId, - specificationId, - status: status as LetterStatusType, - url, - })); - }; + letterDtos.push( + createLetterDto({ + letterId: randomUUID(), + supplierId, + groupId, + specificationId, + status: status as LetterStatusType, + url, + }), + ); + } // Upload Letters await letterRepository.putLetterBatch(letterDtos); @@ -184,8 +192,8 @@ async function main() { } if (require.main === module) { - main().catch((err) => { - console.error(err); + main().catch((error) => { + console.error(error); process.exitCode = 1; }); } diff --git a/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts b/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts index 062154ec..c6137db7 100644 --- a/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts @@ -1,6 +1,6 @@ import { - LetterRepository, Letter, + LetterRepository, LetterStatusType, } from "@internal/datastore"; import { uploadFile } from "./s3_helpers"; @@ -16,14 +16,14 @@ export async function createLetter(params: { letterRepository: LetterRepository; }) { const { - letterId, bucketName, - supplierId, - targetFilename, - specificationId, groupId, - status, + letterId, letterRepository, + specificationId, + status, + supplierId, + targetFilename, } = params; await uploadFile( @@ -39,7 +39,7 @@ export async function createLetter(params: { specificationId, groupId, url: `s3://${bucketName}/${supplierId}/${targetFilename}`, - status: status, + status, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; @@ -56,22 +56,16 @@ export function createLetterDto(params: { status: LetterStatusType; url: string; }) { - const { - letterId, - supplierId, - specificationId, - groupId, - status, - url, - } = params; + const { groupId, letterId, specificationId, status, supplierId, url } = + params; const letter: Omit = { id: letterId, supplierId, specificationId, groupId, - url: url, - status: status, + url, + status, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; diff --git a/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts b/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts index 89ef72a4..0e5dde77 100644 --- a/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts @@ -1,9 +1,13 @@ -import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; -import { readFileSync } from "fs"; -import path from "path"; +import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; +import { readFileSync } from "node:fs"; +import path from "node:path"; - -export async function uploadFile(bucketName: string, supplierId: string, sourceFilename: string, targetFilename: string) { +export async function uploadFile( + bucketName: string, + supplierId: string, + sourceFilename: string, + targetFilename: string, +) { try { const s3 = new S3Client(); const filePath = path.join(__dirname, sourceFilename); @@ -18,7 +22,7 @@ export async function uploadFile(bucketName: string, supplierId: string, sourceF const command = new PutObjectCommand(uploadParams); return await s3.send(command); - } catch (err) { - console.error("Error uploading file:", err); + } catch (error) { + console.error("Error uploading file:", error); } } diff --git a/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts b/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts index e0060337..f2bef4a4 100644 --- a/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts +++ b/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts @@ -1,9 +1,12 @@ -import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; -import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; -import { pino } from 'pino'; -import { LetterRepository } from '@internal/datastore'; +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; +import { pino } from "pino"; +import { LetterRepository } from "@internal/datastore"; -export function createLetterRepository(environment: string, ttlHours:number): LetterRepository { +export function createLetterRepository( + environment: string, + ttlHours: number, +): LetterRepository { const ddbClient = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(ddbClient); const log = pino(); From 495d77e2a5284b85263328cb0bb5b5c92c8f6a15 Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 11:40:12 +0000 Subject: [PATCH 02/15] letter test data manual fixes --- package-lock.json | 938 ++++++++++++++---- .../utilities/letter-test-data/package.json | 2 + ....test.ts => create-letter-helpers.test.ts} | 4 +- .../letter-test-data/src/cli/index.ts | 18 +- ...er_helpers.ts => create-letter-helpers.ts} | 2 +- .../helpers/{s3_helpers.ts => s3-helpers.ts} | 3 +- .../src/infrastructure/letter-repo-factory.ts | 2 +- 7 files changed, 784 insertions(+), 185 deletions(-) rename scripts/utilities/letter-test-data/src/__test__/helpers/{create_letter_helpers.test.ts => create-letter-helpers.test.ts} (95%) rename scripts/utilities/letter-test-data/src/helpers/{create_letter_helpers.ts => create-letter-helpers.ts} (97%) rename scripts/utilities/letter-test-data/src/helpers/{s3_helpers.ts => s3-helpers.ts} (92%) diff --git a/package-lock.json b/package-lock.json index 45ac4684..e33ee81d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8502,12 +8502,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", - "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.6.tgz", + "integrity": "sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8540,16 +8540,16 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", - "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.4.tgz", + "integrity": "sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", "tslib": "^2.6.2" }, "engines": { @@ -8557,18 +8557,18 @@ } }, "node_modules/@smithy/core": { - "version": "3.18.7", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.7.tgz", - "integrity": "sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.19.0.tgz", + "integrity": "sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.2.6", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-stream": "^4.5.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-stream": "^4.5.7", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" @@ -8578,15 +8578,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", - "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.6.tgz", + "integrity": "sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", "tslib": "^2.6.2" }, "engines": { @@ -8664,14 +8664,14 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", - "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.7.tgz", + "integrity": "sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/querystring-builder": "^4.2.5", - "@smithy/types": "^4.9.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/querystring-builder": "^4.2.6", + "@smithy/types": "^4.10.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" }, @@ -8695,12 +8695,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", - "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.6.tgz", + "integrity": "sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -8724,12 +8724,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", - "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.6.tgz", + "integrity": "sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8763,13 +8763,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", - "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.6.tgz", + "integrity": "sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8777,18 +8777,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.3.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.14.tgz", - "integrity": "sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.0.tgz", + "integrity": "sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.18.7", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-middleware": "^4.2.5", + "@smithy/core": "^3.19.0", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-middleware": "^4.2.6", "tslib": "^2.6.2" }, "engines": { @@ -8796,18 +8796,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.14.tgz", - "integrity": "sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==", + "version": "4.4.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.16.tgz", + "integrity": "sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/service-error-classification": "^4.2.5", - "@smithy/smithy-client": "^4.9.10", - "@smithy/types": "^4.9.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-retry": "^4.2.5", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/service-error-classification": "^4.2.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" }, @@ -8816,13 +8816,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", - "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.7.tgz", + "integrity": "sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8830,12 +8830,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", - "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.6.tgz", + "integrity": "sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8843,14 +8843,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", - "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.6.tgz", + "integrity": "sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8858,15 +8858,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", - "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.6.tgz", + "integrity": "sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/querystring-builder": "^4.2.5", - "@smithy/types": "^4.9.0", + "@smithy/abort-controller": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/querystring-builder": "^4.2.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8874,12 +8874,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", - "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.6.tgz", + "integrity": "sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8887,12 +8887,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", - "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.6.tgz", + "integrity": "sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8900,12 +8900,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", - "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.6.tgz", + "integrity": "sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" }, @@ -8914,12 +8914,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", - "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.6.tgz", + "integrity": "sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8927,24 +8927,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", - "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.6.tgz", + "integrity": "sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0" + "@smithy/types": "^4.10.0" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", - "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.1.tgz", + "integrity": "sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -8952,16 +8952,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", - "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.6.tgz", + "integrity": "sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.5", + "@smithy/util-middleware": "^4.2.6", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -8971,17 +8971,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.9.10", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.10.tgz", - "integrity": "sha512-Jaoz4Jw1QYHc1EFww/E6gVtNjhoDU+gwRKqXP6C3LKYqqH2UQhP8tMP3+t/ePrhaze7fhLE8vS2q6vVxBANFTQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.1.tgz", + "integrity": "sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.18.7", - "@smithy/middleware-endpoint": "^4.3.14", - "@smithy/middleware-stack": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-stream": "^4.5.6", + "@smithy/core": "^3.19.0", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "@smithy/util-stream": "^4.5.7", "tslib": "^2.6.2" }, "engines": { @@ -8989,9 +8989,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", - "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.10.0.tgz", + "integrity": "sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -9001,13 +9001,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", - "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.6.tgz", + "integrity": "sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.2.5", - "@smithy/types": "^4.9.0", + "@smithy/querystring-parser": "^4.2.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9078,14 +9078,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.13", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.13.tgz", - "integrity": "sha512-hlVLdAGrVfyNei+pKIgqDTxfu/ZI2NSyqj4IDxKd5bIsIqwR/dSlkxlPaYxFiIaDVrBy0he8orsFy+Cz119XvA==", + "version": "4.3.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.15.tgz", + "integrity": "sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.5", - "@smithy/smithy-client": "^4.9.10", - "@smithy/types": "^4.9.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9093,17 +9093,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.16", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.16.tgz", - "integrity": "sha512-F1t22IUiJLHrxW9W1CQ6B9PN+skZ9cqSuzB18Eh06HrJPbjsyZ7ZHecAKw80DQtyGTRcVfeukKaCRYebFwclbg==", + "version": "4.2.18", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.18.tgz", + "integrity": "sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.4.3", - "@smithy/credential-provider-imds": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/smithy-client": "^4.9.10", - "@smithy/types": "^4.9.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9111,13 +9111,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", - "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.6.tgz", + "integrity": "sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9137,12 +9137,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", - "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.6.tgz", + "integrity": "sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9150,13 +9150,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", - "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.6.tgz", + "integrity": "sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.2.5", - "@smithy/types": "^4.9.0", + "@smithy/service-error-classification": "^4.2.6", + "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { @@ -9164,14 +9164,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", - "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.7.tgz", + "integrity": "sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/types": "^4.9.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/types": "^4.10.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", @@ -27140,7 +27140,9 @@ "name": "nhs-notify-supplier-api-letter-test-data-utility", "version": "0.0.1", "dependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0", "@aws-sdk/client-s3": "^3.858.0", + "@aws-sdk/lib-dynamodb": "^3.954.0", "@internal/datastore": "*", "esbuild": "^0.25.11", "pino": "^9.7.0", @@ -27154,6 +27156,604 @@ "typescript": "^5.9.3" } }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/client-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.954.0.tgz", + "integrity": "sha512-QhdiE3W9jC8wAmkjQhiwDBdpaK3/y/kc9aXfTyj8TaPP+B39zt56zA0VT4GtmXauyiYb81qcvKIjIDTvr95Y4A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-node": "3.954.0", + "@aws-sdk/dynamodb-codec": "3.954.0", + "@aws-sdk/middleware-endpoint-discovery": "3.953.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/client-sso": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.954.0.tgz", + "integrity": "sha512-FVyMAvlFhLK68DHWB1lSkCRTm25xl38bIZDd+jKt5+yDolCrG5+n9aIN8AA8jNO1HNGhZuMjSIQm9r5rGmJH8g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/core": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz", + "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@aws-sdk/xml-builder": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/signature-v4": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.954.0.tgz", + "integrity": "sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.954.0.tgz", + "integrity": "sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-stream": "^4.5.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.954.0.tgz", + "integrity": "sha512-WAFD8pVwRSoBsuXcoD+s/hrdsP9Z0PNUedSgkOGExuJVAabpM2cIIMzYNsdHio9XFZUSqHkv8mF5mQXuIZvuzg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-login": "3.954.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.954.0", + "@aws-sdk/credential-provider-web-identity": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.954.0.tgz", + "integrity": "sha512-UPBjw7Lnly5i+/rES8Z5U+nPaumzEUYOE/wrHkxyH6JjwFWn8w7R07fE5Z5cgYlIq1U1lQ7sxYwB3wHPpQ65Aw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-ini": "3.954.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.954.0", + "@aws-sdk/credential-provider-web-identity": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.954.0.tgz", + "integrity": "sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.954.0.tgz", + "integrity": "sha512-UXxGfkp/plFRdyidMLvNul5zoLKmHhVQOCrD2OgR/lg9jNqNmJ7abF+Qu8abo902iDkhU21Qj4M398cx6l8Kng==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.954.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/token-providers": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.954.0.tgz", + "integrity": "sha512-XEyf1T08q1tG4zkTS4Dnf1cAQyrJUo/xlvi6XNpqGhY3bOmKUYE2h/K6eITIdytDL9VuCpWYQ6YRcIVtL29E0w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/dynamodb-codec": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.954.0.tgz", + "integrity": "sha512-fNY0L1l9e36pLJef4NY5k7Q1SJnm5rgLSxSRPT8xL+bhQBtEn2E2t4JdBiTqlxgeyuOrafWOawbg8yS3pRPcLw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/endpoint-cache": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.953.0.tgz", + "integrity": "sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==", + "license": "Apache-2.0", + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.954.0.tgz", + "integrity": "sha512-DBEzAW7WfvNy6bQ32TfpvuFSVewj5eE8O1sTQWfvylNSZu81u6sPwb+eHPEclbvC84zAANl72JnkETOIkL4r8g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/util-dynamodb": "3.954.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.953.0.tgz", + "integrity": "sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/endpoint-cache": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz", + "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/middleware-logger": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz", + "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz", + "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz", + "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/nested-clients": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.954.0.tgz", + "integrity": "sha512-JLUhf35fTQIDPLk6G5KPggL9tV//Hjhy6+N2zZeis76LuBRNhKDq8z1CFyKhjf00vXi/tDYdn9D7y9emI+5Y/g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz", + "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/token-providers": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.954.0.tgz", + "integrity": "sha512-rDyN3oQQKMOJgyQ9/LNbh4fAGAj8ePMGOAQzSP/kyzizmViI6STpBW1o/VRqiTgMNi1bvA9ZasDtfrJqcVt0iA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/types": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz", + "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/util-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.954.0.tgz", + "integrity": "sha512-PXjS9P98OMMVXl4ledr/nTHGmNx6oF2rqTBvSQKKWi8dB4mcHjSaU5ASsklQC944xLs1IGsUkrJ39vu7bEqLoA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/util-endpoints": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz", + "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-endpoints": "^3.2.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz", + "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz", + "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws-sdk/xml-builder": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz", + "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.10.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", + "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/letter-test-data/node_modules/@smithy/util-waiter": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz", + "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "scripts/utilities/letter-test-data/node_modules/ansi-regex": { "version": "6.2.2", "license": "MIT", diff --git a/scripts/utilities/letter-test-data/package.json b/scripts/utilities/letter-test-data/package.json index a98c7161..45a7d644 100644 --- a/scripts/utilities/letter-test-data/package.json +++ b/scripts/utilities/letter-test-data/package.json @@ -1,6 +1,8 @@ { "dependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0", "@aws-sdk/client-s3": "^3.858.0", + "@aws-sdk/lib-dynamodb": "^3.954.0", "@internal/datastore": "*", "esbuild": "^0.25.11", "pino": "^9.7.0", diff --git a/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts similarity index 95% rename from scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts rename to scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts index bc3c4b73..c63dfe61 100644 --- a/scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts +++ b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts @@ -3,8 +3,8 @@ import { LetterStatusType } from "@internal/datastore"; import { createLetter, createLetterDto, -} from "../../helpers/create_letter_helpers"; -import { uploadFile } from "../../helpers/s3_helpers"; +} from "../../helpers/create-letter-helpers"; +import { uploadFile } from "../../helpers/s3-helpers"; jest.mock("../../helpers/s3_helpers"); diff --git a/scripts/utilities/letter-test-data/src/cli/index.ts b/scripts/utilities/letter-test-data/src/cli/index.ts index fba64289..97b6e038 100644 --- a/scripts/utilities/letter-test-data/src/cli/index.ts +++ b/scripts/utilities/letter-test-data/src/cli/index.ts @@ -5,9 +5,9 @@ import { randomUUID } from "node:crypto"; import { createLetter, createLetterDto, -} from "../helpers/create_letter_helpers"; +} from "../helpers/create-letter-helpers"; import { createLetterRepository } from "../infrastructure/letter-repo-factory"; -import { uploadFile } from "../helpers/s3_helpers"; +import { uploadFile } from "../helpers/s3-helpers"; async function main() { await yargs(hideBin(process.argv)) @@ -64,13 +64,11 @@ async function main() { }, async (argv) => { const { supplierId } = argv; - const letterId = argv.letterId ? argv.letterId : randomUUID(); + const letterId = argv.letterId ?? randomUUID(); const bucketName = `nhs-${argv.awsAccountId}-eu-west-2-${argv.environment}-supapi-test-letters`; const targetFilename = `${letterId}.pdf`; - const groupId = argv.groupId ? argv.groupId : randomUUID(); - const specificationId = argv.specificationId - ? argv.specificationId - : randomUUID(); + const groupId = argv.groupId ?? randomUUID(); + const specificationId = argv.specificationId ?? randomUUID(); const { status } = argv; const { environment } = argv; const { ttlHours } = argv; @@ -145,10 +143,8 @@ async function main() { // parse args const { supplierId } = argv; - const groupId = argv.groupId ? argv.groupId : randomUUID(); - const specificationId = argv.specificationId - ? argv.specificationId - : randomUUID(); + const groupId = argv.groupId ?? randomUUID(); + const specificationId = argv.specificationId ?? randomUUID(); const { status } = argv; const { environment } = argv; const { ttlHours } = argv; diff --git a/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts similarity index 97% rename from scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts rename to scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts index c6137db7..c04b7ee9 100644 --- a/scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts @@ -3,7 +3,7 @@ import { LetterRepository, LetterStatusType, } from "@internal/datastore"; -import { uploadFile } from "./s3_helpers"; +import { uploadFile } from "./s3-helpers"; export async function createLetter(params: { letterId: string; diff --git a/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts b/scripts/utilities/letter-test-data/src/helpers/s3-helpers.ts similarity index 92% rename from scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts rename to scripts/utilities/letter-test-data/src/helpers/s3-helpers.ts index 0e5dde77..b88bbf74 100644 --- a/scripts/utilities/letter-test-data/src/helpers/s3_helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/s3-helpers.ts @@ -2,7 +2,7 @@ import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { readFileSync } from "node:fs"; import path from "node:path"; -export async function uploadFile( +export default async function uploadFile( bucketName: string, supplierId: string, sourceFilename: string, @@ -24,5 +24,6 @@ export async function uploadFile( return await s3.send(command); } catch (error) { console.error("Error uploading file:", error); + throw error; } } diff --git a/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts b/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts index f2bef4a4..c6440bf1 100644 --- a/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts +++ b/scripts/utilities/letter-test-data/src/infrastructure/letter-repo-factory.ts @@ -3,7 +3,7 @@ import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; import { pino } from "pino"; import { LetterRepository } from "@internal/datastore"; -export function createLetterRepository( +export default function createLetterRepository( environment: string, ttlHours: number, ): LetterRepository { From f738f1542e84043367d3ce0799ec4eaf64f545fb Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 11:42:53 +0000 Subject: [PATCH 03/15] supplier data auto fixes --- .../utilities/supplier-data/jest.config.ts | 32 ++++++------- .../utilities/supplier-data/src/cli/index.ts | 45 ++++++++----------- .../infrastructure/suppliers-repo-factory.ts | 12 ++--- 3 files changed, 42 insertions(+), 47 deletions(-) diff --git a/scripts/utilities/supplier-data/jest.config.ts b/scripts/utilities/supplier-data/jest.config.ts index f2972c27..4bb3369a 100644 --- a/scripts/utilities/supplier-data/jest.config.ts +++ b/scripts/utilities/supplier-data/jest.config.ts @@ -1,7 +1,7 @@ -import type { Config } from 'jest'; +import type { Config } from "jest"; export const baseJestConfig: Config = { - preset: 'ts-jest', + preset: "ts-jest", // Automatically clear mock calls, instances, contexts and results before every test clearMocks: true, @@ -10,10 +10,10 @@ export const baseJestConfig: Config = { collectCoverage: true, // The directory where Jest should output its coverage files - coverageDirectory: './.reports/unit/coverage', + coverageDirectory: "./.reports/unit/coverage", // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'babel', + coverageProvider: "babel", coverageThreshold: { global: { @@ -24,37 +24,37 @@ export const baseJestConfig: Config = { }, }, - coveragePathIgnorePatterns: ['/__tests__/'], - transform: { '^.+\\.ts$': 'ts-jest' }, - testPathIgnorePatterns: ['.build'], - testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + coveragePathIgnorePatterns: ["/__tests__/"], + transform: { "^.+\\.ts$": "ts-jest" }, + testPathIgnorePatterns: [".build"], + testMatch: ["**/?(*.)+(spec|test).[jt]s?(x)"], // Use this configuration option to add custom reporters to Jest reporters: [ - 'default', + "default", [ - 'jest-html-reporter', + "jest-html-reporter", { - pageTitle: 'Test Report', - outputPath: './.reports/unit/test-report.html', + pageTitle: "Test Report", + outputPath: "./.reports/unit/test-report.html", includeFailureMsg: true, }, ], ], // The test environment that will be used for testing - testEnvironment: 'jsdom', + testEnvironment: "jsdom", }; const utilsJestConfig = { ...baseJestConfig, - testEnvironment: 'node', + testEnvironment: "node", coveragePathIgnorePatterns: [ ...(baseJestConfig.coveragePathIgnorePatterns ?? []), - 'cli/index.ts', - 'suppliers-repo-factory.ts', + "cli/index.ts", + "suppliers-repo-factory.ts", ], }; diff --git a/scripts/utilities/supplier-data/src/cli/index.ts b/scripts/utilities/supplier-data/src/cli/index.ts index 3efab279..0b5be186 100644 --- a/scripts/utilities/supplier-data/src/cli/index.ts +++ b/scripts/utilities/supplier-data/src/cli/index.ts @@ -1,11 +1,9 @@ import { hideBin } from "yargs/helpers"; -import yargs from 'yargs'; +import yargs from "yargs"; import { LetterStatusType } from "@internal/datastore/src/types"; -import { randomUUID } from "crypto"; +import { randomUUID } from "node:crypto"; import { createSupplierRepository } from "../infrastructure/suppliers-repo-factory"; - - async function main() { await yargs(hideBin(process.argv)) .command( @@ -16,35 +14,32 @@ async function main() { type: "string", demandOption: true, }, - "id": { + id: { type: "string", demandOption: true, }, - "name": { + name: { type: "string", demandOption: true, }, - "apimId": { + apimId: { type: "string", demandOption: true, }, status: { type: "string", demandOption: true, - choices: [ - "ENABLED", - "DISABLED" - ], + choices: ["ENABLED", "DISABLED"], }, }, async (argv) => { // parse args - const id = argv.id; - const name = argv.name; - const apimId = argv.apimId; + const { id } = argv; + const { name } = argv; + const { apimId } = argv; const status = argv.status as "ENABLED" | "DISABLED"; - const environment = argv.environment; + const { environment } = argv; const supplierRepository = createSupplierRepository(environment); @@ -56,13 +51,13 @@ async function main() { }); console.log(`PUT successful ${JSON.stringify(putResult)}`); - } + }, ) .command( "get-supplier-by-id", "Get a supplier by their Supplier ID", { - "id": { + id: { type: "string", demandOption: true, }, @@ -72,9 +67,8 @@ async function main() { }, }, async (argv) => { - - const id = argv.id; - const environment = argv.environment; + const { id } = argv; + const { environment } = argv; const supplierRepository = createSupplierRepository(environment); @@ -87,7 +81,7 @@ async function main() { "get-supplier-by-apim-id", "Get a supplier by their APIM ID", { - "apimId": { + apimId: { type: "string", demandOption: true, }, @@ -97,9 +91,8 @@ async function main() { }, }, async (argv) => { - - const apimId = argv.apimId; - const environment = argv.environment; + const { apimId } = argv; + const { environment } = argv; const supplierRepository = createSupplierRepository(environment); @@ -113,8 +106,8 @@ async function main() { } if (require.main === module) { - main().catch((err) => { - console.error(err); + main().catch((error) => { + console.error(error); process.exitCode = 1; }); } diff --git a/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts b/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts index 3bddc616..a37e2b5d 100644 --- a/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts +++ b/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts @@ -1,9 +1,11 @@ -import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; -import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; -import { pino } from 'pino'; -import { SupplierRepository } from '@internal/datastore'; +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; +import { pino } from "pino"; +import { SupplierRepository } from "@internal/datastore"; -export function createSupplierRepository(environment: string): SupplierRepository { +export function createSupplierRepository( + environment: string, +): SupplierRepository { const ddbClient = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(ddbClient); const log = pino(); From ba51e4b17e3446064881fa399ee24187450e293f Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 11:46:33 +0000 Subject: [PATCH 04/15] supplier data manual fixes --- package-lock.json | 600 ++++++++++++++++++ scripts/utilities/supplier-data/package.json | 2 + .../utilities/supplier-data/src/cli/index.ts | 2 - .../infrastructure/suppliers-repo-factory.ts | 2 +- 4 files changed, 603 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e33ee81d..3c9e98bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27881,6 +27881,8 @@ "name": "nhs-notify-supplier-api-suppliers-data-utility", "version": "0.0.1", "dependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0", + "@aws-sdk/lib-dynamodb": "^3.954.0", "@internal/datastore": "*", "esbuild": "^0.25.11", "pino": "^9.7.0", @@ -27894,6 +27896,604 @@ "typescript": "^5.8.3" } }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/client-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.954.0.tgz", + "integrity": "sha512-QhdiE3W9jC8wAmkjQhiwDBdpaK3/y/kc9aXfTyj8TaPP+B39zt56zA0VT4GtmXauyiYb81qcvKIjIDTvr95Y4A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-node": "3.954.0", + "@aws-sdk/dynamodb-codec": "3.954.0", + "@aws-sdk/middleware-endpoint-discovery": "3.953.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/client-sso": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.954.0.tgz", + "integrity": "sha512-FVyMAvlFhLK68DHWB1lSkCRTm25xl38bIZDd+jKt5+yDolCrG5+n9aIN8AA8jNO1HNGhZuMjSIQm9r5rGmJH8g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/core": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz", + "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@aws-sdk/xml-builder": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/signature-v4": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.954.0.tgz", + "integrity": "sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.954.0.tgz", + "integrity": "sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-stream": "^4.5.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.954.0.tgz", + "integrity": "sha512-WAFD8pVwRSoBsuXcoD+s/hrdsP9Z0PNUedSgkOGExuJVAabpM2cIIMzYNsdHio9XFZUSqHkv8mF5mQXuIZvuzg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-login": "3.954.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.954.0", + "@aws-sdk/credential-provider-web-identity": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.954.0.tgz", + "integrity": "sha512-UPBjw7Lnly5i+/rES8Z5U+nPaumzEUYOE/wrHkxyH6JjwFWn8w7R07fE5Z5cgYlIq1U1lQ7sxYwB3wHPpQ65Aw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-ini": "3.954.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.954.0", + "@aws-sdk/credential-provider-web-identity": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.954.0.tgz", + "integrity": "sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.954.0.tgz", + "integrity": "sha512-UXxGfkp/plFRdyidMLvNul5zoLKmHhVQOCrD2OgR/lg9jNqNmJ7abF+Qu8abo902iDkhU21Qj4M398cx6l8Kng==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.954.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/token-providers": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.954.0.tgz", + "integrity": "sha512-XEyf1T08q1tG4zkTS4Dnf1cAQyrJUo/xlvi6XNpqGhY3bOmKUYE2h/K6eITIdytDL9VuCpWYQ6YRcIVtL29E0w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/dynamodb-codec": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.954.0.tgz", + "integrity": "sha512-fNY0L1l9e36pLJef4NY5k7Q1SJnm5rgLSxSRPT8xL+bhQBtEn2E2t4JdBiTqlxgeyuOrafWOawbg8yS3pRPcLw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/endpoint-cache": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.953.0.tgz", + "integrity": "sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==", + "license": "Apache-2.0", + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.954.0.tgz", + "integrity": "sha512-DBEzAW7WfvNy6bQ32TfpvuFSVewj5eE8O1sTQWfvylNSZu81u6sPwb+eHPEclbvC84zAANl72JnkETOIkL4r8g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/util-dynamodb": "3.954.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.953.0.tgz", + "integrity": "sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/endpoint-cache": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz", + "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/middleware-logger": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz", + "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz", + "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz", + "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/nested-clients": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.954.0.tgz", + "integrity": "sha512-JLUhf35fTQIDPLk6G5KPggL9tV//Hjhy6+N2zZeis76LuBRNhKDq8z1CFyKhjf00vXi/tDYdn9D7y9emI+5Y/g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz", + "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/token-providers": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.954.0.tgz", + "integrity": "sha512-rDyN3oQQKMOJgyQ9/LNbh4fAGAj8ePMGOAQzSP/kyzizmViI6STpBW1o/VRqiTgMNi1bvA9ZasDtfrJqcVt0iA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/types": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz", + "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/util-dynamodb": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.954.0.tgz", + "integrity": "sha512-PXjS9P98OMMVXl4ledr/nTHGmNx6oF2rqTBvSQKKWi8dB4mcHjSaU5ASsklQC944xLs1IGsUkrJ39vu7bEqLoA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/util-endpoints": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz", + "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-endpoints": "^3.2.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz", + "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz", + "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "scripts/utilities/supplier-data/node_modules/@aws-sdk/xml-builder": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz", + "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.10.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", + "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/utilities/supplier-data/node_modules/@smithy/util-waiter": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz", + "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "scripts/utilities/supplier-data/node_modules/cliui": { "version": "8.0.1", "license": "ISC", diff --git a/scripts/utilities/supplier-data/package.json b/scripts/utilities/supplier-data/package.json index a74ca076..ebeb6a55 100644 --- a/scripts/utilities/supplier-data/package.json +++ b/scripts/utilities/supplier-data/package.json @@ -1,5 +1,7 @@ { "dependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0", + "@aws-sdk/lib-dynamodb": "^3.954.0", "@internal/datastore": "*", "esbuild": "^0.25.11", "pino": "^9.7.0", diff --git a/scripts/utilities/supplier-data/src/cli/index.ts b/scripts/utilities/supplier-data/src/cli/index.ts index 0b5be186..cc60ae5e 100644 --- a/scripts/utilities/supplier-data/src/cli/index.ts +++ b/scripts/utilities/supplier-data/src/cli/index.ts @@ -1,7 +1,5 @@ import { hideBin } from "yargs/helpers"; import yargs from "yargs"; -import { LetterStatusType } from "@internal/datastore/src/types"; -import { randomUUID } from "node:crypto"; import { createSupplierRepository } from "../infrastructure/suppliers-repo-factory"; async function main() { diff --git a/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts b/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts index a37e2b5d..59ce4c3a 100644 --- a/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts +++ b/scripts/utilities/supplier-data/src/infrastructure/suppliers-repo-factory.ts @@ -3,7 +3,7 @@ import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; import { pino } from "pino"; import { SupplierRepository } from "@internal/datastore"; -export function createSupplierRepository( +export default function createSupplierRepository( environment: string, ): SupplierRepository { const ddbClient = new DynamoDBClient({}); From 939ee380983f67364938ba87350f2674b27b7c87 Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 13:53:19 +0000 Subject: [PATCH 05/15] general tidyup --- docs/package.json | 1 + internal/datastore/.eslintignore | 1 - internal/events/tsconfig.json | 3 ++- lambdas/api-handler/.eslintignore | 1 - lambdas/authorizer/.eslintignore | 1 - lambdas/letter-updates-transformer/.eslintignore | 1 - lambdas/upsert-letter/.eslintignore | 1 - scripts/utilities/letter-test-data/.eslintignore | 1 - scripts/utilities/supplier-data/.eslintignore | 1 - 9 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 internal/datastore/.eslintignore delete mode 100644 lambdas/api-handler/.eslintignore delete mode 100644 lambdas/authorizer/.eslintignore delete mode 100644 lambdas/letter-updates-transformer/.eslintignore delete mode 100644 lambdas/upsert-letter/.eslintignore delete mode 100644 scripts/utilities/letter-test-data/.eslintignore delete mode 100644 scripts/utilities/supplier-data/.eslintignore diff --git a/docs/package.json b/docs/package.json index 2f2d699b..c694856e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,6 +14,7 @@ "build": "JEKYLL_ENV=production bundle exec jekyll build --trace --config _config.yml,_config.version.yml", "debug": "JEKYLL_ENV=development BUNDLE_GEMFILE=Gemfile bundle exec jekyll serve --config _config.yml,_config.dev.yml,_config.version.yml --limit_posts 100 --trace", "generate-includes": "./generate-includes.sh", + "lint": "echo \"Documentation module has no code to lint\"", "test:unit": "echo \"Documentation module has no unit tests\"", "typecheck": "echo \"Documentation module has no typescript to typecheck\"" }, diff --git a/internal/datastore/.eslintignore b/internal/datastore/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/internal/datastore/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/internal/events/tsconfig.json b/internal/events/tsconfig.json index fa5c2949..a9b1c7ab 100644 --- a/internal/events/tsconfig.json +++ b/internal/events/tsconfig.json @@ -14,6 +14,7 @@ "extends": "../../tsconfig.base.json", "include": [ "src/**/*", - "package.json" + "package.json", + "jest.config.ts" ] } diff --git a/lambdas/api-handler/.eslintignore b/lambdas/api-handler/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/lambdas/api-handler/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/lambdas/authorizer/.eslintignore b/lambdas/authorizer/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/lambdas/authorizer/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/lambdas/letter-updates-transformer/.eslintignore b/lambdas/letter-updates-transformer/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/lambdas/letter-updates-transformer/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/lambdas/upsert-letter/.eslintignore b/lambdas/upsert-letter/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/lambdas/upsert-letter/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/scripts/utilities/letter-test-data/.eslintignore b/scripts/utilities/letter-test-data/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/scripts/utilities/letter-test-data/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/scripts/utilities/supplier-data/.eslintignore b/scripts/utilities/supplier-data/.eslintignore deleted file mode 100644 index 1521c8b7..00000000 --- a/scripts/utilities/supplier-data/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -dist From 01b684eb6d347104962b0879a130949389140202 Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 14:48:13 +0000 Subject: [PATCH 06/15] aws-lanbda install --- lambdas/authorizer/package.json | 1 + lambdas/upsert-letter/package.json | 1 + package-lock.json | 20 ++------------------ 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/lambdas/authorizer/package.json b/lambdas/authorizer/package.json index b359c393..d89f0315 100644 --- a/lambdas/authorizer/package.json +++ b/lambdas/authorizer/package.json @@ -4,6 +4,7 @@ "@aws-sdk/lib-dynamodb": "^3.858.0", "@internal/datastore": "*", "@types/aws-lambda": "^8.10.148", + "aws-lambda": "^1.0.7", "esbuild": "^0.25.11", "pino": "^9.7.0", "zod": "^4.1.11" diff --git a/lambdas/upsert-letter/package.json b/lambdas/upsert-letter/package.json index af6f91bf..61d29e01 100644 --- a/lambdas/upsert-letter/package.json +++ b/lambdas/upsert-letter/package.json @@ -1,6 +1,7 @@ { "dependencies": { "@types/aws-lambda": "^8.10.148", + "aws-lambda": "^1.0.7", "esbuild": "^0.24.0" }, "devDependencies": { diff --git a/package-lock.json b/package-lock.json index 3c9e98bb..583d1726 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1630,6 +1630,7 @@ "@aws-sdk/lib-dynamodb": "^3.858.0", "@internal/datastore": "*", "@types/aws-lambda": "^8.10.148", + "aws-lambda": "^1.0.7", "esbuild": "^0.25.11", "pino": "^9.7.0", "zod": "^4.1.11" @@ -2501,6 +2502,7 @@ "version": "0.0.1", "dependencies": { "@types/aws-lambda": "^8.10.148", + "aws-lambda": "^1.0.7", "esbuild": "^0.24.0" }, "devDependencies": { @@ -27731,15 +27733,6 @@ "node": ">=18.0.0" } }, - "scripts/utilities/letter-test-data/node_modules/@aws/lambda-invoke-store": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", - "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, "scripts/utilities/letter-test-data/node_modules/@smithy/util-waiter": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz", @@ -28471,15 +28464,6 @@ "node": ">=18.0.0" } }, - "scripts/utilities/supplier-data/node_modules/@aws/lambda-invoke-store": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", - "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, "scripts/utilities/supplier-data/node_modules/@smithy/util-waiter": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz", From 5f33644cfac113ab59d8ca9a6bfbe5634fc75aa3 Mon Sep 17 00:00:00 2001 From: David Wass Date: Thu, 18 Dec 2025 15:50:20 +0000 Subject: [PATCH 07/15] Update event schema version --- internal/events/package.json | 2 +- .../src/mappers/__tests__/letter-mapper.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/events/package.json b/internal/events/package.json index 2d799646..8005d13e 100644 --- a/internal/events/package.json +++ b/internal/events/package.json @@ -50,5 +50,5 @@ "typecheck": "tsc --noEmit" }, "types": "dist/index.d.ts", - "version": "1.0.5" + "version": "1.0.6" } diff --git a/lambdas/letter-updates-transformer/src/mappers/__tests__/letter-mapper.test.ts b/lambdas/letter-updates-transformer/src/mappers/__tests__/letter-mapper.test.ts index fe5b5a79..9499ef95 100644 --- a/lambdas/letter-updates-transformer/src/mappers/__tests__/letter-mapper.test.ts +++ b/lambdas/letter-updates-transformer/src/mappers/__tests__/letter-mapper.test.ts @@ -22,7 +22,7 @@ describe("letter-mapper", () => { expect(event.dataschema).toBe( `https://notify.nhs.uk/cloudevents/schemas/supplier-api/letter.PRINTED.${event.dataschemaversion}.schema.json`, ); - expect(event.dataschemaversion).toBe("1.0.5"); + expect(event.dataschemaversion).toBe("1.0.6"); expect(event.subject).toBe("letter-origin/supplier-api/letter/id1"); expect(event.time).toBe("2025-11-24T15:55:18.000Z"); expect(event.recordedtime).toBe("2025-11-24T15:55:18.000Z"); From 36ae3e12cee3deb4b3a605b22cc08b3a434c54af Mon Sep 17 00:00:00 2001 From: David Wass Date: Fri, 19 Dec 2025 10:36:39 +0000 Subject: [PATCH 08/15] fix tests --- .../helpers/create-letter-helpers.test.ts | 4 +- .../src/__test__/helpers/s3-helpers.test.ts | 87 +++++++++++++++++++ .../src/helpers/create-letter-helpers.ts | 2 +- 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 scripts/utilities/letter-test-data/src/__test__/helpers/s3-helpers.test.ts diff --git a/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts index c63dfe61..36217a5c 100644 --- a/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts +++ b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts @@ -4,9 +4,9 @@ import { createLetter, createLetterDto, } from "../../helpers/create-letter-helpers"; -import { uploadFile } from "../../helpers/s3-helpers"; +import uploadFile from "../../helpers/s3-helpers"; -jest.mock("../../helpers/s3_helpers"); +jest.mock("../../helpers/s3-helpers"); describe("Create letter helpers", () => { beforeEach(() => { diff --git a/scripts/utilities/letter-test-data/src/__test__/helpers/s3-helpers.test.ts b/scripts/utilities/letter-test-data/src/__test__/helpers/s3-helpers.test.ts new file mode 100644 index 00000000..22e56cd5 --- /dev/null +++ b/scripts/utilities/letter-test-data/src/__test__/helpers/s3-helpers.test.ts @@ -0,0 +1,87 @@ +/** + * Unit tests for s3-helpers.ts + * + * Mocks: + * - @aws-sdk/client-s3: S3Client (with send) and PutObjectCommand + * - node:fs.readFileSync to avoid touching the filesystem + */ + +import * as s3Module from "@aws-sdk/client-s3"; +import uploadFile from "../../helpers/s3-helpers"; + +jest.mock("@aws-sdk/client-s3", () => { + const sendMock = jest.fn(); + class PutObjectCommand { + input: any; + + constructor(input: any) { + this.input = input; + } + } + const S3Client = jest.fn().mockImplementation(() => ({ send: sendMock })); + return { + S3Client, + PutObjectCommand, + __sendMock: sendMock, + __esModule: true, + }; +}); + +jest.mock("node:fs", () => ({ + readFileSync: jest.fn().mockReturnValue(Buffer.from("fake-pdf-bytes")), +})); + +describe("uploadFile", () => { + const bucket = "my-bucket"; + const supplierId = "supplier-1"; + const sourceFilename = "some.pdf"; + const targetFilename = "target.pdf"; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("calls S3Client.send with a PutObjectCommand containing correct params", async () => { + const sendMock = (s3Module as any).__sendMock as jest.Mock; + sendMock.mockResolvedValue({ ETag: '"etag-value"' }); + + await expect( + uploadFile(bucket, supplierId, sourceFilename, targetFilename), + ).resolves.toBeDefined(); + + // S3Client is a mocked constructor — grab the instance that was created + const S3ClientMock = (s3Module as any).S3Client as jest.Mock; + expect(S3ClientMock).toHaveBeenCalled(); + + const instance = S3ClientMock.mock.results[0].value; + expect(instance.send).toHaveBeenCalledTimes(1); + + const calledWith = instance.send.mock.calls[0][0]; + // The mocked PutObjectCommand stores input as `input` property + expect(calledWith).toHaveProperty("input"); + expect(calledWith.input).toEqual({ + Bucket: bucket, + Key: `${supplierId}/${targetFilename}`, + Body: Buffer.from("fake-pdf-bytes"), + ContentType: "application/pdf", + }); + }); + + it("logs and rethrows when S3Client.send rejects", async () => { + const sendMock = (s3Module as any).__sendMock as jest.Mock; + const err = new Error("upload-failed"); + sendMock.mockRejectedValueOnce(err); + + const consoleSpy = jest + .spyOn(console, "error") + .mockImplementation(() => {}); + + await expect( + uploadFile(bucket, supplierId, sourceFilename, targetFilename), + ).rejects.toThrow("upload-failed"); + + expect(consoleSpy).toHaveBeenCalledWith("Error uploading file:", err); + + consoleSpy.mockRestore(); + }); +}); diff --git a/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts index c04b7ee9..827c6801 100644 --- a/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts @@ -3,7 +3,7 @@ import { LetterRepository, LetterStatusType, } from "@internal/datastore"; -import { uploadFile } from "./s3-helpers"; +import uploadFile from "./s3-helpers"; export async function createLetter(params: { letterId: string; From 13c62e7dd125dcc22b3f0e204f623251bbb723b2 Mon Sep 17 00:00:00 2001 From: Mark Slowey Date: Wed, 24 Dec 2025 11:06:01 +0000 Subject: [PATCH 09/15] CI typecheck and lint --- .github/workflows/stage-1-commit.yaml | 50 +++++++++++++++++++++++++++ docs/package.json | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index 4d9d5b14..a3f1dd78 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -150,6 +150,56 @@ jobs: uses: actions/checkout@v5 - name: "Lint Terraform" uses: ./.github/actions/lint-terraform + + detect-typescript-changes: + name: "Detect TypeScript Changes" + runs-on: ubuntu-latest + outputs: + typescript_changed: ${{ steps.check.outputs.typescript_changed }} + steps: + - name: "Checkout code" + uses: actions/checkout@v5 + + - name: "Check for TypeScript changes" + id: check + run: | + git fetch origin main || true # Ensure you have the latest main branch + CHANGED_FILES=$(git diff --name-only HEAD origin/main) + echo "Changed files: $CHANGED_FILES" + + if echo "$CHANGED_FILES" | grep -qE '\.ts$'; then + echo "Typescript files have changed." + echo "typescript_changed=true" >> $GITHUB_OUTPUT + else + echo "No Typescript changes detected." + echo "typescript_changed=false" >> $GITHUB_OUTPUT + fi + typecheck-typescript: + name: "Typecheck TypeScript" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: detect-typescript-changes + if: needs.detect-typescript-changes.outputs.typescript_changed == 'true' + steps: + - name: "Checkout code" + uses: actions/checkout@v5 + - name: "Typecheck TypeScript" + run: | + npm run typecheck --workspaces + lint-typescript: + name: "Typecheck TypeScript" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: detect-typescript-changes + if: needs.detect-typescript-changes.outputs.typescript_changed == 'true' + steps: + - name: "Checkout code" + uses: actions/checkout@v5 + - name: "Typecheck TypeScript" + run: | + npm run lint --workspaces + + trivy-iac: name: "Trivy IaC Scan" permissions: diff --git a/docs/package.json b/docs/package.json index c694856e..c6116a80 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,7 +14,7 @@ "build": "JEKYLL_ENV=production bundle exec jekyll build --trace --config _config.yml,_config.version.yml", "debug": "JEKYLL_ENV=development BUNDLE_GEMFILE=Gemfile bundle exec jekyll serve --config _config.yml,_config.dev.yml,_config.version.yml --limit_posts 100 --trace", "generate-includes": "./generate-includes.sh", - "lint": "echo \"Documentation module has no code to lint\"", + "lint": "echo \"Documentation module has no typescript to lint\"", "test:unit": "echo \"Documentation module has no unit tests\"", "typecheck": "echo \"Documentation module has no typescript to typecheck\"" }, From a3f693dbec7211e1316875177910aa486778474b Mon Sep 17 00:00:00 2001 From: Mark Slowey Date: Wed, 24 Dec 2025 11:10:03 +0000 Subject: [PATCH 10/15] default perms --- .github/workflows/stage-1-commit.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index a3f1dd78..8be84bbd 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -36,6 +36,10 @@ on: required: true type: string + +permissions: + contents: read + jobs: scan-secrets: name: "Scan secrets" From 0ac07eb861df32fa52a8edea7dbfc20ea6415466 Mon Sep 17 00:00:00 2001 From: Mark Slowey Date: Wed, 24 Dec 2025 11:11:14 +0000 Subject: [PATCH 11/15] try and make the alerts happy --- .github/workflows/stage-1-commit.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index 8be84bbd..f9740fb8 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -1,5 +1,8 @@ name: "Commit stage" +permissions: + contents: read + on: workflow_call: inputs: @@ -36,10 +39,6 @@ on: required: true type: string - -permissions: - contents: read - jobs: scan-secrets: name: "Scan secrets" From e7417614a6b2f8d030b1a0f0de4bf10f427a4f2c Mon Sep 17 00:00:00 2001 From: Mark Slowey Date: Wed, 24 Dec 2025 11:48:05 +0000 Subject: [PATCH 12/15] Revert "CI typecheck and lint" This reverts commit 663ac0a059fa661106db0525420f89d6cd09c390. --- .github/workflows/stage-1-commit.yaml | 50 --------------------------- docs/package.json | 2 +- 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index f9740fb8..80ad8c8f 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -153,56 +153,6 @@ jobs: uses: actions/checkout@v5 - name: "Lint Terraform" uses: ./.github/actions/lint-terraform - - detect-typescript-changes: - name: "Detect TypeScript Changes" - runs-on: ubuntu-latest - outputs: - typescript_changed: ${{ steps.check.outputs.typescript_changed }} - steps: - - name: "Checkout code" - uses: actions/checkout@v5 - - - name: "Check for TypeScript changes" - id: check - run: | - git fetch origin main || true # Ensure you have the latest main branch - CHANGED_FILES=$(git diff --name-only HEAD origin/main) - echo "Changed files: $CHANGED_FILES" - - if echo "$CHANGED_FILES" | grep -qE '\.ts$'; then - echo "Typescript files have changed." - echo "typescript_changed=true" >> $GITHUB_OUTPUT - else - echo "No Typescript changes detected." - echo "typescript_changed=false" >> $GITHUB_OUTPUT - fi - typecheck-typescript: - name: "Typecheck TypeScript" - runs-on: ubuntu-latest - timeout-minutes: 5 - needs: detect-typescript-changes - if: needs.detect-typescript-changes.outputs.typescript_changed == 'true' - steps: - - name: "Checkout code" - uses: actions/checkout@v5 - - name: "Typecheck TypeScript" - run: | - npm run typecheck --workspaces - lint-typescript: - name: "Typecheck TypeScript" - runs-on: ubuntu-latest - timeout-minutes: 5 - needs: detect-typescript-changes - if: needs.detect-typescript-changes.outputs.typescript_changed == 'true' - steps: - - name: "Checkout code" - uses: actions/checkout@v5 - - name: "Typecheck TypeScript" - run: | - npm run lint --workspaces - - trivy-iac: name: "Trivy IaC Scan" permissions: diff --git a/docs/package.json b/docs/package.json index c6116a80..c694856e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,7 +14,7 @@ "build": "JEKYLL_ENV=production bundle exec jekyll build --trace --config _config.yml,_config.version.yml", "debug": "JEKYLL_ENV=development BUNDLE_GEMFILE=Gemfile bundle exec jekyll serve --config _config.yml,_config.dev.yml,_config.version.yml --limit_posts 100 --trace", "generate-includes": "./generate-includes.sh", - "lint": "echo \"Documentation module has no typescript to lint\"", + "lint": "echo \"Documentation module has no code to lint\"", "test:unit": "echo \"Documentation module has no unit tests\"", "typecheck": "echo \"Documentation module has no typescript to typecheck\"" }, From 939dd54caf3648d0e21b0315e98b9f1976e8448f Mon Sep 17 00:00:00 2001 From: Mark Slowey Date: Wed, 24 Dec 2025 11:52:24 +0000 Subject: [PATCH 13/15] test hooks --- scripts/tests/lint.sh | 22 ++++++++++++++++++++++ scripts/tests/typecheck.sh | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100755 scripts/tests/lint.sh create mode 100755 scripts/tests/typecheck.sh diff --git a/scripts/tests/lint.sh b/scripts/tests/lint.sh new file mode 100755 index 00000000..2ace8310 --- /dev/null +++ b/scripts/tests/lint.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +# This file is for you! Edit it to call your unit test suite. Note that the same +# file will be called if you run it locally as if you run it on CI. + +# Replace the following line with something like: +# +# rails test:unit +# python manage.py test +# npm run test +# +# or whatever is appropriate to your project. You should *only* run your fast +# tests from here. If you want to run other test suites, see the predefined +# tasks in scripts/test.mk. + +# run tests +npm ci +npm run lint --workspaces diff --git a/scripts/tests/typecheck.sh b/scripts/tests/typecheck.sh new file mode 100755 index 00000000..2ed6c2e0 --- /dev/null +++ b/scripts/tests/typecheck.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +# This file is for you! Edit it to call your unit test suite. Note that the same +# file will be called if you run it locally as if you run it on CI. + +# Replace the following line with something like: +# +# rails test:unit +# python manage.py test +# npm run test +# +# or whatever is appropriate to your project. You should *only* run your fast +# tests from here. If you want to run other test suites, see the predefined +# tasks in scripts/test.mk. + +# run tests +npm ci +npm run typecheck --workspaces From 836a26c71b8f1319e013f0779f5cf9c3383fe690 Mon Sep 17 00:00:00 2001 From: David Wass Date: Tue, 6 Jan 2026 14:50:33 +0000 Subject: [PATCH 14/15] auto test fixes --- .../apiGateway-tests/createMi.spec.ts | 186 ++++++++------ .../apiGateway-tests/getLetterStatus.spec.ts | 114 +++++---- .../apiGateway-tests/getLetters.spec.ts | 108 ++++---- .../apiGateway-tests/testCases/createMi.ts | 62 ++--- .../testCases/updateLetterStatus.ts | 112 +++++---- .../updateLetterStatus.spec.ts | 214 +++++++++------- tests/config/main.config.ts | 16 +- tests/config/playwright.base.config.ts | 6 +- tests/config/reporters.ts | 20 +- tests/config/sandbox.config.ts | 16 +- tests/constants/api_constants.ts | 13 +- tests/constants/request_headers.ts | 70 +++--- tests/helpers/awsGatewayHelper.ts | 8 +- tests/helpers/commonTypes.ts | 138 ++++++----- tests/helpers/generate_fetch_testData.ts | 88 ++++--- tests/helpers/pnpmHelpers.ts | 61 ++--- tests/helpers/validateJsonSchema.ts | 20 +- tests/mtls/mtls_test.spec.ts | 16 +- tests/sandbox/getLetterStatus.spec.ts | 43 ++-- tests/sandbox/getListOfLetters.spec.ts | 40 +-- .../testCases/getLetterStatus_testCases.ts | 232 +++++++++--------- .../testCases/getListOfLetters_testCases.ts | 136 +++++----- .../testCases/updateLetterStatus_testCases.ts | 221 +++++++++-------- .../updateMultipleStatus_testCases.ts | 191 +++++++------- tests/sandbox/updateLetterStatus.spec.ts | 43 ++-- .../updateMultipleLetterStatus.spec.ts | 36 +-- 26 files changed, 1193 insertions(+), 1017 deletions(-) diff --git a/tests/component-tests/apiGateway-tests/createMi.spec.ts b/tests/component-tests/apiGateway-tests/createMi.spec.ts index 0455c06d..23464045 100644 --- a/tests/component-tests/apiGateway-tests/createMi.spec.ts +++ b/tests/component-tests/apiGateway-tests/createMi.spec.ts @@ -1,10 +1,25 @@ -import {test, expect} from '@playwright/test'; +import { expect, test } from "@playwright/test"; +import { time } from "node:console"; import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; -import { MI_ENDPOINT } from '../../constants/api_constants'; -import { createHeaderWithNoCorrelationId, createHeaderWithNoRequestId, createInvalidRequestHeaders, createValidRequestHeaders } from '../../constants/request_headers'; -import { miInvalidDateRequest, miInvalidRequest, miValidRequest } from './testCases/createMi'; -import { time } from 'console'; -import { error400InvalidDate, error400ResponseBody, error403ResponseBody, error404ResponseBody, requestId500Error } from '../../helpers/commonTypes'; +import { MI_ENDPOINT } from "../../constants/api_constants"; +import { + createHeaderWithNoCorrelationId, + createHeaderWithNoRequestId, + createInvalidRequestHeaders, + createValidRequestHeaders, +} from "../../constants/request_headers"; +import { + miInvalidDateRequest, + miInvalidRequest, + miValidRequest, +} from "./testCases/createMi"; +import { + error400InvalidDate, + error400ResponseBody, + error403ResponseBody, + error404ResponseBody, + requestId500Error, +} from "../../helpers/commonTypes"; let baseUrl: string; @@ -12,99 +27,110 @@ test.beforeAll(async () => { baseUrl = await getRestApiGatewayBaseUrl(); }); -test.describe('API Gateway Tests to Verify Mi Endpoint', () => { - test(`Post /mi returns 200 when a valid request is passed`, async ({ request }) => { - - const headers = createValidRequestHeaders(); - const body = miValidRequest(); - - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); - - const responseBody = await response.json(); - expect(response.status()).toBe(201); - expect(responseBody.data.attributes).toMatchObject({ - groupId: 'group123', - lineItem: 'envelope-business-standard', - quantity: 10, - specificationId: 'Test-Spec-Id', - stockRemaining: 100, - timestamp: body.data.attributes.timestamp, - }); - expect(responseBody.data.type).toBe('ManagementInformation'); - }); +test.describe("API Gateway Tests to Verify Mi Endpoint", () => { + test(`Post /mi returns 200 when a valid request is passed`, async ({ + request, + }) => { + const headers = createValidRequestHeaders(); + const body = miValidRequest(); + + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, + }); - test(`Post /mi returns 400 when a invalid request is passed`, async ({ request }) => { - const headers = createValidRequestHeaders(); - const body = miInvalidRequest(); + const responseBody = await response.json(); + expect(response.status()).toBe(201); + expect(responseBody.data.attributes).toMatchObject({ + groupId: "group123", + lineItem: "envelope-business-standard", + quantity: 10, + specificationId: "Test-Spec-Id", + stockRemaining: 100, + timestamp: body.data.attributes.timestamp, + }); + expect(responseBody.data.type).toBe("ManagementInformation"); + }); - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); + test(`Post /mi returns 400 when a invalid request is passed`, async ({ + request, + }) => { + const headers = createValidRequestHeaders(); + const body = miInvalidRequest(); - const responseBody = await response.json(); - expect(response.status()).toBe(400); - expect(responseBody).toMatchObject(error400ResponseBody()); + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, }); - test(`Post /mi returns 403 when a authentication header is not passed`, async ({ request }) => { - const headers = createInvalidRequestHeaders(); - const body = miValidRequest(); + const responseBody = await response.json(); + expect(response.status()).toBe(400); + expect(responseBody).toMatchObject(error400ResponseBody()); + }); - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); + test(`Post /mi returns 403 when a authentication header is not passed`, async ({ + request, + }) => { + const headers = createInvalidRequestHeaders(); + const body = miValidRequest(); - const responseBody = await response.json(); - expect(response.status()).toBe(403); - expect(responseBody).toMatchObject(error403ResponseBody()); + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, }); - test(`Post /mi returns 500 when a correlationId is not passed`, async ({ request }) => { - const headers = createHeaderWithNoCorrelationId(); - const body = miValidRequest(); + const responseBody = await response.json(); + expect(response.status()).toBe(403); + expect(responseBody).toMatchObject(error403ResponseBody()); + }); - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); + test(`Post /mi returns 500 when a correlationId is not passed`, async ({ + request, + }) => { + const headers = createHeaderWithNoCorrelationId(); + const body = miValidRequest(); - const res = await response.json(); - expect(response.status()).toBe(500); - expect(res.errors[0].detail).toBe("The request headers don't contain the APIM correlation id"); + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, }); - test(`Post /mi returns 500 when a x-request-id is not passed`, async ({ request }) => { - const headers = createHeaderWithNoRequestId(); - const body = miValidRequest(); + const res = await response.json(); + expect(response.status()).toBe(500); + expect(res.errors[0].detail).toBe( + "The request headers don't contain the APIM correlation id", + ); + }); - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); + test(`Post /mi returns 500 when a x-request-id is not passed`, async ({ + request, + }) => { + const headers = createHeaderWithNoRequestId(); + const body = miValidRequest(); - const responseBody = await response.json(); - expect(response.status()).toBe(500); - expect(responseBody).toMatchObject(requestId500Error()); + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, }); - test(`Post /mi returns 400 when a invalid Date is passed`, async ({ request }) => { - const headers = createValidRequestHeaders(); - const body = miInvalidDateRequest(); + const responseBody = await response.json(); + expect(response.status()).toBe(500); + expect(responseBody).toMatchObject(requestId500Error()); + }); - const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { - headers: headers, - data: body - }); + test(`Post /mi returns 400 when a invalid Date is passed`, async ({ + request, + }) => { + const headers = createValidRequestHeaders(); + const body = miInvalidDateRequest(); - const responseBody = await response.json(); - expect(response.status()).toBe(400); - expect(responseBody).toMatchObject(error400InvalidDate()); + const response = await request.post(`${baseUrl}/${MI_ENDPOINT}`, { + headers, + data: body, }); - + const responseBody = await response.json(); + expect(response.status()).toBe(400); + expect(responseBody).toMatchObject(error400InvalidDate()); + }); }); diff --git a/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts b/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts index 7382cb79..39d7e118 100644 --- a/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts +++ b/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts @@ -1,9 +1,12 @@ -import { test, expect } from '@playwright/test'; -import { getRestApiGatewayBaseUrl } from '../../helpers/awsGatewayHelper'; -import { getLettersBySupplier } from '../../helpers/generate_fetch_testData'; -import { SUPPLIER_LETTERS, SUPPLIERID } from '../../constants/api_constants'; -import { createValidRequestHeaders } from '../../constants/request_headers'; -import { error404ResponseBody, error500ResponseBody } from '../../helpers/commonTypes'; +import { expect, test } from "@playwright/test"; +import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; +import { getLettersBySupplier } from "../../helpers/generate_fetch_testData"; +import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api_constants"; +import { createValidRequestHeaders } from "../../constants/request_headers"; +import { + error404ResponseBody, + error500ResponseBody, +} from "../../helpers/commonTypes"; let baseUrl: string; @@ -11,61 +14,66 @@ test.beforeAll(async () => { baseUrl = await getRestApiGatewayBaseUrl(); }); -test.describe('API Gateway Tests to Verify Get Letter Status Endpoint', () => { - test(`Get /letters/{id} returns 200 and valid response for a given id`, async ({ request }) => { +test.describe("API Gateway Tests to Verify Get Letter Status Endpoint", () => { + test(`Get /letters/{id} returns 200 and valid response for a given id`, async ({ + request, + }) => { + const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 1); - const letters = await getLettersBySupplier(SUPPLIERID, 'PENDING', 1); + if (!letters?.length) { + test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); + return; + } + const letter = letters[0]; + const headers = createValidRequestHeaders(); + const response = await request.get( + `${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, + { + headers, + }, + ); - if (!letters?.length) { - test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); - return; - } - const letter = letters[0]; - const headers = createValidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, { - headers: headers, - }); + const responseBody = await response.json(); - const responseBody = await response.json(); - - expect(response.status()).toBe(200); - expect(responseBody).toMatchObject({ - data:{ - attributes: { - status: 'PENDING', - specificationId: letter.specificationId, - groupId: letter.groupId, - }, - id: letter.id, - type: 'Letter' - } - }); + expect(response.status()).toBe(200); + expect(responseBody).toMatchObject({ + data: { + attributes: { + status: "PENDING", + specificationId: letter.specificationId, + groupId: letter.groupId, + }, + id: letter.id, + type: "Letter", + }, }); + }); - test(`Get /letters/{id} returns 404 if no resource is found for id`, async ({ request }) => - { - const id = '11'; - const headers = createValidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { - headers: headers, - }); - - const responseBody = await response.json(); - expect(response.status()).toBe(404); - expect(responseBody).toMatchObject(error404ResponseBody()); + test(`Get /letters/{id} returns 404 if no resource is found for id`, async ({ + request, + }) => { + const id = "11"; + const headers = createValidRequestHeaders(); + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { + headers, }); - test(`Get /letters/{id} returns 500 if letter is not found for supplierId ${SUPPLIERID}`, async ({ request }) => - { - const id = 'non-existing-id-12345'; - const headers = createValidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { - headers: headers, - }); + const responseBody = await response.json(); + expect(response.status()).toBe(404); + expect(responseBody).toMatchObject(error404ResponseBody()); + }); - const responseBody = await response.json(); - expect(response.status()).toBe(500); - expect(responseBody).toMatchObject(error500ResponseBody(id)); + test(`Get /letters/{id} returns 500 if letter is not found for supplierId ${SUPPLIERID}`, async ({ + request, + }) => { + const id = "non-existing-id-12345"; + const headers = createValidRequestHeaders(); + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { + headers, }); + const responseBody = await response.json(); + expect(response.status()).toBe(500); + expect(responseBody).toMatchObject(error500ResponseBody(id)); + }); }); diff --git a/tests/component-tests/apiGateway-tests/getLetters.spec.ts b/tests/component-tests/apiGateway-tests/getLetters.spec.ts index b21fa5b9..0a66a14e 100644 --- a/tests/component-tests/apiGateway-tests/getLetters.spec.ts +++ b/tests/component-tests/apiGateway-tests/getLetters.spec.ts @@ -1,8 +1,12 @@ -import { test, expect } from '@playwright/test'; -import { SUPPLIER_LETTERS } from '../../constants/api_constants'; -import { createHeaderWithNoCorrelationId, createInvalidRequestHeaders, createValidRequestHeaders } from '../../constants/request_headers'; -import { getRestApiGatewayBaseUrl } from '../../helpers/awsGatewayHelper'; -import { validateApiResponse } from '../../helpers/validateJsonSchema'; +import { expect, test } from "@playwright/test"; +import { SUPPLIER_LETTERS } from "../../constants/api_constants"; +import { + createHeaderWithNoCorrelationId, + createInvalidRequestHeaders, + createValidRequestHeaders, +} from "../../constants/request_headers"; +import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; +import { validateApiResponse } from "../../helpers/validateJsonSchema"; let baseUrl: string; @@ -10,84 +14,94 @@ test.beforeAll(async () => { baseUrl = await getRestApiGatewayBaseUrl(); }); -test.describe('API Gateway Tests To Get List Of Pending Letters', () => -{ - test('GET /letters should return 200 and list items', async ({ request }) => - { +test.describe("API Gateway Tests To Get List Of Pending Letters", () => { + test("GET /letters should return 200 and list items", async ({ request }) => { const header = createValidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}` ,{ + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { headers: header, params: { - limit:'2'}, + limit: "2", }, - ); + }); expect(response.status()).toBe(200); const responseBody = await response.json(); - expect(responseBody.data.length.toString()).toEqual('2'); + expect(responseBody.data.length.toString()).toEqual("2"); - const validationResult = validateApiResponse("get", "/letters", response.status(), responseBody); + const validationResult = validateApiResponse( + "get", + "/letters", + response.status(), + responseBody, + ); if (validationResult) { console.error("API response validation failed:", validationResult); } expect(validationResult).toBeUndefined(); }); - test('GET /letters with invalid authentication should return 403', async ({ request }) => { + test("GET /letters with invalid authentication should return 403", async ({ + request, + }) => { const header = createInvalidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}` ,{ + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { headers: header, - params:{ - limit:'2' - }, + params: { + limit: "2", }, - ); + }); expect(response.status()).toBe(403); const responseBody = await response.json(); expect(responseBody).toMatchObject({ - Message : 'User is not authorized to access this resource with an explicit deny in an identity-based policy' } - ); + Message: + "User is not authorized to access this resource with an explicit deny in an identity-based policy", + }); }); - test('GET /letters with empty correlationId should return 500', async ({ request }) => { + test("GET /letters with empty correlationId should return 500", async ({ + request, + }) => { const header = createHeaderWithNoCorrelationId(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}` ,{ + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { headers: header, - params:{ - limit:'2' - }, + params: { + limit: "2", }, - ); + }); expect(response.status()).toBe(500); const responseBody = await response.json(); - expect(responseBody.errors[0].code).toBe('NOTIFY_INTERNAL_SERVER_ERROR'); - expect(responseBody.errors[0].detail).toBe("The request headers don't contain the APIM correlation id"); - + expect(responseBody.errors[0].code).toBe("NOTIFY_INTERNAL_SERVER_ERROR"); + expect(responseBody.errors[0].detail).toBe( + "The request headers don't contain the APIM correlation id", + ); }); - test('GET /letters with invalid query param return 400', async ({ request }) => { + test("GET /letters with invalid query param return 400", async ({ + request, + }) => { const header = createValidRequestHeaders(); - const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}` ,{ - headers: header, - params:{ - limit:'?' - }, - }); + const response = await request.get(`${baseUrl}/${SUPPLIER_LETTERS}`, { + headers: header, + params: { + limit: "?", + }, + }); expect(response.status()).toBe(400); const responseBody = await response.json(); expect(responseBody).toMatchObject({ errors: [ { - id: '12345', - code: 'NOTIFY_INVALID_REQUEST', + id: "12345", + code: "NOTIFY_INVALID_REQUEST", links: { - about: 'https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier' - }, - status: '400', - title: 'Invalid request', - detail: 'The limit parameter is not a number' - } - ] + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "400", + title: "Invalid request", + detail: "The limit parameter is not a number", + }, + ], }); }); }); diff --git a/tests/component-tests/apiGateway-tests/testCases/createMi.ts b/tests/component-tests/apiGateway-tests/testCases/createMi.ts index f7f0b222..c9ba204a 100644 --- a/tests/component-tests/apiGateway-tests/testCases/createMi.ts +++ b/tests/component-tests/apiGateway-tests/testCases/createMi.ts @@ -1,70 +1,70 @@ - - - export type MiRequestBody = { data: { type: string; attributes: { - groupId: string; - lineItem: string; - quantity: number; - specificationId: string; - stockRemaining: number; - timestamp: string; + groupId: string; + lineItem: string; + quantity: number; + specificationId: string; + stockRemaining: number; + timestamp: string; }; }; }; -export function miValidRequest() : MiRequestBody{ +export function miValidRequest(): MiRequestBody { let requestBody: MiRequestBody; requestBody = { data: { -  attributes: { - groupId: 'group123', - lineItem: 'envelope-business-standard', + attributes: { + groupId: "group123", + lineItem: "envelope-business-standard", quantity: 10, - specificationId: 'Test-Spec-Id', + specificationId: "Test-Spec-Id", stockRemaining: 100, timestamp: new Date().toISOString(), }, - type: 'ManagementInformation', - }}; + type: "ManagementInformation", + }, + }; return requestBody; } -export function miInvalidRequest() : MiRequestBody{ +export function miInvalidRequest(): MiRequestBody { let requestBody: MiRequestBody; requestBody = { data: { -  attributes: { - groupId: 'group123', - lineItem: 'envelope-business-standard', + attributes: { + groupId: "group123", + lineItem: "envelope-business-standard", quantity: 10, - specificationId: 'Test-Spec-Id', + specificationId: "Test-Spec-Id", stockRemaining: 100, timestamp: new Date().toISOString(), }, - type: '?', - }}; + type: "?", + }, + }; return requestBody; } -export function miInvalidDateRequest() : MiRequestBody{ +export function miInvalidDateRequest(): MiRequestBody { let requestBody: MiRequestBody; requestBody = { data: { -  attributes: { - groupId: 'group123', - lineItem: 'envelope-business-standard', + attributes: { + groupId: "group123", + lineItem: "envelope-business-standard", quantity: 10, - specificationId: 'Test-Spec-Id', + specificationId: "Test-Spec-Id", stockRemaining: 100, - timestamp: '2021-10-28T', + timestamp: "2021-10-28T", }, - type: 'ManagementInformation', - }}; + type: "ManagementInformation", + }, + }; return requestBody; } diff --git a/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts b/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts index 1dc60d4d..0c7453e1 100644 --- a/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts +++ b/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts @@ -1,7 +1,6 @@ - -import { RequestHeaders } from '../../../constants/request_headers'; -import { SUPPLIERID } from '../../../constants/api_constants'; -import { ErrorMessageBody } from '../../../helpers/commonTypes'; +import { RequestHeaders } from "../../../constants/request_headers"; +import { SUPPLIERID } from "../../../constants/api_constants"; +import { ErrorMessageBody } from "../../../helpers/commonTypes"; export type PatchMessageRequestBody = { data: { @@ -23,92 +22,97 @@ export type PatchMessageResponseBody = { reasonCode?: string; reasonText?: string; status: string; - specificationId:string; - groupId?:string; + specificationId: string; + groupId?: string; }; }; }; export function patchRequestHeaders(): RequestHeaders { let requestHeaders: RequestHeaders; - requestHeaders = { - headerauth1: process.env.HEADERAUTH || '', - 'NHSD-Supplier-ID': SUPPLIERID, - 'NHSD-Correlation-ID': '12344', - 'X-Request-ID': 'requestId1' - }; + requestHeaders = { + headerauth1: process.env.HEADERAUTH || "", + "NHSD-Supplier-ID": SUPPLIERID, + "NHSD-Correlation-ID": "12344", + "X-Request-ID": "requestId1", + }; return requestHeaders; -}; - +} -export function patchValidRequestBody (id: string, status: string) : PatchMessageRequestBody{ +export function patchValidRequestBody( + id: string, + status: string, +): PatchMessageRequestBody { let requestBody: PatchMessageRequestBody; requestBody = { data: { -  attributes: { -   status: status, + attributes: { + status, }, - type: 'Letter', - id: id - } - + type: "Letter", + id, + }, }; return requestBody; } -export function patchFailureRequestBody (id: string, status: string) : PatchMessageRequestBody{ +export function patchFailureRequestBody( + id: string, + status: string, +): PatchMessageRequestBody { let requestBody: PatchMessageRequestBody; requestBody = { data: { - attributes: { - status: status, - reasonCode: 'R01', - reasonText: 'Test Reason' + attributes: { + status, + reasonCode: "R01", + reasonText: "Test Reason", }, - type: 'Letter', - id: id - } - + type: "Letter", + id, + }, }; return requestBody; } -export function patch400ErrorResponseBody () : ErrorMessageBody{ +export function patch400ErrorResponseBody(): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ { - id : '12344', - code : 'NOTIFY_INVALID_REQUEST', - "links": { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - "status": "400", - "title": "Invalid request", - "detail": "The request body is invalid" - } - ] + id: "12344", + code: "NOTIFY_INVALID_REQUEST", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "400", + title: "Invalid request", + detail: "The request body is invalid", + }, + ], }; return responseBody; -}; +} -export function patch500ErrorResponseBody (id: string) : ErrorMessageBody{ +export function patch500ErrorResponseBody(id: string): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: "12344", - code: "NOTIFY_INTERNAL_SERVER_ERROR", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "500", - title: "Internal server error", - detail: `Letter with id ${id} not found for supplier ${SUPPLIERID}` - } - ] + { + id: "12344", + code: "NOTIFY_INTERNAL_SERVER_ERROR", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "500", + title: "Internal server error", + detail: `Letter with id ${id} not found for supplier ${SUPPLIERID}`, + }, + ], }; return responseBody; } diff --git a/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts b/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts index 99484bf0..c34bba47 100644 --- a/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts +++ b/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts @@ -1,11 +1,21 @@ -import { test, expect } from '@playwright/test'; -import { SUPPLIER_LETTERS, SUPPLIERID } from '../../constants/api_constants'; -import { getRestApiGatewayBaseUrl } from '../../helpers/awsGatewayHelper'; -import { patch400ErrorResponseBody, patch500ErrorResponseBody, patchFailureRequestBody, patchRequestHeaders, patchValidRequestBody } from './testCases/updateLetterStatus'; -import { createTestData, deleteLettersBySupplier, getLettersBySupplier } from '../../helpers/generate_fetch_testData'; -import { randomUUID } from 'crypto'; -import { createInvalidRequestHeaders } from '../../constants/request_headers'; -import { error403ResponseBody } from '../../helpers/commonTypes'; +import { expect, test } from "@playwright/test"; +import { randomUUID } from "node:crypto"; +import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api_constants"; +import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; +import { + patch400ErrorResponseBody, + patch500ErrorResponseBody, + patchFailureRequestBody, + patchRequestHeaders, + patchValidRequestBody, +} from "./testCases/updateLetterStatus"; +import { + createTestData, + deleteLettersBySupplier, + getLettersBySupplier, +} from "../../helpers/generate_fetch_testData"; +import { createInvalidRequestHeaders } from "../../constants/request_headers"; +import { error403ResponseBody } from "../../helpers/commonTypes"; let baseUrl: string; @@ -13,87 +23,99 @@ test.beforeAll(async () => { baseUrl = await getRestApiGatewayBaseUrl(); }); -test.describe('API Gateway Tests to Verify Patch Status Endpoint', () => { - test(`Patch /letters returns 200 and status is updated to ACCEPTED`, async ({ request }) => { - - await createTestData(SUPPLIERID); - const letters = await getLettersBySupplier(SUPPLIERID, 'PENDING', 1); - - if (!letters?.length) { - test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); - return; - } - const letter = letters[0]; - const headers = patchRequestHeaders(); - const body = patchValidRequestBody(letter.id, 'ACCEPTED'); - - const response = await request.patch(`${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, { - headers: headers, - data: body - }); +test.describe("API Gateway Tests to Verify Patch Status Endpoint", () => { + test(`Patch /letters returns 200 and status is updated to ACCEPTED`, async ({ + request, + }) => { + await createTestData(SUPPLIERID); + const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 1); + + if (!letters?.length) { + test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); + return; + } + const letter = letters[0]; + const headers = patchRequestHeaders(); + const body = patchValidRequestBody(letter.id, "ACCEPTED"); + + const response = await request.patch( + `${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, + { + headers, + data: body, + }, + ); const responseBody = await response.json(); expect(response.status()).toBe(200); expect(responseBody).toMatchObject({ - data:{ + data: { attributes: { - status: 'ACCEPTED', - specificationId: letter.specificationId, - groupId: letter.groupId, + status: "ACCEPTED", + specificationId: letter.specificationId, + groupId: letter.groupId, }, id: letter.id, - type: 'Letter' - } + type: "Letter", + }, }); await deleteLettersBySupplier(letter.id); }); - test(`Patch /letters returns 200 and status is updated to REJECTED`, async ({ request }) => { - - await createTestData(SUPPLIERID); - const letters = await getLettersBySupplier(SUPPLIERID, 'PENDING', 1); - - if (!letters?.length) { - test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); - return; - } - const letter = letters[0]; - const headers = patchRequestHeaders(); - const body = patchFailureRequestBody(letter.id, 'REJECTED'); - - const response = await request.patch(`${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, { - headers: headers, - data: body - }); + test(`Patch /letters returns 200 and status is updated to REJECTED`, async ({ + request, + }) => { + await createTestData(SUPPLIERID); + const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 1); + + if (!letters?.length) { + test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`); + return; + } + const letter = letters[0]; + const headers = patchRequestHeaders(); + const body = patchFailureRequestBody(letter.id, "REJECTED"); + + const response = await request.patch( + `${baseUrl}/${SUPPLIER_LETTERS}/${letter.id}`, + { + headers, + data: body, + }, + ); const responseBody = await response.json(); expect(response.status()).toBe(200); expect(responseBody).toMatchObject({ - data:{ + data: { attributes: { - status: 'REJECTED', - specificationId: letter.specificationId, - groupId: letter.groupId, + status: "REJECTED", + specificationId: letter.specificationId, + groupId: letter.groupId, }, id: letter.id, - type: 'Letter' - } + type: "Letter", + }, }); await deleteLettersBySupplier(letter.id); }); - test(`Patch /letters returns 400 if request Body is invalid`, async ({ request }) => { - - const id = randomUUID() - const headers = patchRequestHeaders(); - const body = patchValidRequestBody(id, ''); - - const response = await request.patch(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { - headers: headers, - data: body - }); + test(`Patch /letters returns 400 if request Body is invalid`, async ({ + request, + }) => { + const id = randomUUID(); + const headers = patchRequestHeaders(); + const body = patchValidRequestBody(id, ""); + + const response = await request.patch( + `${baseUrl}/${SUPPLIER_LETTERS}/${id}`, + { + headers, + data: body, + }, + ); const responseBody = await response.json(); @@ -101,33 +123,43 @@ test.describe('API Gateway Tests to Verify Patch Status Endpoint', () => { expect(responseBody).toMatchObject(patch400ErrorResponseBody()); }); - test(`Patch /letters returns 500 if Id doesn't exist for SupplierId`, async ({ request }) => { - const headers = patchRequestHeaders(); - const id = randomUUID() - const body = patchValidRequestBody(id, 'PENDING'); + test(`Patch /letters returns 500 if Id doesn't exist for SupplierId`, async ({ + request, + }) => { + const headers = patchRequestHeaders(); + const id = randomUUID(); + const body = patchValidRequestBody(id, "PENDING"); + + const response = await request.patch( + `${baseUrl}/${SUPPLIER_LETTERS}/${id}`, + { + headers, + data: body, + }, + ); - const response = await request.patch(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { - headers: headers, - data: body - }); - - const responseBody = await response.json(); - expect(response.status()).toBe(500); - expect(responseBody).toMatchObject(patch500ErrorResponseBody(id)); - }); - - test(`Patch /letters returns 403 for invalid headers`, async ({ request }) => { - const headers = createInvalidRequestHeaders(); - const id = randomUUID() - const body = patchValidRequestBody(id, 'PENDING'); + const responseBody = await response.json(); + expect(response.status()).toBe(500); + expect(responseBody).toMatchObject(patch500ErrorResponseBody(id)); + }); - const response = await request.patch(`${baseUrl}/${SUPPLIER_LETTERS}/${id}`, { - headers: headers, - data: body - }); + test(`Patch /letters returns 403 for invalid headers`, async ({ + request, + }) => { + const headers = createInvalidRequestHeaders(); + const id = randomUUID(); + const body = patchValidRequestBody(id, "PENDING"); + + const response = await request.patch( + `${baseUrl}/${SUPPLIER_LETTERS}/${id}`, + { + headers, + data: body, + }, + ); - const responseBody = await response.json(); - expect(response.status()).toBe(403); - expect(responseBody).toMatchObject(error403ResponseBody()); - }); + const responseBody = await response.json(); + expect(response.status()).toBe(403); + expect(responseBody).toMatchObject(error403ResponseBody()); + }); }); diff --git a/tests/config/main.config.ts b/tests/config/main.config.ts index 4c87088a..fa60a5be 100644 --- a/tests/config/main.config.ts +++ b/tests/config/main.config.ts @@ -1,17 +1,17 @@ -import {defineConfig, PlaywrightTestConfig } from '@playwright/test'; -import baseConfig from './playwright.base.config'; -import { getReporters } from './reporters'; -import path from 'path'; +import { PlaywrightTestConfig, defineConfig } from "@playwright/test"; +import path from "node:path"; +import baseConfig from "./playwright.base.config"; +import { getReporters } from "./reporters"; const localConfig: PlaywrightTestConfig = { ...baseConfig, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: getReporters('api-test'), + reporter: getReporters("api-test"), projects: [ { - name: 'component-tests', - testDir: path.resolve(__dirname, '../component-tests'), - testMatch: '**/*.spec.ts', + name: "component-tests", + testDir: path.resolve(__dirname, "../component-tests"), + testMatch: "**/*.spec.ts", }, ], }; diff --git a/tests/config/playwright.base.config.ts b/tests/config/playwright.base.config.ts index c6edb35a..d6e53e16 100644 --- a/tests/config/playwright.base.config.ts +++ b/tests/config/playwright.base.config.ts @@ -1,7 +1,7 @@ -import { defineConfig, PlaywrightTestConfig } from '@playwright/test'; -import 'dotenv/config'; +import { PlaywrightTestConfig, defineConfig } from "@playwright/test"; +import "dotenv/config"; -const baseUrl = process.env.NHSD_APIM_PROXY_URL || 'http://localhost:3000/'; +const baseUrl = process.env.NHSD_APIM_PROXY_URL || "http://localhost:3000/"; const envMaxInstances = Number.parseInt(process.env.WORKERS_MAX_INST!) || 10; /** * See https://playwright.dev/docs/test-configuration. diff --git a/tests/config/reporters.ts b/tests/config/reporters.ts index 94a68a63..27be1ac8 100644 --- a/tests/config/reporters.ts +++ b/tests/config/reporters.ts @@ -1,17 +1,17 @@ -import type { ReporterDescription } from '@playwright/test'; +import type { ReporterDescription } from "@playwright/test"; -const resultsDir = process.env.RESULTS_DIR || 'results'; -const reportsDir = process.env.REPORTS_DIR || 'reports'; +const resultsDir = process.env.RESULTS_DIR || "results"; +const reportsDir = process.env.REPORTS_DIR || "reports"; export function getReporters(allureFolder: string) { return [ [ - 'allure-playwright', + "allure-playwright", { outputFolder: `./target/reports/allure-results/${allureFolder}`, detail: false, suiteTitle: true, - open: 'always', + open: "always", environmentInfo: { E2E_NODE_VERSION: process.env.ENVIRONMENT, E2E_OS: process.platform, @@ -19,21 +19,21 @@ export function getReporters(allureFolder: string) { }, ], [ - 'html', + "html", { outputFolder: `../target/test-artifacts/${reportsDir}/html-report`, - open: process.env.CI ? 'never' : 'on-failure', + open: process.env.CI ? "never" : "on-failure", }, ], - ['list', { printSteps: true }], + ["list", { printSteps: true }], [ - 'junit', + "junit", { outputFile: `../target/test-artifacts/${resultsDir}/junit-results.xml`, }, ], [ - 'json', + "json", { outputFile: `../target/test-artifacts/${resultsDir}/json-results.json`, }, diff --git a/tests/config/sandbox.config.ts b/tests/config/sandbox.config.ts index c7295100..6f63788b 100644 --- a/tests/config/sandbox.config.ts +++ b/tests/config/sandbox.config.ts @@ -1,17 +1,17 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { config as baseConfig } from './playwright.base.config'; -import { getReporters } from './reporters'; -import path from 'path'; +import type { PlaywrightTestConfig } from "@playwright/test"; +import path from "node:path"; +import { config as baseConfig } from "./playwright.base.config"; +import { getReporters } from "./reporters"; const localConfig: PlaywrightTestConfig = { /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: getReporters('api-test'), + reporter: getReporters("api-test"), ...baseConfig, projects: [ { - name: 'sandbox', - testDir: path.resolve(__dirname, '../sandbox'), - testMatch: '*.spec.ts', + name: "sandbox", + testDir: path.resolve(__dirname, "../sandbox"), + testMatch: "*.spec.ts", }, ], }; diff --git a/tests/constants/api_constants.ts b/tests/constants/api_constants.ts index 53e1d703..f1b11e0c 100644 --- a/tests/constants/api_constants.ts +++ b/tests/constants/api_constants.ts @@ -1,8 +1,9 @@ -export const SUPPLIER_LETTERS = 'letters'; -export const SUPPLIER_API_URL_SANDBOX = 'https://internal-dev-sandbox.api.service.nhs.uk/nhs-notify-supplier'; -export const AWS_REGION = 'eu-west-2'; -export const envName = process.env.PR_NUMBER ?? 'main'; +export const SUPPLIER_LETTERS = "letters"; +export const SUPPLIER_API_URL_SANDBOX = + "https://internal-dev-sandbox.api.service.nhs.uk/nhs-notify-supplier"; +export const AWS_REGION = "eu-west-2"; +export const envName = process.env.PR_NUMBER ?? "main"; export const API_NAME = `nhs-${envName}-supapi`; export const LETTERSTABLENAME = `nhs-${envName}-supapi-letters`; -export const SUPPLIERID = 'TestSupplier1'; -export const MI_ENDPOINT = 'mi'; +export const SUPPLIERID = "TestSupplier1"; +export const MI_ENDPOINT = "mi"; diff --git a/tests/constants/request_headers.ts b/tests/constants/request_headers.ts index 5440f818..dc92d355 100644 --- a/tests/constants/request_headers.ts +++ b/tests/constants/request_headers.ts @@ -1,66 +1,66 @@ -import { randomUUID } from 'node:crypto'; -import { SUPPLIERID } from './api_constants'; +import { randomUUID } from "node:crypto"; +import { SUPPLIERID } from "./api_constants"; export const sandBoxHeader: RequestSandBoxHeaders = { - 'X-Request-ID': randomUUID(), - 'Content-Type': 'application/vnd.api+json', - 'X-Correlation-ID': randomUUID(), + "X-Request-ID": randomUUID(), + "Content-Type": "application/vnd.api+json", + "X-Correlation-ID": randomUUID(), }; export interface RequestHeaders { headerauth1: string; - 'NHSD-Supplier-ID': string; - 'NHSD-Correlation-ID': string; + "NHSD-Supplier-ID": string; + "NHSD-Correlation-ID": string; [key: string]: string; } export interface RequestSandBoxHeaders { - 'X-Request-ID': string; - 'Content-Type': string; - 'X-Correlation-ID': string; + "X-Request-ID": string; + "Content-Type": string; + "X-Correlation-ID": string; [key: string]: string; } export function createInvalidRequestHeaders(): RequestHeaders { let requestHeaders: RequestHeaders; - requestHeaders = { - headerauth1: '', - 'NHSD-Supplier-ID': SUPPLIERID, - 'NHSD-Correlation-ID': '1234', - 'X-Request-ID': 'requestId1' - }; + requestHeaders = { + headerauth1: "", + "NHSD-Supplier-ID": SUPPLIERID, + "NHSD-Correlation-ID": "1234", + "X-Request-ID": "requestId1", + }; return requestHeaders; } export function createHeaderWithNoCorrelationId(): RequestHeaders { let requestHeaders: RequestHeaders; - requestHeaders = { - headerauth1: process.env.HEADERAUTH || '', - 'NHSD-Supplier-ID': SUPPLIERID, - 'NHSD-Correlation-ID': '', - 'X-Request-ID': 'requestId1' - }; + requestHeaders = { + headerauth1: process.env.HEADERAUTH || "", + "NHSD-Supplier-ID": SUPPLIERID, + "NHSD-Correlation-ID": "", + "X-Request-ID": "requestId1", + }; return requestHeaders; } -export function createValidRequestHeaders(): RequestHeaders{ +export function createValidRequestHeaders(): RequestHeaders { let requestHeaders: RequestHeaders; - requestHeaders = { - headerauth1: process.env.HEADERAUTH || '', - 'NHSD-Supplier-ID': SUPPLIERID, - 'NHSD-Correlation-ID': '12345', - 'X-Request-ID': 'requestId1' - }; + requestHeaders = { + headerauth1: process.env.HEADERAUTH || "", + "NHSD-Supplier-ID": SUPPLIERID, + "NHSD-Correlation-ID": "12345", + "X-Request-ID": "requestId1", + }; return requestHeaders; } export function createHeaderWithNoRequestId(): RequestHeaders { let requestHeaders: RequestHeaders; - requestHeaders = { - headerauth1: process.env.HEADERAUTH || '', - 'NHSD-Supplier-ID': SUPPLIERID, - 'NHSD-Correlation-ID': '1234', - 'X-Request-ID': '' - }; + requestHeaders = { + headerauth1: process.env.HEADERAUTH || "", + "NHSD-Supplier-ID": SUPPLIERID, + "NHSD-Correlation-ID": "1234", + "X-Request-ID": "", + }; return requestHeaders; } diff --git a/tests/helpers/awsGatewayHelper.ts b/tests/helpers/awsGatewayHelper.ts index 9e0db8bb..31a590fb 100644 --- a/tests/helpers/awsGatewayHelper.ts +++ b/tests/helpers/awsGatewayHelper.ts @@ -1,8 +1,10 @@ -import { APIGatewayClient, GetRestApisCommand } from "@aws-sdk/client-api-gateway"; -import { AWS_REGION, API_NAME } from "../constants/api_constants"; +import { + APIGatewayClient, + GetRestApisCommand, +} from "@aws-sdk/client-api-gateway"; +import { API_NAME, AWS_REGION } from "../constants/api_constants"; export async function getRestApiGatewayBaseUrl(): Promise { - const region = AWS_REGION; const client = new APIGatewayClient({ region }); diff --git a/tests/helpers/commonTypes.ts b/tests/helpers/commonTypes.ts index c76ef4f7..139cd546 100644 --- a/tests/helpers/commonTypes.ts +++ b/tests/helpers/commonTypes.ts @@ -1,4 +1,4 @@ -import { error } from "console"; +import { error } from "node:console"; import { SUPPLIERID } from "../constants/api_constants"; export type ErrorLink = { @@ -18,107 +18,111 @@ export type ErrorMessageBody = { errors: ErrorResponse[]; }; -export function error404ResponseBody () : ErrorMessageBody{ +export function error404ResponseBody(): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: "12345", - code: "NOTIFY_LETTER_NOT_FOUND", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "404", - title: "Not found", - detail: "No resource found with that ID" - } - ] + { + id: "12345", + code: "NOTIFY_LETTER_NOT_FOUND", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "404", + title: "Not found", + detail: "No resource found with that ID", + }, + ], }; return responseBody; -}; +} -export function error500ResponseBody (id: string) : ErrorMessageBody{ +export function error500ResponseBody(id: string): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: "12345", - code: "NOTIFY_INTERNAL_SERVER_ERROR", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "500", - title: "Internal server error", - detail: `Letter with id ${id} not found for supplier ${SUPPLIERID}` - } - ] + { + id: "12345", + code: "NOTIFY_INTERNAL_SERVER_ERROR", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "500", + title: "Internal server error", + detail: `Letter with id ${id} not found for supplier ${SUPPLIERID}`, + }, + ], }; return responseBody; } - -export function error400ResponseBody () : ErrorMessageBody{ - +export function error400ResponseBody(): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: '12345', - code: "NOTIFY_INVALID_REQUEST", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "400", - title: "Invalid request", - detail: "The request body is invalid" - } - ] + { + id: "12345", + code: "NOTIFY_INVALID_REQUEST", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "400", + title: "Invalid request", + detail: "The request body is invalid", + }, + ], }; return responseBody; } -export function requestId500Error () : ErrorMessageBody{ +export function requestId500Error(): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: "1234", - code: "NOTIFY_INTERNAL_SERVER_ERROR", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "500", - title: "Internal server error", - detail: "The request headers don't contain the x-request-id" - } - ] + { + id: "1234", + code: "NOTIFY_INTERNAL_SERVER_ERROR", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "500", + title: "Internal server error", + detail: "The request headers don't contain the x-request-id", + }, + ], }; return responseBody; } -export function error403ResponseBody () : { Message: string }{ +export function error403ResponseBody(): { Message: string } { return { - Message : 'User is not authorized to access this resource with an explicit deny in an identity-based policy' + Message: + "User is not authorized to access this resource with an explicit deny in an identity-based policy", }; } -export function error400InvalidDate () : ErrorMessageBody{ - +export function error400InvalidDate(): ErrorMessageBody { let responseBody: ErrorMessageBody; responseBody = { errors: [ - { - id: '12345', - code: "NOTIFY_INVALID_REQUEST", - links: { - "about": "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" - }, - status: "400", - title: "Invalid request", - detail: "Timestamps should be UTC date/times in ISO8601 format, with a Z suffix" - } - ] + { + id: "12345", + code: "NOTIFY_INVALID_REQUEST", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "400", + title: "Invalid request", + detail: + "Timestamps should be UTC date/times in ISO8601 format, with a Z suffix", + }, + ], }; return responseBody; } diff --git a/tests/helpers/generate_fetch_testData.ts b/tests/helpers/generate_fetch_testData.ts index 2fd63aa6..ac2c3c9c 100644 --- a/tests/helpers/generate_fetch_testData.ts +++ b/tests/helpers/generate_fetch_testData.ts @@ -1,52 +1,62 @@ -import { envName, LETTERSTABLENAME, SUPPLIERID } from "../constants/api_constants"; +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { + DeleteCommand, + DynamoDBDocumentClient, + QueryCommand, +} from "@aws-sdk/lib-dynamodb"; +import { + LETTERSTABLENAME, + SUPPLIERID, + envName, +} from "../constants/api_constants"; import { runCreateLetter } from "./pnpmHelpers"; -import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; -import { DeleteCommand, DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb'; const ddb = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(ddb); export interface SupplierApiLetters { - supplierId: string, - specificationId: string, - supplierStatus: string, - createdAt: string, - supplierStatusSk: string, - updatedAt: string, - groupId: string, - reasonCode: string, - id: string, - url: string, - ttl: string, - reasonText: string, - status: string -}; + supplierId: string; + specificationId: string; + supplierStatus: string; + createdAt: string; + supplierStatusSk: string; + updatedAt: string; + groupId: string; + reasonCode: string; + id: string; + url: string; + ttl: string; + reasonText: string; + status: string; +} export async function createTestData(supplierId: string): Promise { - - await runCreateLetter({ - filter: 'nhs-notify-supplier-api-data-generator', - supplierId: supplierId, + await runCreateLetter({ + filter: "nhs-notify-supplier-api-data-generator", + supplierId, environment: envName, - awsAccountId: '820178564574', - groupId: 'TestGroupID', - specificationId: 'TestSpecificationID', - status: 'PENDING', + awsAccountId: "820178564574", + groupId: "TestGroupID", + specificationId: "TestSpecificationID", + status: "PENDING", count: 1, }); -}; - -export const getLettersBySupplier = async(supplierId: string, status: string, limit: number) => { +} - const supplierStatus = `${supplierId}#${status}`; - const params = { +export const getLettersBySupplier = async ( + supplierId: string, + status: string, + limit: number, +) => { + const supplierStatus = `${supplierId}#${status}`; + const params = { TableName: LETTERSTABLENAME, - IndexName: 'supplierStatus-index', - KeyConditionExpression: 'supplierStatus = :supplierStatus', + IndexName: "supplierStatus-index", + KeyConditionExpression: "supplierStatus = :supplierStatus", ProjectionExpression: - 'id, specificationId, groupId, reasonCode, reasonText', + "id, specificationId, groupId, reasonCode, reasonText", ExpressionAttributeValues: { - ':supplierStatus': supplierStatus, + ":supplierStatus": supplierStatus, }, Limit: limit, }; @@ -58,13 +68,13 @@ export const getLettersBySupplier = async(supplierId: string, status: string, li return Items as SupplierApiLetters[]; }; -export const deleteLettersBySupplier = async(id: string) => { +export const deleteLettersBySupplier = async (id: string) => { const resp = await docClient.send( new DeleteCommand({ TableName: LETTERSTABLENAME, Key: { supplierId: SUPPLIERID, id }, - ReturnValues: 'ALL_OLD', - }) - ) + ReturnValues: "ALL_OLD", + }), + ); return resp.Attributes; -} +}; diff --git a/tests/helpers/pnpmHelpers.ts b/tests/helpers/pnpmHelpers.ts index e0e748c0..552cbf9a 100644 --- a/tests/helpers/pnpmHelpers.ts +++ b/tests/helpers/pnpmHelpers.ts @@ -1,5 +1,5 @@ -import { spawn } from 'child_process'; -import path from 'path'; +import { spawn } from "node:child_process"; +import path from "node:path"; /** * Runs the "create-letter" CLI command via npm. @@ -17,60 +17,63 @@ export async function runCreateLetter(options: { count: number; }) { const { - filter, - supplierId, - environment, awsAccountId, + count, + environment, + filter, groupId, specificationId, status, - count, + supplierId, } = options; - const workspaceRoot = path.resolve(__dirname, '../../scripts/test-data'); - const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'; - const root = path.resolve(workspaceRoot); - console.log('Workspace root:', root); + const workspaceRoot = path.resolve(__dirname, "../../scripts/test-data"); + const cmd = process.platform === "win32" ? "npm.cmd" : "npm"; + const root = path.resolve(workspaceRoot); + console.log("Workspace root:", root); // Build arguments array const args = [ - '-w', String(filter), - // '--filter', String(filter), - 'run', - 'cli', - '--', - 'create-letter', - '--supplier-id', + "-w", + String(filter), + // '--filter', String(filter), + "run", + "cli", + "--", + "create-letter", + "--supplier-id", supplierId, - '--environment', + "--environment", environment, - '--awsAccountId', + "--awsAccountId", awsAccountId, - '--group-id', + "--group-id", groupId, - '--specification-id', + "--specification-id", specificationId, - '--status', + "--status", status, - '--count', + "--count", String(count), ]; - console.log('🚀 Running:', [cmd, ...args].join(' ')); + console.log("🚀 Running:", [cmd, ...args].join(" ")); await new Promise((resolve, reject) => { - let output = ''; + let output = ""; const child = spawn(cmd, args, { - stdio: 'inherit', + stdio: "inherit", cwd: root, shell: false, }); - child.stdout?.on('id', (id) => { + child.stdout?.on("id", (id) => { const text = id.toString(); output += text; process.stdout.write(text); }); - child.on('close', (code) => code === 0 ? resolve() : reject(new Error(`pnpm exited with ${code}`))); - child.on('error', reject); + child.on("close", (code) => + code === 0 ? resolve() : reject(new Error(`pnpm exited with ${code}`)), + ); + child.on("error", reject); }); } diff --git a/tests/helpers/validateJsonSchema.ts b/tests/helpers/validateJsonSchema.ts index e8e70cce..af017809 100644 --- a/tests/helpers/validateJsonSchema.ts +++ b/tests/helpers/validateJsonSchema.ts @@ -1,10 +1,12 @@ import OpenAPIResponseValidator from "openapi-response-validator"; -import path from 'path'; +import path from "node:path"; -const paths = path.resolve(__dirname, '../../build/notify-supplier.json'); +const paths = path.resolve(__dirname, "../../build/notify-supplier.json"); const openapiDoc = require(paths); -type ValidationResult = ReturnType; +type ValidationResult = ReturnType< + OpenAPIResponseValidator["validateResponse"] +>; /** * Validate a response against the OpenAPI spec for a given endpoint and method. * @@ -18,19 +20,23 @@ export function validateApiResponse( method: string, path: string, status: number, - body: any + body: any, ): ValidationResult { const pathItem = (openapiDoc.paths as Record)[path]; if (!pathItem) throw new Error(`Path ${path} not found in OpenAPI spec`); const operation = pathItem[method]; - if (!operation) throw new Error(`Method ${method.toUpperCase()} not defined for ${path}`); + if (!operation) + throw new Error(`Method ${method.toUpperCase()} not defined for ${path}`); // Find the response schema for the actual status code - const responseSchema = operation.responses[status] || operation.responses["default"]; + const responseSchema = + operation.responses[status] || operation.responses.default; if (!responseSchema) { - throw new Error(`No schema defined for status ${status} at ${method.toUpperCase()} ${path}`); + throw new Error( + `No schema defined for status ${status} at ${method.toUpperCase()} ${path}`, + ); } const validator = new OpenAPIResponseValidator({ diff --git a/tests/mtls/mtls_test.spec.ts b/tests/mtls/mtls_test.spec.ts index b0990efd..256b3c96 100644 --- a/tests/mtls/mtls_test.spec.ts +++ b/tests/mtls/mtls_test.spec.ts @@ -1,31 +1,29 @@ -import { test, expect, request, APIRequestContext } from '@playwright/test'; +import { APIRequestContext, expect, request, test } from "@playwright/test"; // Assume you have your constants in a config file -const PROXY_URL = process.env.PROXY_URL; - -test('should fail when connecting without client certificate', async () => { +const { PROXY_URL } = process.env; +test("should fail when connecting without client certificate", async () => { let apiContext: APIRequestContext | null = null; try { apiContext = await request.newContext(); const response = await apiContext.get(PROXY_URL!, { - headers: { "X-Client-Id": "hello" } + headers: { "X-Client-Id": "hello" }, }); // Check if request succeeded or failed if (response.ok()) { throw new Error( - `Expected connection failure, but got success with status ${response.status()}` + `Expected connection failure, but got success with status ${response.status()}`, ); } // Assert on the actual error code returned by the gateway // For mTLS, often 401, 403, or 502 depending on infra config expect(response.ok()).toBeFalsy(); - - } catch (err: any) { + } catch (error: any) { // If the request truly fails at the TLS layer, Playwright will throw instead - expect(err.message).toMatch(/SSL|certificate|ECONNRESET|socket/i); + expect(error.message).toMatch(/SSL|certificate|ECONNRESET|socket/i); } finally { if (apiContext) { await apiContext.dispose(); diff --git a/tests/sandbox/getLetterStatus.spec.ts b/tests/sandbox/getLetterStatus.spec.ts index 3d10845d..379d1431 100644 --- a/tests/sandbox/getLetterStatus.spec.ts +++ b/tests/sandbox/getLetterStatus.spec.ts @@ -1,21 +1,30 @@ -import { test, expect, request } from '@playwright/test'; -import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS} from '../constants/api_constants'; -import { apiSandboxGetLetterStatusTestData } from './testCases/getLetterStatus_testCases'; +import { expect, request, test } from "@playwright/test"; +import { + SUPPLIER_API_URL_SANDBOX, + SUPPLIER_LETTERS, +} from "../constants/api_constants"; +import { apiSandboxGetLetterStatusTestData } from "./testCases/getLetterStatus_testCases"; +test.describe("Sandbox Tests To Get Letter Status", () => { + for (const { + expectedResponse, + expectedStatus, + header, + id, + testCase, + } of apiSandboxGetLetterStatusTestData) { + test(`Get Letter Status endpoint returns ${testCase}`, async ({ + request, + }) => { + const response = await request.get( + `${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}/${id}`, + { + headers: header, + }, + ); -test.describe('Sandbox Tests To Get Letter Status', () => -{ - apiSandboxGetLetterStatusTestData.forEach(({ testCase, header, id, expectedStatus, expectedResponse }) => { - test(`Get Letter Status endpoint returns ${testCase}`, async ({ request }) => { - - const response = await request.get(`${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}/${id}` ,{ - headers: header - }, - ); - - const res = await response.json(); - expect(res).toEqual(expectedResponse); - + const res = await response.json(); + expect(res).toEqual(expectedResponse); }); - }); + } }); diff --git a/tests/sandbox/getListOfLetters.spec.ts b/tests/sandbox/getListOfLetters.spec.ts index e2bca376..012d9a38 100644 --- a/tests/sandbox/getListOfLetters.spec.ts +++ b/tests/sandbox/getListOfLetters.spec.ts @@ -1,27 +1,35 @@ -import { test, expect, request } from '@playwright/test'; -import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS} from '../constants/api_constants'; -import { apiSandboxGetLettersRequestTestData } from './testCases/getListOfLetters_testCases'; +import { expect, request, test } from "@playwright/test"; +import { + SUPPLIER_API_URL_SANDBOX, + SUPPLIER_LETTERS, +} from "../constants/api_constants"; +import { apiSandboxGetLettersRequestTestData } from "./testCases/getListOfLetters_testCases"; - -test.describe('Sandbox Tests To Get List Of Pending Letters ', () => -{ - apiSandboxGetLettersRequestTestData.forEach(({ testCase, header, limit, expectedStatus, expectedResponse }) => { +test.describe("Sandbox Tests To Get List Of Pending Letters ", () => { + for (const { + expectedResponse, + expectedStatus, + header, + limit, + testCase, + } of apiSandboxGetLettersRequestTestData) { test(`Get /Letters endpoint returns ${testCase}`, async ({ request }) => { - - const response = await request.get(`${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}` ,{ - headers: header, - params:{ - limit: limit - }, + const response = await request.get( + `${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}`, + { + headers: header, + params: { + limit, }, - ); + }, + ); const res = await response.json(); await expect(response.status()).toBe(expectedStatus); expect(res).toEqual(expectedResponse); - if (response.status() === 200){ + if (response.status() === 200) { expect(res.data.length.toString()).toEqual(limit); } }); - }); + } }); diff --git a/tests/sandbox/testCases/getLetterStatus_testCases.ts b/tests/sandbox/testCases/getLetterStatus_testCases.ts index 6e52bf4c..88125c43 100644 --- a/tests/sandbox/testCases/getLetterStatus_testCases.ts +++ b/tests/sandbox/testCases/getLetterStatus_testCases.ts @@ -1,137 +1,145 @@ import { randomUUID } from "node:crypto"; -import { RequestSandBoxHeaders, sandBoxHeader} from "../../constants/request_headers"; -import { NoRequestIdHeaders, SandboxErrorResponse, SandboxSuccessResponse } from "./getListOfLetters_testCases"; +import { + RequestSandBoxHeaders, + sandBoxHeader, +} from "../../constants/request_headers"; +import { + NoRequestIdHeaders, + SandboxErrorResponse, + SandboxSuccessResponse, +} from "./getListOfLetters_testCases"; type ApiSandboxGetLetterStatusTestCase = { testCase: string; - id: string, + id: string; header?: RequestSandBoxHeaders | NoRequestIdHeaders; expectedStatus: number; - expectedResponse?: GetLetterStatusResponse | GetLetterStatusErrorResponse | GetRejectedLetterResponse; + expectedResponse?: + | GetLetterStatusResponse + | GetLetterStatusErrorResponse + | GetRejectedLetterResponse; }; export type GetLetterStatusResponse = { - data: GetLetterData; + data: GetLetterData; }; export type GetRejectedLetterResponse = { - data: RejectedLetterData; + data: RejectedLetterData; }; -type GetLetterData = -{ - type: string; - id: string; - attributes: { - specificationId: string; - groupId: string; - status: string; - } +type GetLetterData = { + type: string; + id: string; + attributes: { + specificationId: string; + groupId: string; + status: string; + }; }; -type RejectedLetterData = -{ - type: string; - id: string; - attributes: { - specificationId: string; - groupId: string; - status: string; - reasonCode: string; - reasonText: string; - } +type RejectedLetterData = { + type: string; + id: string; + attributes: { + specificationId: string; + groupId: string; + status: string; + reasonCode: string; + reasonText: string; + }; }; export type GetLetterStatusErrorResponse = { - errors: ApiErrors[]; + errors: ApiErrors[]; }; type ApiErrors = { - code: string; - detail: string; - id: string; - links:{ - about: string; - }, - status: string; - title: string; + code: string; + detail: string; + id: string; + links: { + about: string; + }; + status: string; + title: string; }; -export const apiSandboxGetLetterStatusTestData: ApiSandboxGetLetterStatusTestCase[] = [ -{ - testCase: '200 response and ACCEPTED record is fetched successfully', - id: '2AL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - expectedStatus: 200, - expectedResponse: { - data: - { - id: '2AL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter', - attributes: { - specificationId: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - groupId: 'c5d93f917f5546d08beccf770a915d96', - status: 'ACCEPTED', - }, - } - } -}, -{ - testCase: '200 response and REJECTED record is fetched successfully', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - expectedStatus: 200, - expectedResponse: { - data: - { - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter', - attributes: { - specificationId: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - groupId: 'c5d93f917f5546d08beccf770a915d96', - status: 'REJECTED', - reasonCode: 'R01', - reasonText: "failed validation", - }, - } - } -}, -{ - testCase: '200 response and CANCELLED record is fetched successfully', - id: '2XL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - expectedStatus: 200, - expectedResponse: { - data: - { - id: '2XL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter', - attributes: { - specificationId: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - groupId: 'c5d93f917f5546d08beccf770a915d96', - status: 'CANCELLED', - reasonCode: 'R01' - }, - } - } -}, -{ - testCase: '404 response when no record is found for the given id', - id: '24L5eYSWGzCHlGmzNxuqVusP', - header: sandBoxHeader, - expectedStatus: 200, - expectedResponse: { +export const apiSandboxGetLetterStatusTestData: ApiSandboxGetLetterStatusTestCase[] = + [ + { + testCase: "200 response and ACCEPTED record is fetched successfully", + id: "2AL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + expectedStatus: 200, + expectedResponse: { + data: { + id: "2AL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + attributes: { + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + groupId: "c5d93f917f5546d08beccf770a915d96", + status: "ACCEPTED", + }, + }, + }, + }, + { + testCase: "200 response and REJECTED record is fetched successfully", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + expectedStatus: 200, + expectedResponse: { + data: { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + attributes: { + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + groupId: "c5d93f917f5546d08beccf770a915d96", + status: "REJECTED", + reasonCode: "R01", + reasonText: "failed validation", + }, + }, + }, + }, + { + testCase: "200 response and CANCELLED record is fetched successfully", + id: "2XL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + expectedStatus: 200, + expectedResponse: { + data: { + id: "2XL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + attributes: { + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + groupId: "c5d93f917f5546d08beccf770a915d96", + status: "CANCELLED", + reasonCode: "R01", + }, + }, + }, + }, + { + testCase: "404 response when no record is found for the given id", + id: "24L5eYSWGzCHlGmzNxuqVusP", + header: sandBoxHeader, + expectedStatus: 200, + expectedResponse: { errors: [ - { - status: '404', - title: 'Resource not found', - code:'NOTIFY_RESOURCE_NOT_FOUND', - detail: 'No resource found with that ID', - id: 'rrt-1931948104716186917-c-geu2-10664-3111479-3.0', - links: { - about: 'https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier' - } - } - ] - } -}]; + { + status: "404", + title: "Resource not found", + code: "NOTIFY_RESOURCE_NOT_FOUND", + detail: "No resource found with that ID", + id: "rrt-1931948104716186917-c-geu2-10664-3111479-3.0", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + }, + ], + }, + }, + ]; diff --git a/tests/sandbox/testCases/getListOfLetters_testCases.ts b/tests/sandbox/testCases/getListOfLetters_testCases.ts index 422786d0..8a4fd111 100644 --- a/tests/sandbox/testCases/getListOfLetters_testCases.ts +++ b/tests/sandbox/testCases/getListOfLetters_testCases.ts @@ -1,97 +1,101 @@ -import { RequestSandBoxHeaders, sandBoxHeader} from '../../constants/request_headers'; -import { randomUUID } from 'node:crypto'; - +import { randomUUID } from "node:crypto"; +import { + RequestSandBoxHeaders, + sandBoxHeader, +} from "../../constants/request_headers"; type ApiSandboxGetLettersRequestTestCase = { testCase: string; - limit: string, + limit: string; header?: RequestSandBoxHeaders | NoRequestIdHeaders; expectedStatus: number; expectedResponse?: SandboxSuccessResponse | SandboxErrorResponse; }; export type SandboxSuccessResponse = { - data: ApiData []; + data: ApiData[]; }; -type ApiData = -{ - type: string; - id: string; - attributes: { - specificationId: string; - groupId: string; - status: string; - } +type ApiData = { + type: string; + id: string; + attributes: { + specificationId: string; + groupId: string; + status: string; + }; }; export type SandboxErrorResponse = { - message: string; - errors: ApiErrors[]; + message: string; + errors: ApiErrors[]; }; type ApiErrors = { - path: string; - message: string; - errorCode: string; + path: string; + message: string; + errorCode: string; }; -export type NoRequestIdHeaders = Omit; +export type NoRequestIdHeaders = Omit; const NoRequestIdHeaders: NoRequestIdHeaders = { - 'Content-Type': 'application/vnd.api+json', - 'X-Correlation-ID': randomUUID(), + "Content-Type": "application/vnd.api+json", + "X-Correlation-ID": randomUUID(), }; -export const apiSandboxGetLettersRequestTestData: ApiSandboxGetLettersRequestTestCase[] = [ -{ - testCase: '200 response if record is fetched successfully', - limit: '1', - header: sandBoxHeader, - expectedStatus: 200, - expectedResponse: { +export const apiSandboxGetLettersRequestTestData: ApiSandboxGetLettersRequestTestCase[] = + [ + { + testCase: "200 response if record is fetched successfully", + limit: "1", + header: sandBoxHeader, + expectedStatus: 200, + expectedResponse: { data: [ - { - id: 'fcfd849ceec940e8832b41f4fc161e09', - type: 'Letter', + { + id: "fcfd849ceec940e8832b41f4fc161e09", + type: "Letter", attributes: { - specificationId: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - groupId: 'c5d93f917f5546d08beccf770a915d96', - status: 'PENDING', + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + groupId: "c5d93f917f5546d08beccf770a915d96", + status: "PENDING", }, - }] + }, + ], + }, }, -}, -{ - testCase: '400 response if invalid limit is passed', - limit: 'XX', - header: sandBoxHeader, - expectedStatus: 400, - expectedResponse: { - message: 'request.query.limit should be number', + { + testCase: "400 response if invalid limit is passed", + limit: "XX", + header: sandBoxHeader, + expectedStatus: 400, + expectedResponse: { + message: "request.query.limit should be number", errors: [ - { - path:'.query.limit', - message:'should be number', - errorCode:'type.openapi.validation' - } - ] - } -}, + { + path: ".query.limit", + message: "should be number", + errorCode: "type.openapi.validation", + }, + ], + }, + }, -{ - testCase: '400 response if invalid headers are passed', - limit: '2', - header: NoRequestIdHeaders, - expectedStatus: 400, - expectedResponse: { + { + testCase: "400 response if invalid headers are passed", + limit: "2", + header: NoRequestIdHeaders, + expectedStatus: 400, + expectedResponse: { message: "request.headers should have required property 'x-request-id'", errors: [ - { - path: '.headers.x-request-id', - message: "should have required property 'x-request-id'", - errorCode:'required.openapi.validation' - } - ] - } -}]; + { + path: ".headers.x-request-id", + message: "should have required property 'x-request-id'", + errorCode: "required.openapi.validation", + }, + ], + }, + }, + ]; diff --git a/tests/sandbox/testCases/updateLetterStatus_testCases.ts b/tests/sandbox/testCases/updateLetterStatus_testCases.ts index 1932aac2..3d67848e 100644 --- a/tests/sandbox/testCases/updateLetterStatus_testCases.ts +++ b/tests/sandbox/testCases/updateLetterStatus_testCases.ts @@ -1,123 +1,138 @@ - -import { PatchMessageRequestBody, PatchMessageResponseBody } from '../../component-tests/apiGateway-tests/testCases/updateLetterStatus'; -import { RequestSandBoxHeaders, sandBoxHeader } from '../../constants/request_headers'; -import { ErrorMessageBody } from '../../helpers/commonTypes'; -import { SandboxErrorResponse } from './getListOfLetters_testCases'; - +import { + PatchMessageRequestBody, + PatchMessageResponseBody, +} from "../../component-tests/apiGateway-tests/testCases/updateLetterStatus"; +import { + RequestSandBoxHeaders, + sandBoxHeader, +} from "../../constants/request_headers"; +import { ErrorMessageBody } from "../../helpers/commonTypes"; +import { SandboxErrorResponse } from "./getListOfLetters_testCases"; export type ApiSandboxUpdateLetterStatusTestData = { testCase: string; - id: string, + id: string; header: RequestSandBoxHeaders; body?: PatchMessageRequestBody; expectedStatus: number; - expectedResponse?: PatchMessageResponseBody | SandboxErrorResponse | ErrorMessageBody; + expectedResponse?: + | PatchMessageResponseBody + | SandboxErrorResponse + | ErrorMessageBody; }; -export const apiSandboxUpdateLetterStatusTestData: ApiSandboxUpdateLetterStatusTestData[] = [ - { - testCase: '200 response if record is updated with status PENDING', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - body: { - data: { - type: 'Letter', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - attributes: { - status: 'PENDING', +export const apiSandboxUpdateLetterStatusTestData: ApiSandboxUpdateLetterStatusTestData[] = + [ + { + testCase: "200 response if record is updated with status PENDING", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + body: { + data: { + type: "Letter", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + attributes: { + status: "PENDING", + }, }, - } - }, - expectedStatus: 200, - expectedResponse: { - data: { - type: 'Letter', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - attributes: { - status: 'PENDING', - specificationId:'2WL5eYSWGzCHlGmzNxuqVusPxDg', + }, + expectedStatus: 200, + expectedResponse: { + data: { + type: "Letter", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + attributes: { + status: "PENDING", + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + }, }, - } + }, }, - }, - { - testCase: '200 response if record is updated with status REJECTED', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - body: { - data: { - type: 'Letter', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - attributes: { - status: 'REJECTED', - reasonCode: 'R01', - reasonText: 'failed validation', + { + testCase: "200 response if record is updated with status REJECTED", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + body: { + data: { + type: "Letter", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + attributes: { + status: "REJECTED", + reasonCode: "R01", + reasonText: "failed validation", + }, }, - } - }, - expectedStatus: 200, - expectedResponse: { - data: { - type: 'Letter', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - attributes: { - reasonCode: 'R01', - reasonText: 'failed validation', - status: 'REJECTED', - specificationId:'2WL5eYSWGzCHlGmzNxuqVusPxDg', + }, + expectedStatus: 200, + expectedResponse: { + data: { + type: "Letter", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + attributes: { + reasonCode: "R01", + reasonText: "failed validation", + status: "REJECTED", + specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + }, }, - } + }, }, - }, - { - testCase: '404 response if no resource is found for the given id', - id: '0', - header: sandBoxHeader, - body: { - data: { - type: 'Letter', - id: '0', - attributes: { - status: 'PENDING', + { + testCase: "404 response if no resource is found for the given id", + id: "0", + header: sandBoxHeader, + body: { + data: { + type: "Letter", + id: "0", + attributes: { + status: "PENDING", + }, }, - } - }, - expectedStatus: 404, - expectedResponse: { - errors: [{ - id: 'rrt-1931948104716186917-c-geu2-10664-3111479-3.0', - code: 'NOTIFY_RESOURCE_NOT_FOUND', - links: { - about: "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier" + }, + expectedStatus: 404, + expectedResponse: { + errors: [ + { + id: "rrt-1931948104716186917-c-geu2-10664-3111479-3.0", + code: "NOTIFY_RESOURCE_NOT_FOUND", + links: { + about: + "https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier", + }, + status: "404", + title: "Resource not found", + detail: "No resource found with that ID", }, - status: '404', - title: 'Resource not found', - detail: 'No resource found with that ID' - }] + ], + }, }, - }, - { - testCase: '400 response if request body is invalid', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - header: sandBoxHeader, - body: { - data: { - type: 'Letter', - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - attributes: { - status: 'NO_STATUS', + { + testCase: "400 response if request body is invalid", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + header: sandBoxHeader, + body: { + data: { + type: "Letter", + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + attributes: { + status: "NO_STATUS", + }, }, - } - }, - expectedStatus: 400, - expectedResponse: { - message: 'request.body.data.attributes.status should be equal to one of the allowed values: PENDING, ACCEPTED, REJECTED, PRINTED, ENCLOSED, CANCELLED, DISPATCHED, DELIVERED, FAILED, RETURNED, FORWARDED', - errors: [{ - path: '.body.data.attributes.status', - message: 'should be equal to one of the allowed values: PENDING, ACCEPTED, REJECTED, PRINTED, ENCLOSED, CANCELLED, DISPATCHED, DELIVERED, FAILED, RETURNED, FORWARDED', - errorCode: 'enum.openapi.validation' - }] + }, + expectedStatus: 400, + expectedResponse: { + message: + "request.body.data.attributes.status should be equal to one of the allowed values: PENDING, ACCEPTED, REJECTED, PRINTED, ENCLOSED, CANCELLED, DISPATCHED, DELIVERED, FAILED, RETURNED, FORWARDED", + errors: [ + { + path: ".body.data.attributes.status", + message: + "should be equal to one of the allowed values: PENDING, ACCEPTED, REJECTED, PRINTED, ENCLOSED, CANCELLED, DISPATCHED, DELIVERED, FAILED, RETURNED, FORWARDED", + errorCode: "enum.openapi.validation", + }, + ], + }, }, - }, -]; + ]; diff --git a/tests/sandbox/testCases/updateMultipleStatus_testCases.ts b/tests/sandbox/testCases/updateMultipleStatus_testCases.ts index dd6fdc7b..99f476e4 100644 --- a/tests/sandbox/testCases/updateMultipleStatus_testCases.ts +++ b/tests/sandbox/testCases/updateMultipleStatus_testCases.ts @@ -1,4 +1,7 @@ -import { RequestSandBoxHeaders, sandBoxHeader } from "../../constants/request_headers"; +import { + RequestSandBoxHeaders, + sandBoxHeader, +} from "../../constants/request_headers"; export type ApiSandboxUpdateLetterStatusTestData = { testCase: string; @@ -8,118 +11,122 @@ export type ApiSandboxUpdateLetterStatusTestData = { }; type PostMessageRequestBody = { - data: postRequest [] -} + data: postRequest[]; +}; type postRequest = { - type: string; - id: string; - attributes: { - reasonCode?: string; - reasonText?: string; - status: string; - } + type: string; + id: string; + attributes: { + reasonCode?: string; + reasonText?: string; + status: string; + }; }; export const apiSandboxMultipleLetterStatusTestData: ApiSandboxUpdateLetterStatusTestData[] = -[{ - testCase: '200 response if records are updated', - header: sandBoxHeader, - body:{ - data : - [{ + [ + { + testCase: "200 response if records are updated", + header: sandBoxHeader, + body: { + data: [ + { + attributes: { + status: "PENDING", + }, + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - status: 'PENDING' + status: "ACCEPTED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - 'status': 'ACCEPTED' + status: "PRINTED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - status: 'PRINTED' + status: "ENCLOSED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { - attributes: { - status: 'ENCLOSED' - }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { - attributes: { - status: 'DISPATCHED' - }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - status: 'DELIVERED' + status: "DISPATCHED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - reasonCode: 'R01', - reasonText: 'failed validation', - status: 'RETURNED' + status: "DELIVERED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - reasonCode: 'R01', - reasonText: 'failed validation', - status: 'CANCELLED' + reasonCode: "R01", + reasonText: "failed validation", + status: "RETURNED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - reasonCode: 'R01', - reasonText: 'failed validation', - status: 'FAILED' + reasonCode: "R01", + reasonText: "failed validation", + status: "CANCELLED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - }, - { + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { attributes: { - reasonCode: 'R01', - reasonText: 'failed validation', - status: 'RETURNED' + reasonCode: "R01", + reasonText: "failed validation", + status: "FAILED", }, - id: '2WL5eYSWGzCHlGmzNxuqVusPxDg', - type: 'Letter' - } - ]}, - expectedStatus: 200 -}, -{ - testCase: '404 response if invalid request is passed', - header: sandBoxHeader, - body:{ - data : - [{ + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + { + attributes: { + reasonCode: "R01", + reasonText: "failed validation", + status: "RETURNED", + }, + id: "2WL5eYSWGzCHlGmzNxuqVusPxDg", + type: "Letter", + }, + ], + }, + expectedStatus: 200, + }, + { + testCase: "404 response if invalid request is passed", + header: sandBoxHeader, + body: { + data: [ + { attributes: { - status: 'PENDING' + status: "PENDING", }, - id: '1234', - type: 'Letter' - }] + id: "1234", + type: "Letter", + }, + ], + }, + expectedStatus: 404, }, - expectedStatus:404, -}]; + ]; diff --git a/tests/sandbox/updateLetterStatus.spec.ts b/tests/sandbox/updateLetterStatus.spec.ts index 9e0d9a4d..77bb99be 100644 --- a/tests/sandbox/updateLetterStatus.spec.ts +++ b/tests/sandbox/updateLetterStatus.spec.ts @@ -1,22 +1,31 @@ -import { test, expect, request } from '@playwright/test'; -import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS} from '../constants/api_constants'; -import { apiSandboxUpdateLetterStatusTestData } from './testCases/updateLetterStatus_testCases'; +import { expect, request, test } from "@playwright/test"; +import { + SUPPLIER_API_URL_SANDBOX, + SUPPLIER_LETTERS, +} from "../constants/api_constants"; +import { apiSandboxUpdateLetterStatusTestData } from "./testCases/updateLetterStatus_testCases"; - -test.describe('Sandbox Tests To Update Letter Status', () => -{ - apiSandboxUpdateLetterStatusTestData.forEach(({ testCase, header, id, body, expectedStatus, expectedResponse }) => { +test.describe("Sandbox Tests To Update Letter Status", () => { + for (const { + body, + expectedResponse, + expectedStatus, + header, + id, + testCase, + } of apiSandboxUpdateLetterStatusTestData) { test(`Patch /Letters endpoint returns ${testCase}`, async ({ request }) => { + const response = await request.patch( + `${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}/${id}`, + { + headers: header, + data: body, + }, + ); - const response = await request.patch(`${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}/${id}` ,{ - headers: header, - data: body - }); - - const res = await response.json(); - expect(response.status()).toBe(expectedStatus); - expect(res).toEqual(expectedResponse); - + const res = await response.json(); + expect(response.status()).toBe(expectedStatus); + expect(res).toEqual(expectedResponse); }); - }); + } }); diff --git a/tests/sandbox/updateMultipleLetterStatus.spec.ts b/tests/sandbox/updateMultipleLetterStatus.spec.ts index 524229bf..53071d92 100644 --- a/tests/sandbox/updateMultipleLetterStatus.spec.ts +++ b/tests/sandbox/updateMultipleLetterStatus.spec.ts @@ -1,18 +1,26 @@ -import { test, expect, request } from '@playwright/test'; -import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS} from '../constants/api_constants'; -import { apiSandboxMultipleLetterStatusTestData } from './testCases/updateMultipleStatus_testCases'; +import { expect, request, test } from "@playwright/test"; +import { + SUPPLIER_API_URL_SANDBOX, + SUPPLIER_LETTERS, +} from "../constants/api_constants"; +import { apiSandboxMultipleLetterStatusTestData } from "./testCases/updateMultipleStatus_testCases"; - -test.describe('Sandbox Tests To Update Multiple Letter Status', () => -{ - apiSandboxMultipleLetterStatusTestData.forEach(({ testCase, header, body, expectedStatus }) => { +test.describe("Sandbox Tests To Update Multiple Letter Status", () => { + for (const { + body, + expectedStatus, + header, + testCase, + } of apiSandboxMultipleLetterStatusTestData) { test(`Patch /Letters endpoint returns ${testCase}`, async ({ request }) => { - - const response = await request.post(`${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}` ,{ - headers: header, - data: body - }); - expect(response.status()).toBe(expectedStatus); + const response = await request.post( + `${SUPPLIER_API_URL_SANDBOX}/${SUPPLIER_LETTERS}`, + { + headers: header, + data: body, + }, + ); + expect(response.status()).toBe(expectedStatus); }); - }); + } }); From f7b6afaa825455435cb538516070d1c93b1e2c4b Mon Sep 17 00:00:00 2001 From: David Wass Date: Tue, 6 Jan 2026 15:56:39 +0000 Subject: [PATCH 15/15] tests - manual fixes --- .../{createMi.spec.ts => create-mi.spec.ts} | 12 ++++---- ...atus.spec.ts => get-letter-status.spec.ts} | 10 +++---- ...getLetters.spec.ts => get-letters.spec.ts} | 8 +++--- .../testCases/{createMi.ts => create-mi.ts} | 15 ++-------- ...etterStatus.ts => update-letter-status.ts} | 28 ++++++------------- ...s.spec.ts => update-letter-status.spec.ts} | 12 ++++---- tests/config/playwright.base.config.ts | 4 +-- .../{api_constants.ts => api-constants.ts} | 0 ...{request_headers.ts => request-headers.ts} | 18 ++++-------- ...GatewayHelper.ts => aws-gateway-helper.ts} | 2 +- .../{commonTypes.ts => common-types.ts} | 24 ++++------------ ...estData.ts => generate-fetch-test-data.ts} | 4 +-- .../{pnpmHelpers.ts => pnpm-helpers.ts} | 2 -- ...eJsonSchema.ts => validate-json-schema.ts} | 20 +++++++------ .../{mtls_test.spec.ts => mtls-test.spec.ts} | 0 ...atus.spec.ts => get-letter-status.spec.ts} | 7 ++--- ...rs.spec.ts => get-list-of-letters.spec.ts} | 6 ++-- ...ses.ts => get-letter-status-test-cases.ts} | 9 ++---- ...s.ts => get-list-of-letters-test-cases.ts} | 2 +- ....ts => update-letter-status-test-cases.ts} | 8 +++--- ...s => update-multiple-status-test-cases.ts} | 6 ++-- ...s.spec.ts => update-letter-status.spec.ts} | 6 ++-- ... => update-multiple-letter-status.spec.ts} | 6 ++-- 23 files changed, 81 insertions(+), 128 deletions(-) rename tests/component-tests/apiGateway-tests/{createMi.spec.ts => create-mi.spec.ts} (92%) rename tests/component-tests/apiGateway-tests/{getLetterStatus.spec.ts => get-letter-status.spec.ts} (90%) rename tests/component-tests/apiGateway-tests/{getLetters.spec.ts => get-letters.spec.ts} (92%) rename tests/component-tests/apiGateway-tests/testCases/{createMi.ts => create-mi.ts} (85%) rename tests/component-tests/apiGateway-tests/testCases/{updateLetterStatus.ts => update-letter-status.ts} (76%) rename tests/component-tests/apiGateway-tests/{updateLetterStatus.spec.ts => update-letter-status.spec.ts} (94%) rename tests/constants/{api_constants.ts => api-constants.ts} (100%) rename tests/constants/{request_headers.ts => request-headers.ts} (78%) rename tests/helpers/{awsGatewayHelper.ts => aws-gateway-helper.ts} (88%) rename tests/helpers/{commonTypes.ts => common-types.ts} (83%) rename tests/helpers/{generate_fetch_testData.ts => generate-fetch-test-data.ts} (95%) rename tests/helpers/{pnpmHelpers.ts => pnpm-helpers.ts} (97%) rename tests/helpers/{validateJsonSchema.ts => validate-json-schema.ts} (66%) rename tests/mtls/{mtls_test.spec.ts => mtls-test.spec.ts} (100%) rename tests/sandbox/{getLetterStatus.spec.ts => get-letter-status.spec.ts} (82%) rename tests/sandbox/{getListOfLetters.spec.ts => get-list-of-letters.spec.ts} (87%) rename tests/sandbox/testCases/{getLetterStatus_testCases.ts => get-letter-status-test-cases.ts} (94%) rename tests/sandbox/testCases/{getListOfLetters_testCases.ts => get-list-of-letters-test-cases.ts} (98%) rename tests/sandbox/testCases/{updateLetterStatus_testCases.ts => update-letter-status-test-cases.ts} (93%) rename tests/sandbox/testCases/{updateMultipleStatus_testCases.ts => update-multiple-status-test-cases.ts} (97%) rename tests/sandbox/{updateLetterStatus.spec.ts => update-letter-status.spec.ts} (85%) rename tests/sandbox/{updateMultipleLetterStatus.spec.ts => update-multiple-letter-status.spec.ts} (83%) diff --git a/tests/component-tests/apiGateway-tests/createMi.spec.ts b/tests/component-tests/apiGateway-tests/create-mi.spec.ts similarity index 92% rename from tests/component-tests/apiGateway-tests/createMi.spec.ts rename to tests/component-tests/apiGateway-tests/create-mi.spec.ts index 23464045..cef62679 100644 --- a/tests/component-tests/apiGateway-tests/createMi.spec.ts +++ b/tests/component-tests/apiGateway-tests/create-mi.spec.ts @@ -1,25 +1,23 @@ import { expect, test } from "@playwright/test"; -import { time } from "node:console"; -import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; -import { MI_ENDPOINT } from "../../constants/api_constants"; +import { getRestApiGatewayBaseUrl } from "../../helpers/aws-gateway-helper"; +import { MI_ENDPOINT } from "../../constants/api-constants"; import { createHeaderWithNoCorrelationId, createHeaderWithNoRequestId, createInvalidRequestHeaders, createValidRequestHeaders, -} from "../../constants/request_headers"; +} from "../../constants/request-headers"; import { miInvalidDateRequest, miInvalidRequest, miValidRequest, -} from "./testCases/createMi"; +} from "./testCases/create-mi"; import { error400InvalidDate, error400ResponseBody, error403ResponseBody, - error404ResponseBody, requestId500Error, -} from "../../helpers/commonTypes"; +} from "../../helpers/common-types"; let baseUrl: string; diff --git a/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts b/tests/component-tests/apiGateway-tests/get-letter-status.spec.ts similarity index 90% rename from tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts rename to tests/component-tests/apiGateway-tests/get-letter-status.spec.ts index 39d7e118..909f0573 100644 --- a/tests/component-tests/apiGateway-tests/getLetterStatus.spec.ts +++ b/tests/component-tests/apiGateway-tests/get-letter-status.spec.ts @@ -1,12 +1,12 @@ import { expect, test } from "@playwright/test"; -import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; -import { getLettersBySupplier } from "../../helpers/generate_fetch_testData"; -import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api_constants"; -import { createValidRequestHeaders } from "../../constants/request_headers"; +import { getRestApiGatewayBaseUrl } from "../../helpers/aws-gateway-helper"; +import { getLettersBySupplier } from "../../helpers/generate-fetch-test-data"; +import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api-constants"; +import { createValidRequestHeaders } from "../../constants/request-headers"; import { error404ResponseBody, error500ResponseBody, -} from "../../helpers/commonTypes"; +} from "../../helpers/common-types"; let baseUrl: string; diff --git a/tests/component-tests/apiGateway-tests/getLetters.spec.ts b/tests/component-tests/apiGateway-tests/get-letters.spec.ts similarity index 92% rename from tests/component-tests/apiGateway-tests/getLetters.spec.ts rename to tests/component-tests/apiGateway-tests/get-letters.spec.ts index 0a66a14e..2a094b17 100644 --- a/tests/component-tests/apiGateway-tests/getLetters.spec.ts +++ b/tests/component-tests/apiGateway-tests/get-letters.spec.ts @@ -1,12 +1,12 @@ import { expect, test } from "@playwright/test"; -import { SUPPLIER_LETTERS } from "../../constants/api_constants"; +import { SUPPLIER_LETTERS } from "../../constants/api-constants"; import { createHeaderWithNoCorrelationId, createInvalidRequestHeaders, createValidRequestHeaders, -} from "../../constants/request_headers"; -import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; -import { validateApiResponse } from "../../helpers/validateJsonSchema"; +} from "../../constants/request-headers"; +import { getRestApiGatewayBaseUrl } from "../../helpers/aws-gateway-helper"; +import { validateApiResponse } from "../../helpers/validate-json-schema"; let baseUrl: string; diff --git a/tests/component-tests/apiGateway-tests/testCases/createMi.ts b/tests/component-tests/apiGateway-tests/testCases/create-mi.ts similarity index 85% rename from tests/component-tests/apiGateway-tests/testCases/createMi.ts rename to tests/component-tests/apiGateway-tests/testCases/create-mi.ts index c9ba204a..e3f60db9 100644 --- a/tests/component-tests/apiGateway-tests/testCases/createMi.ts +++ b/tests/component-tests/apiGateway-tests/testCases/create-mi.ts @@ -13,9 +13,7 @@ export type MiRequestBody = { }; export function miValidRequest(): MiRequestBody { - let requestBody: MiRequestBody; - - requestBody = { + return { data: { attributes: { groupId: "group123", @@ -28,13 +26,10 @@ export function miValidRequest(): MiRequestBody { type: "ManagementInformation", }, }; - return requestBody; } export function miInvalidRequest(): MiRequestBody { - let requestBody: MiRequestBody; - - requestBody = { + return { data: { attributes: { groupId: "group123", @@ -47,13 +42,10 @@ export function miInvalidRequest(): MiRequestBody { type: "?", }, }; - return requestBody; } export function miInvalidDateRequest(): MiRequestBody { - let requestBody: MiRequestBody; - - requestBody = { + return { data: { attributes: { groupId: "group123", @@ -66,5 +58,4 @@ export function miInvalidDateRequest(): MiRequestBody { type: "ManagementInformation", }, }; - return requestBody; } diff --git a/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts b/tests/component-tests/apiGateway-tests/testCases/update-letter-status.ts similarity index 76% rename from tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts rename to tests/component-tests/apiGateway-tests/testCases/update-letter-status.ts index 0c7453e1..10a9184f 100644 --- a/tests/component-tests/apiGateway-tests/testCases/updateLetterStatus.ts +++ b/tests/component-tests/apiGateway-tests/testCases/update-letter-status.ts @@ -1,6 +1,6 @@ -import { RequestHeaders } from "../../../constants/request_headers"; -import { SUPPLIERID } from "../../../constants/api_constants"; -import { ErrorMessageBody } from "../../../helpers/commonTypes"; +import { RequestHeaders } from "../../../constants/request-headers"; +import { SUPPLIERID } from "../../../constants/api-constants"; +import { ErrorMessageBody } from "../../../helpers/common-types"; export type PatchMessageRequestBody = { data: { @@ -29,23 +29,19 @@ export type PatchMessageResponseBody = { }; export function patchRequestHeaders(): RequestHeaders { - let requestHeaders: RequestHeaders; - requestHeaders = { + return { headerauth1: process.env.HEADERAUTH || "", "NHSD-Supplier-ID": SUPPLIERID, "NHSD-Correlation-ID": "12344", "X-Request-ID": "requestId1", }; - return requestHeaders; } export function patchValidRequestBody( id: string, status: string, ): PatchMessageRequestBody { - let requestBody: PatchMessageRequestBody; - - requestBody = { + return { data: { attributes: { status, @@ -54,16 +50,13 @@ export function patchValidRequestBody( id, }, }; - return requestBody; } export function patchFailureRequestBody( id: string, status: string, ): PatchMessageRequestBody { - let requestBody: PatchMessageRequestBody; - - requestBody = { + return { data: { attributes: { status, @@ -74,12 +67,10 @@ export function patchFailureRequestBody( id, }, }; - return requestBody; } export function patch400ErrorResponseBody(): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12344", @@ -94,12 +85,10 @@ export function patch400ErrorResponseBody(): ErrorMessageBody { }, ], }; - return responseBody; } export function patch500ErrorResponseBody(id: string): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12344", @@ -114,5 +103,4 @@ export function patch500ErrorResponseBody(id: string): ErrorMessageBody { }, ], }; - return responseBody; } diff --git a/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts b/tests/component-tests/apiGateway-tests/update-letter-status.spec.ts similarity index 94% rename from tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts rename to tests/component-tests/apiGateway-tests/update-letter-status.spec.ts index c34bba47..74c03f21 100644 --- a/tests/component-tests/apiGateway-tests/updateLetterStatus.spec.ts +++ b/tests/component-tests/apiGateway-tests/update-letter-status.spec.ts @@ -1,21 +1,21 @@ import { expect, test } from "@playwright/test"; import { randomUUID } from "node:crypto"; -import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api_constants"; -import { getRestApiGatewayBaseUrl } from "../../helpers/awsGatewayHelper"; +import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api-constants"; +import { getRestApiGatewayBaseUrl } from "../../helpers/aws-gateway-helper"; import { patch400ErrorResponseBody, patch500ErrorResponseBody, patchFailureRequestBody, patchRequestHeaders, patchValidRequestBody, -} from "./testCases/updateLetterStatus"; +} from "./testCases/update-letter-status"; import { createTestData, deleteLettersBySupplier, getLettersBySupplier, -} from "../../helpers/generate_fetch_testData"; -import { createInvalidRequestHeaders } from "../../constants/request_headers"; -import { error403ResponseBody } from "../../helpers/commonTypes"; +} from "../../helpers/generate-fetch-test-data"; +import { createInvalidRequestHeaders } from "../../constants/request-headers"; +import { error403ResponseBody } from "../../helpers/common-types"; let baseUrl: string; diff --git a/tests/config/playwright.base.config.ts b/tests/config/playwright.base.config.ts index d6e53e16..12c9edf7 100644 --- a/tests/config/playwright.base.config.ts +++ b/tests/config/playwright.base.config.ts @@ -1,8 +1,8 @@ import { PlaywrightTestConfig, defineConfig } from "@playwright/test"; import "dotenv/config"; -const baseUrl = process.env.NHSD_APIM_PROXY_URL || "http://localhost:3000/"; -const envMaxInstances = Number.parseInt(process.env.WORKERS_MAX_INST!) || 10; +const envMaxInstances = + Number.parseInt(process.env.WORKERS_MAX_INST!, 10) || 10; /** * See https://playwright.dev/docs/test-configuration. */ diff --git a/tests/constants/api_constants.ts b/tests/constants/api-constants.ts similarity index 100% rename from tests/constants/api_constants.ts rename to tests/constants/api-constants.ts diff --git a/tests/constants/request_headers.ts b/tests/constants/request-headers.ts similarity index 78% rename from tests/constants/request_headers.ts rename to tests/constants/request-headers.ts index dc92d355..720b5db8 100644 --- a/tests/constants/request_headers.ts +++ b/tests/constants/request-headers.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import { SUPPLIERID } from "./api_constants"; +import { SUPPLIERID } from "./api-constants"; export const sandBoxHeader: RequestSandBoxHeaders = { "X-Request-ID": randomUUID(), @@ -22,45 +22,37 @@ export interface RequestSandBoxHeaders { } export function createInvalidRequestHeaders(): RequestHeaders { - let requestHeaders: RequestHeaders; - requestHeaders = { + return { headerauth1: "", "NHSD-Supplier-ID": SUPPLIERID, "NHSD-Correlation-ID": "1234", "X-Request-ID": "requestId1", }; - return requestHeaders; } export function createHeaderWithNoCorrelationId(): RequestHeaders { - let requestHeaders: RequestHeaders; - requestHeaders = { + return { headerauth1: process.env.HEADERAUTH || "", "NHSD-Supplier-ID": SUPPLIERID, "NHSD-Correlation-ID": "", "X-Request-ID": "requestId1", }; - return requestHeaders; } export function createValidRequestHeaders(): RequestHeaders { - let requestHeaders: RequestHeaders; - requestHeaders = { + return { headerauth1: process.env.HEADERAUTH || "", "NHSD-Supplier-ID": SUPPLIERID, "NHSD-Correlation-ID": "12345", "X-Request-ID": "requestId1", }; - return requestHeaders; } export function createHeaderWithNoRequestId(): RequestHeaders { - let requestHeaders: RequestHeaders; - requestHeaders = { + return { headerauth1: process.env.HEADERAUTH || "", "NHSD-Supplier-ID": SUPPLIERID, "NHSD-Correlation-ID": "1234", "X-Request-ID": "", }; - return requestHeaders; } diff --git a/tests/helpers/awsGatewayHelper.ts b/tests/helpers/aws-gateway-helper.ts similarity index 88% rename from tests/helpers/awsGatewayHelper.ts rename to tests/helpers/aws-gateway-helper.ts index 31a590fb..320a17bf 100644 --- a/tests/helpers/awsGatewayHelper.ts +++ b/tests/helpers/aws-gateway-helper.ts @@ -2,7 +2,7 @@ import { APIGatewayClient, GetRestApisCommand, } from "@aws-sdk/client-api-gateway"; -import { API_NAME, AWS_REGION } from "../constants/api_constants"; +import { API_NAME, AWS_REGION } from "../constants/api-constants"; export async function getRestApiGatewayBaseUrl(): Promise { const region = AWS_REGION; diff --git a/tests/helpers/commonTypes.ts b/tests/helpers/common-types.ts similarity index 83% rename from tests/helpers/commonTypes.ts rename to tests/helpers/common-types.ts index 139cd546..1f781002 100644 --- a/tests/helpers/commonTypes.ts +++ b/tests/helpers/common-types.ts @@ -1,5 +1,4 @@ -import { error } from "node:console"; -import { SUPPLIERID } from "../constants/api_constants"; +import { SUPPLIERID } from "../constants/api-constants"; export type ErrorLink = { about: string; @@ -19,8 +18,7 @@ export type ErrorMessageBody = { }; export function error404ResponseBody(): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12345", @@ -35,12 +33,10 @@ export function error404ResponseBody(): ErrorMessageBody { }, ], }; - return responseBody; } export function error500ResponseBody(id: string): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12345", @@ -55,12 +51,10 @@ export function error500ResponseBody(id: string): ErrorMessageBody { }, ], }; - return responseBody; } export function error400ResponseBody(): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12345", @@ -75,13 +69,10 @@ export function error400ResponseBody(): ErrorMessageBody { }, ], }; - return responseBody; } export function requestId500Error(): ErrorMessageBody { - let responseBody: ErrorMessageBody; - - responseBody = { + return { errors: [ { id: "1234", @@ -96,7 +87,6 @@ export function requestId500Error(): ErrorMessageBody { }, ], }; - return responseBody; } export function error403ResponseBody(): { Message: string } { @@ -107,8 +97,7 @@ export function error403ResponseBody(): { Message: string } { } export function error400InvalidDate(): ErrorMessageBody { - let responseBody: ErrorMessageBody; - responseBody = { + return { errors: [ { id: "12345", @@ -124,5 +113,4 @@ export function error400InvalidDate(): ErrorMessageBody { }, ], }; - return responseBody; } diff --git a/tests/helpers/generate_fetch_testData.ts b/tests/helpers/generate-fetch-test-data.ts similarity index 95% rename from tests/helpers/generate_fetch_testData.ts rename to tests/helpers/generate-fetch-test-data.ts index ac2c3c9c..0bbb1336 100644 --- a/tests/helpers/generate_fetch_testData.ts +++ b/tests/helpers/generate-fetch-test-data.ts @@ -8,8 +8,8 @@ import { LETTERSTABLENAME, SUPPLIERID, envName, -} from "../constants/api_constants"; -import { runCreateLetter } from "./pnpmHelpers"; +} from "../constants/api-constants"; +import { runCreateLetter } from "./pnpm-helpers"; const ddb = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(ddb); diff --git a/tests/helpers/pnpmHelpers.ts b/tests/helpers/pnpm-helpers.ts similarity index 97% rename from tests/helpers/pnpmHelpers.ts rename to tests/helpers/pnpm-helpers.ts index 552cbf9a..c423b4b8 100644 --- a/tests/helpers/pnpmHelpers.ts +++ b/tests/helpers/pnpm-helpers.ts @@ -59,7 +59,6 @@ export async function runCreateLetter(options: { console.log("🚀 Running:", [cmd, ...args].join(" ")); await new Promise((resolve, reject) => { - let output = ""; const child = spawn(cmd, args, { stdio: "inherit", cwd: root, @@ -67,7 +66,6 @@ export async function runCreateLetter(options: { }); child.stdout?.on("id", (id) => { const text = id.toString(); - output += text; process.stdout.write(text); }); diff --git a/tests/helpers/validateJsonSchema.ts b/tests/helpers/validate-json-schema.ts similarity index 66% rename from tests/helpers/validateJsonSchema.ts rename to tests/helpers/validate-json-schema.ts index af017809..cc509447 100644 --- a/tests/helpers/validateJsonSchema.ts +++ b/tests/helpers/validate-json-schema.ts @@ -1,8 +1,9 @@ import OpenAPIResponseValidator from "openapi-response-validator"; import path from "node:path"; +import fs from "node:fs"; -const paths = path.resolve(__dirname, "../../build/notify-supplier.json"); -const openapiDoc = require(paths); +const filePath = path.resolve(__dirname, "../../build/notify-supplier.json"); +const openapiDoc = JSON.parse(fs.readFileSync(filePath, "utf8")); type ValidationResult = ReturnType< OpenAPIResponseValidator["validateResponse"] @@ -11,31 +12,34 @@ type ValidationResult = ReturnType< * Validate a response against the OpenAPI spec for a given endpoint and method. * * @param method - HTTP method in lowercase ('get', 'post', etc.) - * @param path - API path (must match OpenAPI path exactly, e.g., '/items') + * @param responsePath - API path (must match OpenAPI path exactly, e.g., '/items') * @param status - HTTP status code returned by the API * @param body - Response body to validate * @returns ValidationResult or undefined if valid */ export function validateApiResponse( method: string, - path: string, + responsePath: string, status: number, body: any, ): ValidationResult { - const pathItem = (openapiDoc.paths as Record)[path]; + const pathItem = (openapiDoc.paths as Record)[responsePath]; - if (!pathItem) throw new Error(`Path ${path} not found in OpenAPI spec`); + if (!pathItem) + throw new Error(`Path ${responsePath} not found in OpenAPI spec`); const operation = pathItem[method]; if (!operation) - throw new Error(`Method ${method.toUpperCase()} not defined for ${path}`); + throw new Error( + `Method ${method.toUpperCase()} not defined for ${responsePath}`, + ); // Find the response schema for the actual status code const responseSchema = operation.responses[status] || operation.responses.default; if (!responseSchema) { throw new Error( - `No schema defined for status ${status} at ${method.toUpperCase()} ${path}`, + `No schema defined for status ${status} at ${method.toUpperCase()} ${responsePath}`, ); } diff --git a/tests/mtls/mtls_test.spec.ts b/tests/mtls/mtls-test.spec.ts similarity index 100% rename from tests/mtls/mtls_test.spec.ts rename to tests/mtls/mtls-test.spec.ts diff --git a/tests/sandbox/getLetterStatus.spec.ts b/tests/sandbox/get-letter-status.spec.ts similarity index 82% rename from tests/sandbox/getLetterStatus.spec.ts rename to tests/sandbox/get-letter-status.spec.ts index 379d1431..dd2af877 100644 --- a/tests/sandbox/getLetterStatus.spec.ts +++ b/tests/sandbox/get-letter-status.spec.ts @@ -1,14 +1,13 @@ -import { expect, request, test } from "@playwright/test"; +import { expect, test } from "@playwright/test"; import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS, -} from "../constants/api_constants"; -import { apiSandboxGetLetterStatusTestData } from "./testCases/getLetterStatus_testCases"; +} from "../constants/api-constants"; +import { apiSandboxGetLetterStatusTestData } from "./testCases/get-letter-status-test-cases"; test.describe("Sandbox Tests To Get Letter Status", () => { for (const { expectedResponse, - expectedStatus, header, id, testCase, diff --git a/tests/sandbox/getListOfLetters.spec.ts b/tests/sandbox/get-list-of-letters.spec.ts similarity index 87% rename from tests/sandbox/getListOfLetters.spec.ts rename to tests/sandbox/get-list-of-letters.spec.ts index 012d9a38..624a2227 100644 --- a/tests/sandbox/getListOfLetters.spec.ts +++ b/tests/sandbox/get-list-of-letters.spec.ts @@ -1,9 +1,9 @@ -import { expect, request, test } from "@playwright/test"; +import { expect, test } from "@playwright/test"; import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS, -} from "../constants/api_constants"; -import { apiSandboxGetLettersRequestTestData } from "./testCases/getListOfLetters_testCases"; +} from "../constants/api-constants"; +import { apiSandboxGetLettersRequestTestData } from "./testCases/get-list-of-letters-test-cases"; test.describe("Sandbox Tests To Get List Of Pending Letters ", () => { for (const { diff --git a/tests/sandbox/testCases/getLetterStatus_testCases.ts b/tests/sandbox/testCases/get-letter-status-test-cases.ts similarity index 94% rename from tests/sandbox/testCases/getLetterStatus_testCases.ts rename to tests/sandbox/testCases/get-letter-status-test-cases.ts index 88125c43..36c9c327 100644 --- a/tests/sandbox/testCases/getLetterStatus_testCases.ts +++ b/tests/sandbox/testCases/get-letter-status-test-cases.ts @@ -1,13 +1,8 @@ -import { randomUUID } from "node:crypto"; import { RequestSandBoxHeaders, sandBoxHeader, -} from "../../constants/request_headers"; -import { - NoRequestIdHeaders, - SandboxErrorResponse, - SandboxSuccessResponse, -} from "./getListOfLetters_testCases"; +} from "../../constants/request-headers"; +import { NoRequestIdHeaders } from "./get-list-of-letters-test-cases"; type ApiSandboxGetLetterStatusTestCase = { testCase: string; diff --git a/tests/sandbox/testCases/getListOfLetters_testCases.ts b/tests/sandbox/testCases/get-list-of-letters-test-cases.ts similarity index 98% rename from tests/sandbox/testCases/getListOfLetters_testCases.ts rename to tests/sandbox/testCases/get-list-of-letters-test-cases.ts index 8a4fd111..b41534b3 100644 --- a/tests/sandbox/testCases/getListOfLetters_testCases.ts +++ b/tests/sandbox/testCases/get-list-of-letters-test-cases.ts @@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto"; import { RequestSandBoxHeaders, sandBoxHeader, -} from "../../constants/request_headers"; +} from "../../constants/request-headers"; type ApiSandboxGetLettersRequestTestCase = { testCase: string; diff --git a/tests/sandbox/testCases/updateLetterStatus_testCases.ts b/tests/sandbox/testCases/update-letter-status-test-cases.ts similarity index 93% rename from tests/sandbox/testCases/updateLetterStatus_testCases.ts rename to tests/sandbox/testCases/update-letter-status-test-cases.ts index 3d67848e..aca61977 100644 --- a/tests/sandbox/testCases/updateLetterStatus_testCases.ts +++ b/tests/sandbox/testCases/update-letter-status-test-cases.ts @@ -1,13 +1,13 @@ import { PatchMessageRequestBody, PatchMessageResponseBody, -} from "../../component-tests/apiGateway-tests/testCases/updateLetterStatus"; +} from "../../component-tests/apiGateway-tests/testCases/update-letter-status"; import { RequestSandBoxHeaders, sandBoxHeader, -} from "../../constants/request_headers"; -import { ErrorMessageBody } from "../../helpers/commonTypes"; -import { SandboxErrorResponse } from "./getListOfLetters_testCases"; +} from "../../constants/request-headers"; +import { ErrorMessageBody } from "../../helpers/common-types"; +import { SandboxErrorResponse } from "./get-list-of-letters-test-cases"; export type ApiSandboxUpdateLetterStatusTestData = { testCase: string; diff --git a/tests/sandbox/testCases/updateMultipleStatus_testCases.ts b/tests/sandbox/testCases/update-multiple-status-test-cases.ts similarity index 97% rename from tests/sandbox/testCases/updateMultipleStatus_testCases.ts rename to tests/sandbox/testCases/update-multiple-status-test-cases.ts index 99f476e4..f9c8d5d9 100644 --- a/tests/sandbox/testCases/updateMultipleStatus_testCases.ts +++ b/tests/sandbox/testCases/update-multiple-status-test-cases.ts @@ -1,7 +1,7 @@ import { RequestSandBoxHeaders, sandBoxHeader, -} from "../../constants/request_headers"; +} from "../../constants/request-headers"; export type ApiSandboxUpdateLetterStatusTestData = { testCase: string; @@ -11,10 +11,10 @@ export type ApiSandboxUpdateLetterStatusTestData = { }; type PostMessageRequestBody = { - data: postRequest[]; + data: PostRequest[]; }; -type postRequest = { +type PostRequest = { type: string; id: string; attributes: { diff --git a/tests/sandbox/updateLetterStatus.spec.ts b/tests/sandbox/update-letter-status.spec.ts similarity index 85% rename from tests/sandbox/updateLetterStatus.spec.ts rename to tests/sandbox/update-letter-status.spec.ts index 77bb99be..dcd724fd 100644 --- a/tests/sandbox/updateLetterStatus.spec.ts +++ b/tests/sandbox/update-letter-status.spec.ts @@ -1,9 +1,9 @@ -import { expect, request, test } from "@playwright/test"; +import { expect, test } from "@playwright/test"; import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS, -} from "../constants/api_constants"; -import { apiSandboxUpdateLetterStatusTestData } from "./testCases/updateLetterStatus_testCases"; +} from "../constants/api-constants"; +import { apiSandboxUpdateLetterStatusTestData } from "./testCases/update-letter-status-test-cases"; test.describe("Sandbox Tests To Update Letter Status", () => { for (const { diff --git a/tests/sandbox/updateMultipleLetterStatus.spec.ts b/tests/sandbox/update-multiple-letter-status.spec.ts similarity index 83% rename from tests/sandbox/updateMultipleLetterStatus.spec.ts rename to tests/sandbox/update-multiple-letter-status.spec.ts index 53071d92..f7e30198 100644 --- a/tests/sandbox/updateMultipleLetterStatus.spec.ts +++ b/tests/sandbox/update-multiple-letter-status.spec.ts @@ -1,9 +1,9 @@ -import { expect, request, test } from "@playwright/test"; +import { expect, test } from "@playwright/test"; import { SUPPLIER_API_URL_SANDBOX, SUPPLIER_LETTERS, -} from "../constants/api_constants"; -import { apiSandboxMultipleLetterStatusTestData } from "./testCases/updateMultipleStatus_testCases"; +} from "../constants/api-constants"; +import { apiSandboxMultipleLetterStatusTestData } from "./testCases/update-multiple-status-test-cases"; test.describe("Sandbox Tests To Update Multiple Letter Status", () => { for (const {