Skip to content

Commit ae3ae79

Browse files
Unit tests
1 parent b8a7386 commit ae3ae79

3 files changed

Lines changed: 168 additions & 1 deletion

File tree

lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,48 @@ function createPreparedV1Event(
7575
};
7676
}
7777

78+
function createSupplierStatusChangeEventWithoutSupplier(
79+
overrides: Partial<any> = {},
80+
): LetterEvent {
81+
const now = new Date().toISOString();
82+
83+
return $LetterEvent.parse({
84+
data: {
85+
domainId: overrides.domainId ?? "f47ac10b-58cc-4372-a567-0e02b2c3d479",
86+
groupId: "client_template",
87+
origin: {
88+
domain: "letter-rendering",
89+
event: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
90+
source: "/data-plane/letter-rendering/prod/render-pdf",
91+
subject:
92+
"client/00f3b388-bbe9-41c9-9e76-052d37ee8988/letter-request/0o5Fs0EELR0fUjHjbCnEtdUwQe4_0o5Fs0EELR0fUjHjbCnEtdUwQe5",
93+
},
94+
reasonCode: "R07",
95+
reasonText: "No such address",
96+
specificationId: "1y3q9v1zzzz",
97+
billingRef: "1y3q9v1zzzz",
98+
status: "RETURNED",
99+
supplierId: "",
100+
},
101+
datacontenttype: "application/json",
102+
dataschema:
103+
"https://notify.nhs.uk/cloudevents/schemas/supplier-api/letter.RETURNED.1.0.0.schema.json",
104+
dataschemaversion: "1.0.0",
105+
id: overrides.id ?? "23f1f09c-a555-4d9b-8405-0b33490bc920",
106+
plane: "data",
107+
recordedtime: now,
108+
severitynumber: 2,
109+
severitytext: "INFO",
110+
source: "/data-plane/supplier-api/prod/update-status",
111+
specversion: "1.0",
112+
subject:
113+
"letter-origin/letter-rendering/letter/f47ac10b-58cc-4372-a567-0e02b2c3d479",
114+
time: now,
115+
traceparent: "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
116+
type: "uk.nhs.notify.supplier-api.letter.RETURNED.v1",
117+
});
118+
}
119+
78120
function createPreparedV2Event(
79121
overrides: Partial<any> = {},
80122
): LetterRequestPreparedEventV2 {
@@ -129,6 +171,26 @@ function createSupplierStatusChangeEvent(
129171
});
130172
}
131173

174+
// Mock aws-embedded-metrics
175+
let mockMetrics: any;
176+
jest.mock("aws-embedded-metrics", () => ({
177+
metricScope: (
178+
handler: (metrics: any) => (event: SQSEvent) => Promise<any>,
179+
) => {
180+
return async (event: SQSEvent) => {
181+
mockMetrics = {
182+
setNamespace: jest.fn(),
183+
putDimensions: jest.fn(),
184+
putMetric: jest.fn(),
185+
};
186+
return handler(mockMetrics)(event);
187+
};
188+
},
189+
Unit: {
190+
Count: "Count",
191+
},
192+
}));
193+
132194
describe("createUpsertLetterHandler", () => {
133195
const mockedDeps: jest.Mocked<Deps> = {
134196
letterRepo: {
@@ -213,6 +275,40 @@ describe("createUpsertLetterHandler", () => {
213275
expect(updatedLetter.reasonCode).toBe("R07");
214276
expect(updatedLetter.reasonText).toBe("No such address");
215277
expect(updatedLetter.supplierId).toBe("supplier1");
278+
expect(mockMetrics.setNamespace).toHaveBeenCalledWith("upsertLetter");
279+
expect(mockMetrics.putDimensions).toHaveBeenCalledWith({
280+
Supplier: "supplier1",
281+
});
282+
expect(mockMetrics.putMetric).toHaveBeenCalledWith(
283+
"MessagesProcessed",
284+
3,
285+
"Count",
286+
);
287+
});
288+
289+
test("unknown supplier has metric emitted with 'unknown' supplier dimension", async () => {
290+
const letterEvent = createSupplierStatusChangeEventWithoutSupplier();
291+
292+
const message = {
293+
letterEvent,
294+
operationType: "uk.nhs.notify.supplier-api.letter.RETURNED.v1",
295+
supplierSpec: undefined,
296+
};
297+
const evt: SQSEvent = createSQSEvent([
298+
createSqsRecord("unknown-supplier", JSON.stringify(message)),
299+
]);
300+
301+
await createUpsertLetterHandler(mockedDeps)(evt, {} as any, {} as any);
302+
303+
expect(mockMetrics.setNamespace).toHaveBeenCalledWith("upsertLetter");
304+
expect(mockMetrics.putDimensions).toHaveBeenCalledWith({
305+
Supplier: "unknown",
306+
});
307+
expect(mockMetrics.putMetric).toHaveBeenCalledWith(
308+
"MessagesProcessed",
309+
1,
310+
"Count",
311+
);
216312
});
217313

218314
test("invalid JSON produces batch failure and logs error", async () => {
@@ -235,6 +331,15 @@ describe("createUpsertLetterHandler", () => {
235331
"Error processing upsert of record bad-json",
236332
);
237333
expect(mockedDeps.letterRepo.putLetter).not.toHaveBeenCalled();
334+
expect(mockMetrics.setNamespace).toHaveBeenCalledWith("upsertLetter");
335+
expect(mockMetrics.putDimensions).toHaveBeenCalledWith({
336+
Supplier: "unknown",
337+
});
338+
expect(mockMetrics.putMetric).toHaveBeenCalledWith(
339+
"MessageFailed",
340+
1,
341+
"Count",
342+
);
238343
});
239344

240345
test("invalid letter event schema produces batch failure", async () => {
@@ -260,6 +365,16 @@ describe("createUpsertLetterHandler", () => {
260365
expect(result.batchItemFailures).toHaveLength(1);
261366
expect(result.batchItemFailures[0].itemIdentifier).toBe("bad-schema");
262367
expect(mockedDeps.letterRepo.putLetter).not.toHaveBeenCalled();
368+
expect(mockMetrics.setNamespace).toHaveBeenCalledWith("upsertLetter");
369+
expect(mockMetrics.putDimensions).toHaveBeenCalledWith({
370+
Supplier: "supplier1",
371+
});
372+
expect(mockMetrics.putMetric).toHaveBeenCalledWith(
373+
"MessageFailed",
374+
1,
375+
"Count",
376+
);
377+
263378
});
264379

265380
test("unknown operation type produces batch failure", async () => {
@@ -283,6 +398,16 @@ describe("createUpsertLetterHandler", () => {
283398
if (!result) throw new Error("expected BatchResponse, got void");
284399
expect(result.batchItemFailures).toHaveLength(1);
285400
expect(result.batchItemFailures[0].itemIdentifier).toBe("unknown-op");
401+
402+
expect(mockMetrics.setNamespace).toHaveBeenCalledWith("upsertLetter");
403+
expect(mockMetrics.putDimensions).toHaveBeenCalledWith({
404+
Supplier: "supplier1",
405+
});
406+
expect(mockMetrics.putMetric).toHaveBeenCalledWith(
407+
"MessageFailed",
408+
1,
409+
"Count",
410+
);
286411
});
287412

288413
test("processes multiple records with mixed results", async () => {

lambdas/upsert-letter/src/handler/upsert-handler.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ async function emitMetrics(
136136
}
137137
}
138138

139-
140139
function getSupplierEventId(letterEvent: any): string {
141140
if (letterEvent && letterEvent.data && letterEvent.data.supplierId) {
142141
return letterEvent.data.supplierId;

package-lock.json

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)