Skip to content

Commit aa079df

Browse files
peer review
1 parent 2bc0cc8 commit aa079df

3 files changed

Lines changed: 127 additions & 100 deletions

File tree

Lines changed: 11 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,14 @@
1-
import { expect, test } from "@playwright/test";
2-
import { sendSnsEvent } from "tests/helpers/send-sns-event";
3-
import { createPreparedV1Event } from "tests/helpers/event-fixtures";
4-
import { randomUUID } from "node:crypto";
5-
import { logger } from "tests/helpers/pino-logger";
1+
import { test } from "@playwright/test";
62
import getRestApiGatewayBaseUrl from "tests/helpers/aws-gateway-helper";
73
import { pollForLetterStatus } from "tests/helpers/poll-for-letters-helper";
8-
import { pollSupplierAllocatorLogForResolvedSpec } from "tests/helpers/aws-cloudwatch-helper";
94
import { getLettersFromQueueViaIndex } from "tests/helpers/generate-fetch-test-data";
105
import {
11-
AllocatedLetter,
12-
AllocatedLetterSchema,
13-
} from "../../../lambdas/upsert-letter/src/handler/schemas";
14-
15-
// Values for CI/CD are kept in group_nhs-notify-supplier-api-dev.tfvars in the nhs-notify-internal repo
16-
// If running locally see default of variant_map in infrastructure/terraform/components/api/variables.tf
17-
const variantUrgencyMap: Record<string, number> = {
18-
"digitrials-aspiring": 0,
19-
"digitrials-dmapp": 1,
20-
"digitrials-globalminds": 2,
21-
"digitrials-mymelanoma": 3,
22-
"digitrials-ofh": 4,
23-
"digitrials-prostateprogress": 5,
24-
"digitrials-protectc": 6,
25-
"digitrials-restore": 7,
26-
"gpreg-admail": 8,
27-
"nces-abnormal-results": 9,
28-
"nces-abnormal-results-braille": 10,
29-
"nces-invites": 10,
30-
"nces-invites-braille": 10,
31-
"nces-standard": 11,
32-
"nces-standard-braille": 12,
33-
"notify-braille": 13,
34-
"notify-digital-letters-standard": 97,
35-
"notify-standard": 98,
36-
"notify-standard-colour": 99,
37-
};
38-
const supplier = "supplier1";
6+
getVariantsWithUrgency,
7+
sendEventsForVariants,
8+
supplier,
9+
verifyAllocationLogsContainPriority,
10+
verifyIndexPositionOfLetterVariants,
11+
} from "tests/helpers/urgent-letter-priority-helper";
3912

4013
let baseUrl: string;
4114

@@ -47,11 +20,12 @@ test.describe("Urgent Letter Priority Tests", () => {
4720
test.setTimeout(180_000); // 3 minutes for long running polling
4821

4922
test("Letter with higher urgency gets picked first", async ({ request }) => {
23+
const variantsUrgencyTen = getVariantsWithUrgency(10);
24+
const urgencyTenLetterIds = await sendEventsForVariants(variantsUrgencyTen);
25+
5026
const variantsUrgencyNine = getVariantsWithUrgency(9);
5127
const urgencyNineLetterIds =
5228
await sendEventsForVariants(variantsUrgencyNine);
53-
const variantsUrgencyTen = getVariantsWithUrgency(10);
54-
const urgencyTenLetterIds = await sendEventsForVariants(variantsUrgencyTen);
5529

5630
await Promise.all(
5731
[...urgencyNineLetterIds, ...urgencyTenLetterIds].map(async (domainId) =>
@@ -69,71 +43,8 @@ test.describe("Urgent Letter Priority Tests", () => {
6943

7044
verifyIndexPositionOfLetterVariants(
7145
letterIdsFromQueue,
72-
urgencyNineLetterIds,
7346
urgencyTenLetterIds,
47+
urgencyNineLetterIds,
7448
);
7549
});
7650
});
77-
78-
function getVariantsWithUrgency(urgency: number) {
79-
const variants = Object.keys(variantUrgencyMap).filter(
80-
// safe has comes from map's keys which are controlled by us
81-
// eslint-disable-next-line security/detect-object-injection
82-
(variant) => variantUrgencyMap[variant] === urgency,
83-
);
84-
if (variants.length === 0) {
85-
throw new Error(`No variants found with urgency ${urgency}`);
86-
}
87-
return variants;
88-
}
89-
90-
async function sendEventsForVariants(variants: string[]) {
91-
const domainIds: string[] = [];
92-
for (const variant of variants) {
93-
const domainId = randomUUID();
94-
logger.info(
95-
`Testing event subscription with domainId: ${domainId} and variant: ${variant}`,
96-
);
97-
const preparedEvent = createPreparedV1Event({
98-
domainId,
99-
letterVariantId: variant,
100-
});
101-
const response = await sendSnsEvent(preparedEvent);
102-
expect(response.MessageId).toBeTruthy();
103-
domainIds.push(domainId);
104-
}
105-
return domainIds;
106-
}
107-
108-
function verifyIndexPositionOfLetterVariants(
109-
letterIds: string[],
110-
letterIdsLeastUrgency: string[],
111-
letterIdsHigherUrgency: string[],
112-
) {
113-
for (const leastUrgencyLetterId of letterIdsLeastUrgency) {
114-
expect(letterIds).toContain(leastUrgencyLetterId); // in case limit param is hit
115-
const indexToTest = letterIds.indexOf(leastUrgencyLetterId);
116-
for (const higherUrgencyLetterId of letterIdsHigherUrgency) {
117-
expect(letterIds).toContain(higherUrgencyLetterId); // in case limit param is hit
118-
const higherUrgencyIndex = letterIds.indexOf(higherUrgencyLetterId);
119-
expect(indexToTest).toBeLessThan(higherUrgencyIndex); // higher urgency letters should come before lower urgency letters
120-
}
121-
}
122-
}
123-
124-
async function verifyAllocationLogsContainPriority(
125-
letterIds: string[],
126-
priority: number,
127-
) {
128-
for (const domainId of letterIds) {
129-
const message = await pollSupplierAllocatorLogForResolvedSpec(domainId);
130-
const supplierAllocatorLog = JSON.parse(message);
131-
const allocatedLetter: AllocatedLetter = AllocatedLetterSchema.parse(
132-
supplierAllocatorLog.msg,
133-
);
134-
const { supplierSpec } = allocatedLetter;
135-
expect(supplierSpec).toBeDefined();
136-
expect(supplierSpec.priority).toBeDefined();
137-
expect(supplierSpec.priority).toBe(priority);
138-
}
139-
}

tests/helpers/generate-fetch-test-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ export async function getLettersFromQueueViaIndex(
247247
`Queried letter queue table to verify existence for supplier ${supplierId} and found items.`,
248248
);
249249

250+
// assumes no pagination needed as we expect a small number of letters in the queue for the test supplier
250251
return z.array(PendingLetterSchema).parse(Items);
251252
}
252253
if (attempt < MAX_ATTEMPTS) {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import {
2+
AllocatedLetter,
3+
AllocatedLetterSchema,
4+
} from "lambdas/upsert-letter/src/handler/schemas";
5+
import { randomUUID } from "node:crypto";
6+
import { expect } from "playwright/test";
7+
import { pollSupplierAllocatorLogForResolvedSpec } from "./aws-cloudwatch-helper";
8+
import { createPreparedV1Event } from "./event-fixtures";
9+
import { logger } from "./pino-logger";
10+
import { sendSnsEvent } from "./send-sns-event";
11+
12+
// Values for CI/CD are kept in group_nhs-notify-supplier-api-dev.tfvars in the nhs-notify-internal repo
13+
// If running locally see default of variant_map in infrastructure/terraform/components/api/variables.tf
14+
export const variantUrgencyMap: Record<string, number> = {
15+
"digitrials-aspiring": 0,
16+
"digitrials-dmapp": 1,
17+
"digitrials-globalminds": 2,
18+
"digitrials-mymelanoma": 3,
19+
"digitrials-ofh": 4,
20+
"digitrials-prostateprogress": 5,
21+
"digitrials-protectc": 6,
22+
"digitrials-restore": 7,
23+
"gpreg-admail": 8,
24+
"nces-abnormal-results": 9,
25+
"nces-abnormal-results-braille": 10,
26+
"nces-invites": 10,
27+
"nces-invites-braille": 10,
28+
"nces-standard": 11,
29+
"nces-standard-braille": 12,
30+
"notify-braille": 13,
31+
"notify-digital-letters-standard": 97,
32+
"notify-standard": 98,
33+
"notify-standard-colour": 99,
34+
};
35+
export const supplier = "supplier1";
36+
37+
export function getVariantsWithUrgency(urgency: number) {
38+
const variants = Object.keys(variantUrgencyMap).filter(
39+
// safe as comes from map's keys which are controlled by us
40+
// eslint-disable-next-line security/detect-object-injection
41+
(variant) => variantUrgencyMap[variant] === urgency,
42+
);
43+
if (variants.length === 0) {
44+
throw new Error(`No variants found with urgency ${urgency}`);
45+
}
46+
return variants;
47+
}
48+
49+
export async function sendEventsForVariants(variants: string[]) {
50+
const domainIds: string[] = [];
51+
for (const variant of variants) {
52+
const domainId = randomUUID();
53+
logger.info(
54+
`Testing event subscription with domainId: ${domainId} and variant: ${variant}`,
55+
);
56+
const preparedEvent = createPreparedV1Event({
57+
domainId,
58+
letterVariantId: variant,
59+
});
60+
const response = await sendSnsEvent(preparedEvent);
61+
expect(response.MessageId).toBeTruthy();
62+
domainIds.push(domainId);
63+
}
64+
return domainIds;
65+
}
66+
67+
export function verifyIndexPositionOfLetterVariants(
68+
letterIds: string[],
69+
letterIdsLowerUrgency: string[],
70+
letterIdsHigherUrgency: string[],
71+
) {
72+
expect(
73+
letterIdsLowerUrgency.every((id) => letterIds.includes(id)),
74+
).toBeTruthy();
75+
expect(
76+
letterIdsHigherUrgency.every((id) => letterIds.includes(id)),
77+
).toBeTruthy();
78+
79+
const indexById = new Map<string, number>();
80+
for (const [i, letterId] of letterIds.entries()) {
81+
indexById.set(letterId, i);
82+
}
83+
84+
let highestUrgencyMaxIndex = -1;
85+
for (const id of letterIdsHigherUrgency) {
86+
const idx = indexById.get(id)!;
87+
if (idx > highestUrgencyMaxIndex) highestUrgencyMaxIndex = idx;
88+
}
89+
90+
let lowerUrgencyMinIndex = Number.POSITIVE_INFINITY;
91+
for (const id of letterIdsLowerUrgency) {
92+
const idx = indexById.get(id)!;
93+
if (idx < lowerUrgencyMinIndex) lowerUrgencyMinIndex = idx;
94+
}
95+
96+
// All higher-urgency letters must appear before any lower-urgency letter
97+
expect(highestUrgencyMaxIndex).toBeLessThan(lowerUrgencyMinIndex);
98+
}
99+
100+
export async function verifyAllocationLogsContainPriority(
101+
letterIds: string[],
102+
priority: number,
103+
) {
104+
for (const domainId of letterIds) {
105+
const message = await pollSupplierAllocatorLogForResolvedSpec(domainId);
106+
const supplierAllocatorLog = JSON.parse(message);
107+
const allocatedLetter: AllocatedLetter = AllocatedLetterSchema.parse(
108+
supplierAllocatorLog.msg,
109+
);
110+
const { supplierSpec } = allocatedLetter;
111+
expect(supplierSpec).toBeDefined();
112+
expect(supplierSpec.priority).toBeDefined();
113+
expect(supplierSpec.priority).toBe(priority);
114+
}
115+
}

0 commit comments

Comments
 (0)