Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15,601 changes: 7,024 additions & 8,577 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion scripts/utilities/letter-test-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ For creating multiple batches with different specification and group IDs, use th
--status PENDING
```

This script creates 3 batches with the following configurations:
This script creates 4 batches with the following configurations:

- Batch 1: `--specification-id integration-specification-english --group-id group-english`
- Batch 2: `--specification-id integration-specification-braille --group-id group-accessible`
- Batch 3: `--specification-id integration-specification-arabic --group-id group-international`
- Batch 4: `--specification-id integration-specification-missing-pdf --group-id group-error`

**Note:** The default configuration creates 2,505 letters total (835 letters × 3 batches) with an 18-month TTL.

Expand All @@ -57,5 +58,6 @@ This script creates 3 batches with the following configurations:
- `--environment` (required): Environment (e.g., pr147, main)
- `--awsAccountId` (required): AWS Account ID for S3 bucket resolution
- `--count` (optional): Number of letters per batch (default: 835)
- `--missing-count` (optional): Number of letters with missing PDFs (default: 5)
- `--status` (optional): Letter status (default: PENDING)
- `--ttl-hours` (optional): TTL in hours (default: 13140, ~18 months)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe("Create letter helpers", () => {
jest.resetAllMocks();
});

it("create letter", async () => {
it("create letter should create and upload a test letter", async () => {
jest.useFakeTimers();
jest.setSystemTime(new Date(2020, 1, 1));

Expand All @@ -27,6 +27,7 @@ describe("Create letter helpers", () => {
const groupId = "groupId";
const specificationId = "specificationId";
const status = "PENDING" as LetterStatusType;
const testLetter = "test-letter-standard";

await createLetter({
letterId,
Expand All @@ -37,12 +38,13 @@ describe("Create letter helpers", () => {
specificationId,
status,
letterRepository: mockedLetterRepository,
testLetter,
});

expect(mockedUploadFile).toHaveBeenCalledWith(
"bucketName",
"supplierId",
"../../test_letter.pdf",
"test-letter-standard.pdf",
"targetFilename",
);
expect(mockPutLetter).toHaveBeenCalledWith({
Expand All @@ -60,6 +62,54 @@ describe("Create letter helpers", () => {
});
});

it("should not upload a letter for none", async () => {
jest.useFakeTimers();
jest.setSystemTime(new Date(2020, 1, 1));

const mockPutLetter = jest.fn();
const mockedLetterRepository = {
putLetter: mockPutLetter,
} as any as LetterRepository;
const mockedUploadFile = uploadFile as jest.Mock;

const supplierId = "supplierId";
const letterId = "letterId";
const bucketName = "bucketName";
const targetFilename = "targetFilename";
const groupId = "groupId";
const specificationId = "specificationId";
const status = "PENDING" as LetterStatusType;
const testLetter = "none";

await createLetter({
letterId,
bucketName,
supplierId,
targetFilename,
groupId,
specificationId,
status,
letterRepository: mockedLetterRepository,
testLetter,
});

expect(mockedUploadFile).not.toHaveBeenCalled();

expect(mockPutLetter).toHaveBeenCalledWith({
createdAt: "2020-02-01T00:00:00.000Z",
groupId: "groupId",
id: "letterId",
specificationId: "specificationId",
status: "PENDING",
supplierId: "supplierId",
updatedAt: "2020-02-01T00:00:00.000Z",
url: "s3://bucketName/supplierId/targetFilename",
billingRef: "specificationId",
source: "/data-plane/letter-rendering/letter-test-data",
subject: "supplier-api/letter-test-data/letterId",
});
});

it("should create a letter DTO with correct fields", () => {
jest.useFakeTimers();
jest.setSystemTime(new Date(2020, 1, 1));
Expand Down
48 changes: 43 additions & 5 deletions scripts/utilities/letter-test-data/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ async function main() {
awsAccountId: {
type: "string",
demandOption: true,
choices: [
"820178564574", // Supplier Dev
"885964308133" //Supplier Nonprod
],
},
"letter-id": {
type: "string",
Expand Down Expand Up @@ -58,6 +62,15 @@ async function main() {
"DELIVERED",
],
},
"test-letter": {
type: "string",
demandOption: true,
choices: [
"test-letter-large",
"test-letter-standard",
"none", //none exists to specify letter without pdf for error testing scenarios
]
},
},
async (argv) => {
const supplierId = argv.supplierId;
Expand All @@ -72,6 +85,7 @@ async function main() {
const environment = argv.environment;
const ttlHours = argv.ttlHours;
const letterRepository = createLetterRepository(environment, ttlHours);
const testLetter = argv.testLetter;

createLetter({
letterId,
Expand All @@ -82,6 +96,7 @@ async function main() {
specificationId,
status: status as LetterStatusType,
letterRepository,
testLetter
});
},
)
Expand All @@ -100,6 +115,10 @@ async function main() {
awsAccountId: {
type: "string",
demandOption: true,
choices: [
"820178564574", // Supplier Dev
"885964308133" //Supplier Nonprod
],
},
"group-id": {
type: "string",
Expand Down Expand Up @@ -135,6 +154,15 @@ async function main() {
"DELIVERED",
],
},
"test-letter": {
type: "string",
demandOption: true,
choices: [
"test-letter-large",
"test-letter-standard",
"none", //none exists to specify letter without pdf for error testing scenarios
]
},
},
async (argv) => {

Expand All @@ -152,13 +180,23 @@ async function main() {
const ttlHours = argv.ttlHours;
const letterRepository = createLetterRepository(environment, ttlHours);
const count = argv.count;
const testLetter = argv.testLetter;


// Upload a test file for this batch
// Setup file attributes
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);
const folder = `${supplierId}/${batchId}`;
const url = `s3://${bucketName}/${folder}/${targetFilename}`;

// Upload a test file for this batch if it is not an 'none' batch
if(testLetter !== 'none') {
await uploadFile(
bucketName,
folder,
`${testLetter}.pdf`,
targetFilename,
);
}

// Create letter DTOs
let letterDtos = [];
Expand All @@ -176,7 +214,7 @@ async function main() {
// Upload Letters
await letterRepository.unsafePutLetterBatch(letterDtos);

console.log(`Created batch ${batchId} of ${letterDtos.length}`);
console.log(`Created batch ${batchId} of ${letterDtos.length} letters`);
},
)
.demandCommand(1)
Expand Down
32 changes: 24 additions & 8 deletions scripts/utilities/letter-test-data/src/create-batch-letters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ usage() {
echo ""
echo "Optional parameters:"
echo " --count Number of letters per batch (default: 835)"
echo " --missing-count Number of letters with missing PDFs (default: 5)"
echo " --status Letter status (default: PENDING)"
echo " --ttl-hours TTL in hours (default: 13140)"
echo ""
echo "Example:"
echo " $0 --supplier-id supplier-123 --environment pr147 --awsAccountId 820178564574"
echo " $0 --supplier-id supplier-123 --environment main --awsAccountId 820178564574 --count 25 --status ACCEPTED"
echo " $0 --supplier-id supplier-123 --environment main --awsAccountId 820178564574 --count 25 --status ACCEPTED --missing-count 3"
exit 1
}

# Default values
COUNT=835 #3 batches = 2505 letters
MISSING_COUNT=5 # Number of letters with missing PDFs
STATUS="PENDING"
TTL_HOURS=13140 # Approximately 18 months

Expand All @@ -49,6 +52,10 @@ while [[ $# -gt 0 ]]; do
COUNT="$2"
shift 2
;;
--missing-count)
MISSING_COUNT="$2"
shift 2
;;
--status)
STATUS="$2"
shift 2
Expand Down Expand Up @@ -87,11 +94,18 @@ if ! [[ "$COUNT" =~ ^[1-9][0-9]*$ ]]; then
exit 1
fi

# Validate missing count is a positive number
if ! [[ "$MISSING_COUNT" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: Missing count must be a positive integer"
exit 1
fi

echo "Creating letter batches with the following configuration:"
echo " Supplier ID: $SUPPLIER_ID"
echo " Environment: $ENVIRONMENT"
echo " AWS Account ID: $AWS_ACCOUNT_ID"
echo " Count per batch: $COUNT"
echo " Letters missing PDFs count: $MISSING_COUNT"
echo " Status: $STATUS"
echo " TTL Hours: $TTL_HOURS"
echo ""
Expand All @@ -103,11 +117,12 @@ PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# Change to the project directory
cd "$PROJECT_DIR"

# Define the three batches with different specification and group IDs
# Define the batches with different specification and group IDs
BATCHES=(
"integration-specification-english:group-english"
"integration-specification-braille:group-accessible"
"integration-specification-arabic:group-international"
"integration-specification-english:group-english:test-letter-standard:${COUNT}"
"integration-specification-braille:group-accessible:test-letter-standard:${COUNT}"
"integration-specification-arabic:group-international:test-letter-large:${COUNT}"
"integration-specification-missing-pdf:group-error:none:${MISSING_COUNT}"
)

# Counter for tracking batch creation
Expand All @@ -120,8 +135,8 @@ echo ""

# Create each batch
for batch in "${BATCHES[@]}"; do
# Parse specification-id and group-id from the batch definition
IFS=':' read -r SPEC_ID GROUP_ID <<< "$batch"
# Parse specification-id, group-id and batch volume from the batch definition
IFS=':' read -r SPEC_ID GROUP_ID TEST_LETTER BATCH_COUNT <<< "$batch"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and letter count in comment


echo "[$BATCH_COUNTER/$TOTAL_BATCHES] Creating batch with specification-id: $SPEC_ID, group-id: $GROUP_ID-$SUPPLIER_ID"

Expand All @@ -133,8 +148,9 @@ for batch in "${BATCHES[@]}"; do
--specification-id "$SPEC_ID" \
--group-id "$GROUP_ID-$SUPPLIER_ID" \
--status "$STATUS" \
--count "$COUNT" \
--ttl-hours "$TTL_HOURS"
--count "$BATCH_COUNT" \
--ttl-hours "$TTL_HOURS" \
--test-letter "$TEST_LETTER"

if [[ $? -eq 0 ]]; then
echo "✓ Batch $BATCH_COUNTER completed successfully"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export async function createLetter(params: {
groupId: string;
status: LetterStatusType;
letterRepository: LetterRepository;
testLetter: string;
}) {
const {
bucketName,
Expand All @@ -24,14 +25,17 @@ export async function createLetter(params: {
status,
supplierId,
targetFilename,
testLetter,
} = params;

await uploadFile(
bucketName,
supplierId,
"../../test_letter.pdf",
targetFilename,
);
if (testLetter !== "none") {
await uploadFile(
bucketName,
supplierId,
`${testLetter}.pdf`,
targetFilename,
);
}

const letter: Omit<Letter, "ttl" | "supplierStatus" | "supplierStatusSk"> = {
id: letterId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { readFileSync } from "fs";
import path from "path";


export async function uploadFile(bucketName: string, supplierId: string, sourceFilename: string, targetFilename: string) {
export async function uploadFile(bucketName: string, folder: string, sourceFilename: string, targetFilename: string) {
try {
const s3 = new S3Client();
const filePath = path.join(__dirname, sourceFilename);
const filePath = path.join(__dirname, '..', 'test-letters', sourceFilename);
const fileContent = readFileSync(filePath);

const uploadParams = {
Bucket: bucketName,
Key: `${supplierId}/${targetFilename}`,
Key: `${folder}/${targetFilename}`,
Body: fileContent,
ContentType: "application/pdf",
};
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
9 changes: 5 additions & 4 deletions tests/helpers/generate-fetch-test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface SupplierApiLetters {

export async function createTestData(
supplierId: string,
count?: number
count?: number,
): Promise<void> {
await runCreateLetter({
filter: "nhs-notify-supplier-api-letter-test-data-utility",
Expand All @@ -44,13 +44,14 @@ export async function createTestData(
specificationId: "TestSpecificationID",
status: "PENDING",
count: count || 1,
testLetter: "test-letter-standard",
});
}

export const getLettersBySupplier = async (
supplierId: string,
status: string,
limit: number
limit: number,
) => {
const supplierStatus = `${supplierId}#${status}`;
const params = {
Expand Down Expand Up @@ -78,13 +79,13 @@ export const deleteLettersBySupplier = async (id: string) => {
TableName: LETTERSTABLENAME,
Key: { supplierId: SUPPLIERID, id },
ReturnValues: "ALL_OLD",
})
}),
);
return resp.Attributes;
};

export async function checkSupplierExists(
supplierId: string
supplierId: string,
): Promise<boolean> {
try {
const params = {
Expand Down
Loading
Loading