Skip to content

Commit 6d7b1ea

Browse files
committed
playwright test
1 parent 4639e25 commit 6d7b1ea

File tree

7 files changed

+541
-235
lines changed

7 files changed

+541
-235
lines changed

lambdas/event-publisher/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"esbuild": "^0.25.9",
1818
"jest": "^29.7.0",
1919
"jest-mock-extended": "^3.0.7",
20+
"nhs-notify-web-template-management-test-helper-utils": "^0.0.1",
2021
"typescript": "^5.8.2"
2122
},
2223
"name": "nhs-notify-templates-event-publisher",

lambdas/event-publisher/src/__tests__/domain/event-builder.test.ts

Lines changed: 183 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { mockDeep } from 'jest-mock-extended';
21
import { EventBuilder } from '../../domain/event-builder';
3-
import { Logger } from 'nhs-notify-web-template-management-utils/logger';
2+
import { createMockLogger } from 'nhs-notify-web-template-management-test-helper-utils/mock-logger';
43
import { PublishableEventRecord } from '../../domain/input-schemas';
54
import { shouldPublish } from '../../domain/should-publish';
65

@@ -18,11 +17,11 @@ beforeEach(() => {
1817

1918
const shouldPublishMock = jest.mocked(shouldPublish);
2019

21-
const mockLogger = mockDeep<Logger>();
20+
const { logger: mockLogger } = createMockLogger();
2221

2322
const eventBuilder = new EventBuilder('table-name', 'event-source', mockLogger);
2423

25-
const publishableEventRecord = (status: string): PublishableEventRecord => ({
24+
const publishableEventRecord = (newStatus: string): PublishableEventRecord => ({
2625
dynamodb: {
2726
SequenceNumber: '4',
2827
NewImage: {
@@ -45,7 +44,89 @@ const publishableEventRecord = (status: string): PublishableEventRecord => ({
4544
S: 'name',
4645
},
4746
templateStatus: {
48-
S: status,
47+
S: newStatus,
48+
},
49+
updatedAt: {
50+
S: 'updated-at',
51+
},
52+
updatedBy: {
53+
S: 'updated-by',
54+
},
55+
templateType: {
56+
S: 'LETTER',
57+
},
58+
language: {
59+
S: 'fr',
60+
},
61+
letterType: {
62+
S: 'x0',
63+
},
64+
proofingEnabled: {
65+
BOOL: true,
66+
},
67+
files: {
68+
M: {
69+
pdfTemplate: {
70+
M: {
71+
currentVersion: {
72+
S: 'current-version',
73+
},
74+
fileName: {
75+
S: 'file-name',
76+
},
77+
virusScanStatus: {
78+
S: 'PASSED',
79+
},
80+
},
81+
},
82+
proofs: {
83+
M: {
84+
proof1: {
85+
M: {
86+
supplier: {
87+
S: 'WTMMOCK',
88+
},
89+
fileName: {
90+
S: 'file-name',
91+
},
92+
virusScanStatus: {
93+
S: 'PASSED',
94+
},
95+
},
96+
},
97+
},
98+
},
99+
},
100+
},
101+
personalisationParameters: {
102+
L: [
103+
{
104+
S: 'test',
105+
},
106+
],
107+
},
108+
},
109+
OldImage: {
110+
owner: {
111+
S: 'owner',
112+
},
113+
id: {
114+
S: 'id',
115+
},
116+
clientId: {
117+
S: 'client-id',
118+
},
119+
createdAt: {
120+
S: 'created-at',
121+
},
122+
createdBy: {
123+
S: 'created-by',
124+
},
125+
name: {
126+
S: 'name',
127+
},
128+
templateStatus: {
129+
S: 'PENDING_PROOF_REQUEST',
49130
},
50131
updatedAt: {
51132
S: 'updated-at',
@@ -158,6 +239,37 @@ test('errors on unrecognised event type', () => {
158239
);
159240
});
160241

242+
test('errors on output schema validation failure', () => {
243+
const valid = publishableEventRecord('SUBMITTED');
244+
245+
const invalidDomainEventRecord = {
246+
...valid,
247+
dynamodb: {
248+
...valid.dynamodb,
249+
NewImage: {
250+
...valid.dynamodb.NewImage,
251+
language: { N: 0 },
252+
},
253+
},
254+
};
255+
256+
expect(() =>
257+
eventBuilder.buildEvent(
258+
invalidDomainEventRecord as unknown as PublishableEventRecord
259+
)
260+
).toThrow(
261+
expect.objectContaining({
262+
name: 'ZodError',
263+
issues: [
264+
expect.objectContaining({
265+
code: 'invalid_value',
266+
path: ['data', 'language'],
267+
}),
268+
],
269+
})
270+
);
271+
});
272+
161273
test('builds template completed event', () => {
162274
const event = eventBuilder.buildEvent(publishableEventRecord('SUBMITTED'));
163275

@@ -184,6 +296,72 @@ test('builds template drafted event', () => {
184296
);
185297
});
186298

299+
test('builds template drafted event when no old image is available', () => {
300+
const event = eventBuilder.buildEvent({
301+
dynamodb: {
302+
SequenceNumber: '4',
303+
NewImage: {
304+
owner: {
305+
S: 'owner',
306+
},
307+
id: {
308+
S: 'id',
309+
},
310+
clientId: {
311+
S: 'client-id',
312+
},
313+
createdAt: {
314+
S: 'created-at',
315+
},
316+
createdBy: {
317+
S: 'created-by',
318+
},
319+
name: {
320+
S: 'name',
321+
},
322+
templateStatus: {
323+
S: 'NOT_YET_SUBMITTED',
324+
},
325+
updatedAt: {
326+
S: 'updated-at',
327+
},
328+
updatedBy: {
329+
S: 'updated-by',
330+
},
331+
templateType: {
332+
S: 'NHS_APP',
333+
},
334+
message: {
335+
S: 'app content',
336+
},
337+
},
338+
},
339+
eventID: 'event-id',
340+
tableName: 'table-name',
341+
});
342+
343+
expect(event).toEqual({
344+
...expectedEvent(
345+
'PROOF_AVAILABLE',
346+
'uk.nhs.notify.template-management.TemplateDrafted.v1',
347+
'https://notify.nhs.uk/events/schemas/TemplateDrafted/v1.json'
348+
),
349+
data: {
350+
clientId: 'client-id',
351+
createdAt: 'created-at',
352+
createdBy: 'created-by',
353+
id: 'id',
354+
message: 'app content',
355+
name: 'name',
356+
owner: 'owner',
357+
templateStatus: 'NOT_YET_SUBMITTED',
358+
templateType: 'NHS_APP',
359+
updatedAt: 'updated-at',
360+
updatedBy: 'updated-by',
361+
},
362+
});
363+
});
364+
187365
test('builds template deleted event', () => {
188366
const event = eventBuilder.buildEvent(publishableEventRecord('DELETED'));
189367

Lines changed: 90 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,114 @@
1-
import {
2-
LetterProperties,
3-
TemplateDto,
4-
TemplateStatus,
5-
TemplateType,
6-
} from 'nhs-notify-backend-client';
1+
import { TemplateStatus, TemplateType } from 'nhs-notify-backend-client';
72
import { shouldPublish } from '../../domain/should-publish';
83

94
describe('shouldPublish', () => {
105
test.each(['EMAIL', 'SMS', 'NHS_APP'] satisfies TemplateType[])(
116
'templateType %p should return true',
127
(type) => {
13-
expect(shouldPublish({ templateType: type } as TemplateDto)).toEqual(
14-
true
8+
const publish = shouldPublish(
9+
{
10+
templateType: type,
11+
id: 'id',
12+
templateStatus: 'NOT_YET_SUBMITTED',
13+
},
14+
{
15+
templateType: type,
16+
id: 'id',
17+
templateStatus: 'SUBMITTED',
18+
}
1519
);
20+
21+
expect(publish).toEqual(true);
1622
}
1723
);
1824

1925
test.each([false, undefined])(
20-
'templateType LETTER should return false when proofingEnabled %p',
26+
'templateType LETTER should return false when proofingEnabled is %p',
2127
(proofingEnabled) => {
22-
expect(
23-
shouldPublish({
28+
const publish = shouldPublish(
29+
{
30+
id: 'id',
31+
templateType: 'LETTER',
32+
templateStatus: 'PROOF_AVAILABLE',
33+
proofingEnabled,
34+
},
35+
{
36+
id: 'id',
2437
templateType: 'LETTER',
2538
templateStatus: 'SUBMITTED',
2639
proofingEnabled,
27-
} as TemplateDto & LetterProperties)
28-
).toEqual(false);
40+
}
41+
);
42+
43+
expect(publish).toEqual(false);
44+
}
45+
);
46+
47+
const letterPublishCases: Record<TemplateStatus, boolean> = {
48+
DELETED: true,
49+
PENDING_PROOF_REQUEST: true,
50+
PROOF_AVAILABLE: true,
51+
SUBMITTED: true,
52+
WAITING_FOR_PROOF: true,
53+
NOT_YET_SUBMITTED: false,
54+
PENDING_UPLOAD: false,
55+
PENDING_VALIDATION: false,
56+
VALIDATION_FAILED: false,
57+
VIRUS_SCAN_FAILED: false,
58+
};
59+
60+
test.each(Object.entries(letterPublishCases) as [TemplateStatus, boolean][])(
61+
'templateType LETTER with current status %p should return %p when proofingEnabled is true and status of previous is PENDING_PROOF_REQUEST',
62+
(templateStatus, publishable) => {
63+
const publish = shouldPublish(
64+
{
65+
id: 'id',
66+
templateType: 'LETTER',
67+
templateStatus: 'PENDING_PROOF_REQUEST',
68+
proofingEnabled: true,
69+
},
70+
{
71+
id: 'id',
72+
templateType: 'LETTER',
73+
templateStatus,
74+
proofingEnabled: true,
75+
}
76+
);
77+
78+
expect(publish).toEqual(publishable);
2979
}
3080
);
3181

32-
test.each([
33-
'DELETED',
34-
'PENDING_PROOF_REQUEST',
35-
'PROOF_AVAILABLE',
36-
'SUBMITTED',
37-
'WAITING_FOR_PROOF',
38-
] satisfies TemplateStatus[])(
39-
'templateType LETTER should return true when templateStatus is %p and proofingEnabled is true',
40-
(templateStatus) => {
41-
expect(
42-
shouldPublish({
82+
test.each(Object.entries(letterPublishCases) as [TemplateStatus, boolean][])(
83+
'templateType LETTER with current status DELETED and previous status %p should return %p when proofingEnabled is true',
84+
(templateStatus, publishable) => {
85+
const publish = shouldPublish(
86+
{
87+
id: 'id',
4388
templateType: 'LETTER',
4489
templateStatus,
4590
proofingEnabled: true,
46-
} as TemplateDto & LetterProperties)
47-
).toEqual(true);
91+
},
92+
{
93+
id: 'id',
94+
templateType: 'LETTER',
95+
templateStatus: 'DELETED',
96+
proofingEnabled: true,
97+
}
98+
);
99+
100+
expect(publish).toEqual(publishable);
48101
}
49102
);
103+
104+
test('does not publish if templateType is LETTER and no previous template is available', () => {
105+
expect(
106+
shouldPublish(undefined, {
107+
id: 'id',
108+
templateType: 'LETTER',
109+
templateStatus: 'DELETED',
110+
proofingEnabled: true,
111+
})
112+
).toEqual(false);
113+
});
50114
});

0 commit comments

Comments
 (0)