Skip to content

Commit 197fd3b

Browse files
CCM-10283: Fix test coverage
1 parent 42dbc5a commit 197fd3b

File tree

3 files changed

+151
-19
lines changed

3 files changed

+151
-19
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { mockDeep } from 'jest-mock-extended';
2+
import { SESClient, SendRawEmailCommand } from '@aws-sdk/client-ses';
3+
import { Logger } from 'nhs-notify-web-template-management-utils/logger';
4+
import { EmailClient } from '../../../templates/infra/email-client';
5+
import { TemplateDto } from 'nhs-notify-backend-client';
6+
7+
jest.mock('node:fs', () => ({
8+
readFileSync: jest.fn(() => '<html>{{templateId}}</html>'),
9+
}));
10+
11+
jest.mock('mimetext', () => ({
12+
createMimeMessage: () => {
13+
const msg = {
14+
setSender: jest.fn(),
15+
setTo: jest.fn(),
16+
setSubject: jest.fn(),
17+
addMessage: jest.fn(),
18+
asRaw: jest.fn(() => 'raw-email-content'),
19+
};
20+
return msg;
21+
},
22+
}));
23+
24+
describe('EmailClient', () => {
25+
const recipientEmails = {
26+
supplier1: ['[email protected]'],
27+
28+
};
29+
30+
const sesClient = mockDeep<SESClient>();
31+
const logger = mockDeep<Logger>();
32+
33+
const mockTemplate = mockDeep<TemplateDto>({
34+
id: 'template-id',
35+
templateType: 'LETTER',
36+
files: {
37+
proofs: {
38+
proof1: { fileName: 'proof1.pdf', supplier: 'supplier1' },
39+
proof2: { fileName: 'proof2.pdf', supplier: 'supplier2' },
40+
},
41+
},
42+
updatedAt: '2022-01-01T00:00:00Z',
43+
name: 'Test Template',
44+
});
45+
46+
beforeEach(() => {
47+
jest.clearAllMocks();
48+
});
49+
50+
it('does not send email when no email address provided', async () => {
51+
const client = new EmailClient(sesClient, '', recipientEmails, logger);
52+
53+
await client.sendTemplateSubmittedEmailToSuppliers(mockTemplate);
54+
55+
expect(sesClient.send).not.toHaveBeenCalled();
56+
expect(logger.info).toHaveBeenCalledWith({
57+
description:
58+
'Not sending template submitted email to suppliers because no email address is provided',
59+
templateId: mockTemplate.id,
60+
});
61+
});
62+
63+
it('does not send email if templateType is not LETTER', async () => {
64+
const client = new EmailClient(
65+
sesClient,
66+
67+
recipientEmails,
68+
logger
69+
);
70+
const template = mockDeep<TemplateDto>({
71+
...mockTemplate,
72+
templateType: 'NHS_APP',
73+
});
74+
75+
await client.sendTemplateSubmittedEmailToSuppliers(template);
76+
77+
expect(sesClient.send).not.toHaveBeenCalled();
78+
expect(logger.info).toHaveBeenCalledWith({
79+
description:
80+
'Not sending template submitted email to suppliers because templateType is not LETTER',
81+
templateId: template.id,
82+
});
83+
});
84+
85+
it('sends no email if there are no proofs on the template', async () => {
86+
const client = new EmailClient(
87+
sesClient,
88+
89+
recipientEmails,
90+
logger
91+
);
92+
const template = mockDeep<TemplateDto>({
93+
id: 'template-id',
94+
templateType: 'LETTER',
95+
files: {
96+
proofs: undefined,
97+
},
98+
updatedAt: '2022-01-01T00:00:00Z',
99+
name: 'Test Template',
100+
});
101+
102+
await client.sendTemplateSubmittedEmailToSuppliers(template);
103+
104+
expect(sesClient.send).not.toHaveBeenCalled();
105+
});
106+
107+
it('sends email to multiple suppliers', async () => {
108+
const client = new EmailClient(
109+
sesClient,
110+
111+
recipientEmails,
112+
logger
113+
);
114+
115+
await client.sendTemplateSubmittedEmailToSuppliers(mockTemplate);
116+
117+
expect(sesClient.send).toHaveBeenCalledTimes(2);
118+
expect(sesClient.send).toHaveBeenCalledWith(
119+
expect.any(SendRawEmailCommand)
120+
);
121+
expect(logger.info).toHaveBeenCalled();
122+
});
123+
});

lambdas/backend-api/src/templates/infra/email-client.ts

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,27 @@ export class EmailClient {
1414
private readonly logger: Logger
1515
) {}
1616

17-
getTemplateSubmittedEmailContent(
18-
{ files, updatedAt, id, name }: LetterTemplate,
19-
supplierToEmail: string
17+
private getTemplateSubmittedEmailContent(
18+
{ updatedAt, id, name }: LetterTemplate,
19+
supplier: string,
20+
proofFilenames: string[]
2021
) {
2122
const emailTemplateContent = readFileSync('./email-template.html');
2223
const htmlTemplate = Handlebars.compile(emailTemplateContent);
2324

24-
const proofFilenames = Object.values(files.proofs ?? []).flatMap(
25-
({ fileName, supplier }) =>
26-
supplier === supplierToEmail ? [fileName] : []
27-
);
28-
2925
return htmlTemplate({
3026
proofFilenames,
27+
supplier,
3128
timestamp: updatedAt,
3229
templateId: id,
3330
templateName: name,
3431
});
3532
}
3633

37-
async sendTemplateSubmittedEmailToSupplier(
34+
private async sendTemplateSubmittedEmailToSupplier(
3835
template: LetterTemplate,
39-
supplier: string
36+
supplier: string,
37+
proofFilenames: string[]
4038
) {
4139
const recipientEmailsForSupplier = this.recipientEmails[supplier];
4240

@@ -45,10 +43,14 @@ export class EmailClient {
4543
msg.setTo(
4644
recipientEmailsForSupplier.map((emailAddress) => ({ addr: emailAddress }))
4745
);
48-
msg.setSubject('A letter proof has been approved by an NHS Notify user.');
46+
msg.setSubject(`${supplier} - Letter proof approved by an NHS Notify user`);
4947
msg.addMessage({
5048
contentType: 'text/html',
51-
data: this.getTemplateSubmittedEmailContent(template, supplier),
49+
data: this.getTemplateSubmittedEmailContent(
50+
template,
51+
supplier,
52+
proofFilenames
53+
),
5254
});
5355

5456
const command = new SendRawEmailCommand({
@@ -84,16 +86,21 @@ export class EmailClient {
8486
return;
8587
}
8688

87-
const suppliersToEmail: string[] = [];
89+
const proofsBySupplier: Record<string, string[]> = {};
8890

89-
for (const { supplier } of Object.values(template.files.proofs ?? {})) {
90-
if (!suppliersToEmail.includes(supplier)) {
91-
suppliersToEmail.push(supplier);
92-
}
91+
for (const { supplier, fileName } of Object.values(
92+
template.files.proofs ?? {}
93+
)) {
94+
const proofFilenames = [...(proofsBySupplier[supplier] ?? []), fileName];
95+
proofsBySupplier[supplier] = proofFilenames;
9396
}
9497

95-
for (const supplier of suppliersToEmail) {
96-
await this.sendTemplateSubmittedEmailToSupplier(template, supplier);
98+
for (const [supplier, proofFilenames] of Object.entries(proofsBySupplier)) {
99+
await this.sendTemplateSubmittedEmailToSupplier(
100+
template,
101+
supplier,
102+
proofFilenames
103+
);
97104
}
98105
}
99106
}

lambdas/backend-api/src/templates/infra/email-template.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
}
2121
</head>
2222
<body style="font-family: Frutiger W01; font-size: 14px">
23+
<p>For the attention of {{supplier}}.</p>
24+
2325
<p>This letter proof has been approved by an NHS Notify user.</p>
2426

2527
<p>

0 commit comments

Comments
 (0)