Skip to content

Commit f713f1a

Browse files
CCM-15589: Write automation tests for urgent letter priority (#500)
* Refactor schemas and add test for letter priority * Fix rename * Bump internal events version * Fix rename again * Fix helper name * Add integration-tests to pw config * Change default variant map and refactor poll helper * try * add todo * check letter queue; fix lock file * fix lint * remove commented code * lint * peer review * phrasing * fix imports
1 parent cd571a2 commit f713f1a

21 files changed

Lines changed: 349 additions & 87 deletions

File tree

infrastructure/terraform/components/api/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ No requirements.
3737
| <a name="input_kms_deletion_window"></a> [kms\_deletion\_window](#input\_kms\_deletion\_window) | When a kms key is deleted, how long should it wait in the pending deletion state? | `string` | `"30"` | no |
3838
| <a name="input_letter_event_source"></a> [letter\_event\_source](#input\_letter\_event\_source) | Source value to use for the letter status event updates | `string` | `"/data-plane/supplier-api/nhs-supplier-api-prod/main/update-status"` | no |
3939
| <a name="input_letter_table_ttl_hours"></a> [letter\_table\_ttl\_hours](#input\_letter\_table\_ttl\_hours) | Number of hours to set as TTL on letters table | `number` | `24` | no |
40-
| <a name="input_letter_variant_map"></a> [letter\_variant\_map](#input\_letter\_variant\_map) | n/a | `map(object({ supplierId = string, specId = string, priority = number, billingId = string }))` | <pre>{<br/> "lv1": {<br/> "billingId": "billing1",<br/> "priority": 10,<br/> "specId": "spec1",<br/> "supplierId": "supplier1"<br/> },<br/> "lv2": {<br/> "billingId": "billing1",<br/> "priority": 10,<br/> "specId": "spec2",<br/> "supplierId": "supplier1"<br/> },<br/> "lv3": {<br/> "billingId": "billing1",<br/> "priority": 10,<br/> "specId": "spec3",<br/> "supplierId": "supplier2"<br/> }<br/>}</pre> | no |
40+
| <a name="input_letter_variant_map"></a> [letter\_variant\_map](#input\_letter\_variant\_map) | n/a | `map(object({ supplierId = string, specId = string, priority = number, billingId = string }))` | <pre>{<br/> "digitrials-aspiring": {<br/> "billingId": "digitrials-aspiring-billing",<br/> "priority": "0",<br/> "specId": "digitrials-aspiring",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-dmapp": {<br/> "billingId": "notify-admail-billing",<br/> "priority": "1",<br/> "specId": "notify-admail",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-globalminds": {<br/> "billingId": "digitrials-globalminds-billing",<br/> "priority": "2",<br/> "specId": "digitrials-globalminds",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-mymelanoma": {<br/> "billingId": "digitrials-mymelanoma-billing",<br/> "priority": "3",<br/> "specId": "digitrials-mymelanoma",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-ofh": {<br/> "billingId": "digitrials-ofh-billing",<br/> "priority": "4",<br/> "specId": "digitrials-ofh",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-prostateprogress": {<br/> "billingId": "digitrials-prostateprogress-billing",<br/> "priority": "5",<br/> "specId": "digitrials-prostateprogress",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-protectc": {<br/> "billingId": "notify-c5-colour-billing",<br/> "priority": "6",<br/> "specId": "notify-c5-colour",<br/> "supplierId": "supplier1"<br/> },<br/> "digitrials-restore": {<br/> "billingId": "digitrials-restore-billing",<br/> "priority": "7",<br/> "specId": "digitrials-restore",<br/> "supplierId": "supplier1"<br/> },<br/> "gpreg-admail": {<br/> "billingId": "notify-admail-billing",<br/> "priority": "8",<br/> "specId": "notify-admail",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-abnormal-results": {<br/> "billingId": "nces-abnormal-results-billing",<br/> "priority": "9",<br/> "specId": "nces-abnormal-results",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-abnormal-results-braille": {<br/> "billingId": "nces-abnormal-results-braille-billing",<br/> "priority": "10",<br/> "specId": "nces-abnormal-results-braille",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-invites": {<br/> "billingId": "nces-invites-billing",<br/> "priority": "10",<br/> "specId": "nces-invites",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-invites-braille": {<br/> "billingId": "nces-invites-braille-billing",<br/> "priority": "10",<br/> "specId": "nces-invites-braille",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-standard": {<br/> "billingId": "notify-c5-whitemail-billing",<br/> "priority": "11",<br/> "specId": "notify-c5-whitemail",<br/> "supplierId": "supplier1"<br/> },<br/> "nces-standard-braille": {<br/> "billingId": "notify-braille-whitemail-billing",<br/> "priority": "12",<br/> "specId": "notify-braille-whitemail",<br/> "supplierId": "supplier1"<br/> },<br/> "notify-braille": {<br/> "billingId": "notify-braille-billing",<br/> "priority": "13",<br/> "specId": "notify-braille",<br/> "supplierId": "supplier1"<br/> },<br/> "notify-digital-letters-standard": {<br/> "billingId": "notify-c5-billing",<br/> "priority": "97",<br/> "specId": "notify-c5",<br/> "supplierId": "supplier1"<br/> },<br/> "notify-standard": {<br/> "billingId": "notify-c5-billing",<br/> "priority": "98",<br/> "specId": "notify-c5",<br/> "supplierId": "supplier1"<br/> },<br/> "notify-standard-colour": {<br/> "billingId": "notify-c5-colour-billing",<br/> "priority": "99",<br/> "specId": "notify-c5-colour",<br/> "supplierId": "supplier1"<br/> }<br/>}</pre> | no |
4141
| <a name="input_log_level"></a> [log\_level](#input\_log\_level) | The log level to be used in lambda functions within the component. Any log with a lower severity than the configured value will not be logged: https://docs.python.org/3/library/logging.html#levels | `string` | `"INFO"` | no |
4242
| <a name="input_log_retention_in_days"></a> [log\_retention\_in\_days](#input\_log\_retention\_in\_days) | The retention period in days for the Cloudwatch Logs events to be retained, default of 0 is indefinite | `number` | `0` | no |
4343
| <a name="input_manually_configure_mtls_truststore"></a> [manually\_configure\_mtls\_truststore](#input\_manually\_configure\_mtls\_truststore) | Manually manage the truststore used for API Gateway mTLS (e.g. for prod environment) | `bool` | `false` | no |

infrastructure/terraform/components/api/variables.tf

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,25 @@ variable "eventpub_control_plane_bus_arn" {
138138
variable "letter_variant_map" {
139139
type = map(object({ supplierId = string, specId = string, priority = number, billingId = string }))
140140
default = {
141-
"lv1" = { supplierId = "supplier1", specId = "spec1", priority = 10, billingId = "billing1" },
142-
"lv2" = { supplierId = "supplier1", specId = "spec2", priority = 10, billingId = "billing1" },
143-
"lv3" = { supplierId = "supplier2", specId = "spec3", priority = 10, billingId = "billing1" }
141+
"digitrials-aspiring" = { supplierId = "supplier1", specId = "digitrials-aspiring", priority = "0", billingId = "digitrials-aspiring-billing" },
142+
"digitrials-dmapp" = { supplierId = "supplier1", specId = "notify-admail", priority = "1", billingId = "notify-admail-billing" },
143+
"digitrials-globalminds" = { supplierId = "supplier1", specId = "digitrials-globalminds", priority = "2", billingId = "digitrials-globalminds-billing" },
144+
"digitrials-mymelanoma" = { supplierId = "supplier1", specId = "digitrials-mymelanoma", priority = "3", billingId = "digitrials-mymelanoma-billing" },
145+
"digitrials-ofh" = { supplierId = "supplier1", specId = "digitrials-ofh", priority = "4", billingId = "digitrials-ofh-billing" },
146+
"digitrials-prostateprogress" = { supplierId = "supplier1", specId = "digitrials-prostateprogress", priority = "5", billingId = "digitrials-prostateprogress-billing" },
147+
"digitrials-protectc" = { supplierId = "supplier1", specId = "notify-c5-colour", priority = "6", billingId = "notify-c5-colour-billing" },
148+
"digitrials-restore" = { supplierId = "supplier1", specId = "digitrials-restore", priority = "7", billingId = "digitrials-restore-billing" },
149+
"gpreg-admail" = { supplierId = "supplier1", specId = "notify-admail", priority = "8", billingId = "notify-admail-billing" },
150+
"nces-abnormal-results" = { supplierId = "supplier1", specId = "nces-abnormal-results", priority = "9", billingId = "nces-abnormal-results-billing" },
151+
"nces-abnormal-results-braille" = { supplierId = "supplier1", specId = "nces-abnormal-results-braille", priority = "10", billingId = "nces-abnormal-results-braille-billing" },
152+
"nces-invites" = { supplierId = "supplier1", specId = "nces-invites", priority = "10", billingId = "nces-invites-billing" },
153+
"nces-invites-braille" = { supplierId = "supplier1", specId = "nces-invites-braille", priority = "10", billingId = "nces-invites-braille-billing" },
154+
"nces-standard" = { supplierId = "supplier1", specId = "notify-c5-whitemail", priority = "11", billingId = "notify-c5-whitemail-billing" },
155+
"nces-standard-braille" = { supplierId = "supplier1", specId = "notify-braille-whitemail", priority = "12", billingId = "notify-braille-whitemail-billing" },
156+
"notify-braille" = { supplierId = "supplier1", specId = "notify-braille", priority = "13", billingId = "notify-braille-billing" },
157+
"notify-digital-letters-standard" = { supplierId = "supplier1", specId = "notify-c5", priority = "97", billingId = "notify-c5-billing" },
158+
"notify-standard" = { supplierId = "supplier1", specId = "notify-c5", priority = "98", billingId = "notify-c5-billing" },
159+
"notify-standard-colour" = { supplierId = "supplier1", specId = "notify-c5-colour", priority = "99", billingId = "notify-c5-colour-billing" }
144160
}
145161
}
146162

internal/event-builders/src/__tests__/letter-mapper.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { $LetterEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src";
1+
import { $LetterStatusChangeEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src";
22
import { Letter } from "@internal/datastore";
33
import { mapLetterToCloudEvent } from "../letter-mapper";
44

@@ -22,7 +22,7 @@ describe("letter-mapper", () => {
2222
const event = mapLetterToCloudEvent(letter, source);
2323

2424
// Check it conforms to the letter event schema - parse will throw an error if not
25-
$LetterEvent.parse(event);
25+
$LetterStatusChangeEvent.parse(event);
2626
expect(event.type).toBe("uk.nhs.notify.supplier-api.letter.PRINTED.v1");
2727
expect(event.dataschema).toBe(
2828
`https://notify.nhs.uk/cloudevents/schemas/supplier-api/letter.PRINTED.${event.dataschemaversion}.schema.json`,

internal/event-builders/src/letter-mapper.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { randomBytes, randomUUID } from "node:crypto";
22
import eventSchemaPackage from "@nhsdigital/nhs-notify-event-schemas-supplier-api/package.json";
33
import { Letter } from "@internal/datastore";
4-
import { LetterEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
4+
import { LetterStatusChangeEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
55

66
// eslint-disable-next-line import-x/prefer-default-export
77
export function mapLetterToCloudEvent(
88
letter: Letter,
99
source: string,
10-
): LetterEvent {
10+
): LetterStatusChangeEvent {
1111
const eventId = randomUUID();
1212
const dataschemaversion = eventSchemaPackage.version;
1313
return {
@@ -21,7 +21,7 @@ export function mapLetterToCloudEvent(
2121
subject: `letter-origin/letter-rendering/letter/${letter.id}`,
2222

2323
data: {
24-
domainId: letter.id as LetterEvent["data"]["domainId"],
24+
domainId: letter.id as LetterStatusChangeEvent["data"]["domainId"],
2525
status: letter.status,
2626
specificationId: letter.specificationId,
2727
billingRef: letter.billingRef,

internal/events/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@
3636
"typecheck": "tsc --noEmit"
3737
},
3838
"types": "dist/index.d.ts",
39-
"version": "1.0.17"
39+
"version": "1.0.18"
4040
}

internal/events/src/cli/generate-json.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { z } from "zod";
22
import * as fs from "node:fs";
33
import { $Letter } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/domain/letter";
44
import {
5-
$LetterEvent,
5+
$LetterStatusChangeEvent,
66
letterEventMap,
77
} from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
88
import { $MISubmittedEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/mi-events";
@@ -36,7 +36,7 @@ for (const [key, schema] of Object.entries(letterEventMap)) {
3636
}
3737

3838
// Generic letter status change event schema
39-
const json = z.toJSONSchema($LetterEvent, {
39+
const json = z.toJSONSchema($LetterStatusChangeEvent, {
4040
io: "input",
4141
target: "openapi-3.0",
4242
reused: "ref",

internal/events/src/events/letter-events.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { EventEnvelope } from "@nhsdigital/nhs-notify-event-schemas-supplier-api
99
/**
1010
* A generic schema for parsing any letter status change event
1111
*/
12-
export const $LetterEvent = EventEnvelope(
12+
export const $LetterStatusChangeEvent = EventEnvelope(
1313
"letter",
1414
"letter",
1515
$Letter,
@@ -19,7 +19,7 @@ export const $LetterEvent = EventEnvelope(
1919
title: `letter.* Event`,
2020
description: `Event schema for generic letter status change`,
2121
});
22-
export type LetterEvent = z.infer<typeof $LetterEvent>;
22+
export type LetterStatusChangeEvent = z.infer<typeof $LetterStatusChangeEvent>;
2323

2424
/**
2525
* Specialise the generic event schema for a single status

lambdas/api-handler/src/handlers/amendment-event-transformer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SQSBatchItemFailure, SQSEvent, SQSHandler } from "aws-lambda";
22
import { PublishCommand } from "@aws-sdk/client-sns";
3-
import { LetterEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
3+
import { LetterStatusChangeEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
44
import { MetricEntry, MetricStatus, buildEMFObject } from "@internal/helpers";
55
import { mapLetterToCloudEvent } from "@internal/event-builders/src";
66
import { Unit } from "aws-embedded-metrics";
@@ -66,7 +66,7 @@ export default function createTransformAmendmentEventHandler(
6666
}
6767

6868
function buildSnsCommand(
69-
letterEvent: LetterEvent,
69+
letterEvent: LetterStatusChangeEvent,
7070
topicArn: string,
7171
): PublishCommand {
7272
return new PublishCommand({

lambdas/letter-updates-transformer/src/letter-updates-transformer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
PublishBatchCommand,
1010
PublishBatchRequestEntry,
1111
} from "@aws-sdk/client-sns";
12-
import { LetterEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src";
12+
import { LetterStatusChangeEvent } from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src";
1313
import { MetricEntry, buildEMFObject } from "@internal/helpers";
1414
import { Letter, LetterSchema } from "@internal/datastore";
1515
import { mapLetterToCloudEvent } from "@internal/event-builders/src";
@@ -33,7 +33,7 @@ export default function createHandler(deps: Deps): Handler<KinesisStreamEvent> {
3333
extractPayload(record, deps),
3434
);
3535

36-
const cloudEvents: LetterEvent[] = ddbRecords
36+
const cloudEvents: LetterStatusChangeEvent[] = ddbRecords
3737
.filter((record) => filterRecord(record, deps))
3838
.map((element) => extractNewLetter(element))
3939
.map((element) => mapLetterToCloudEvent(element, deps.env.EVENT_SOURCE));
@@ -59,7 +59,7 @@ export default function createHandler(deps: Deps): Handler<KinesisStreamEvent> {
5959
};
6060
}
6161

62-
function populateEventTypeMap(cloudEvents: LetterEvent[]) {
62+
function populateEventTypeMap(cloudEvents: LetterStatusChangeEvent[]) {
6363
const evtMap = new Map<string, number>();
6464
for (const event of cloudEvents) {
6565
evtMap.set(event.type, (evtMap.get(event.type) || 0) + 1);
@@ -142,14 +142,14 @@ function extractNewLetter(record: DynamoDBRecord): Letter {
142142
return LetterSchema.parse(unmarshall(newImage as any));
143143
}
144144

145-
function* generateBatches(events: LetterEvent[]) {
145+
function* generateBatches(events: LetterStatusChangeEvent[]) {
146146
for (let i = 0; i < events.length; i += BATCH_SIZE) {
147147
yield events.slice(i, i + BATCH_SIZE);
148148
}
149149
}
150150

151151
function buildMessage(
152-
event: LetterEvent,
152+
event: LetterStatusChangeEvent,
153153
index: number,
154154
): PublishBatchRequestEntry {
155155
return {

lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";
44
import { LetterRequestPreparedEventV2 } from "@nhsdigital/nhs-notify-event-schemas-letter-rendering";
55
import { LetterRequestPreparedEvent } from "@nhsdigital/nhs-notify-event-schemas-letter-rendering-v1";
66
import {
7-
$LetterEvent,
8-
LetterEvent,
7+
$LetterStatusChangeEvent,
8+
LetterStatusChangeEvent,
99
} from "@nhsdigital/nhs-notify-event-schemas-supplier-api/src/events/letter-events";
1010
import { SupplierConfigRepository } from "@internal/datastore";
1111
import createSupplierAllocatorHandler from "../allocate-handler";
@@ -99,10 +99,10 @@ function createPreparedV2Event(
9999

100100
function createSupplierStatusChangeEvent(
101101
overrides: Partial<any> = {},
102-
): LetterEvent {
102+
): LetterStatusChangeEvent {
103103
const now = new Date().toISOString();
104104

105-
return $LetterEvent.parse({
105+
return $LetterStatusChangeEvent.parse({
106106
data: {
107107
domainId: overrides.domainId ?? "f47ac10b-58cc-4372-a567-0e02b2c3d479",
108108
groupId: "client_template",

0 commit comments

Comments
 (0)