Skip to content

Commit ec79665

Browse files
committed
CCM-12327: wip - update api tests
1 parent f93f57d commit ec79665

File tree

12 files changed

+372
-191
lines changed

12 files changed

+372
-191
lines changed

lambdas/backend-client/src/schemas/template-schema.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ export const $CreateUpdateTemplate = schemaFor<
134134
])
135135
);
136136

137+
const $LockNumber = z.number().min(0);
138+
137139
const $TemplateDtoFields = z
138140
.object({
139141
campaignId: z.string().optional(),
140142
clientId: z.string().optional(),
141143
createdAt: z.string(),
142-
lockNumber: z.number().default(1),
144+
lockNumber: $LockNumber.default(0),
143145
id: z.string().trim().min(1),
144146
templateStatus: z.enum(TEMPLATE_STATUS_LIST),
145147
updatedAt: z.string(),

package-lock.json

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

tests/test-team/helpers/factories/template-factory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export const TemplateFactory = {
100100
version: 1,
101101
createdAt: new Date().toISOString(),
102102
updatedAt: new Date().toISOString(),
103+
lockNumber: 0,
103104
...template,
104105
};
105106
},

tests/test-team/helpers/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export type Template = TypeSpecificProperties & {
6262
createdAt: string;
6363
id: string;
6464
name: string;
65+
lockNumber: number;
6566
owner: string;
6667
templateStatus: string;
6768
templateType: string;

tests/test-team/helpers/use-cases/simulate-failed-virus-scan.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ export class SimulateFailedVirusScan implements IUseCase<Template> {
2929
owner: `CLIENT#${this.#config.clientId}`,
3030
id: this.#config.templateId,
3131
},
32-
UpdateExpression: `SET ${this.#config.filePath} = :virusScanStatus, templateStatus = :virusScanStatusFailedTemplateStatus`,
32+
UpdateExpression: `ADD #lockNumber :lockNumberIncrement, SET ${this.#config.filePath} = :virusScanStatus, templateStatus = :virusScanStatusFailedTemplateStatus`,
33+
ExpressionAttributeNames: {
34+
'#lockNumber': 'lockNumber',
35+
},
3336
ExpressionAttributeValues: {
37+
':lockNumberIncrement': 1,
3438
':virusScanStatus': 'FAILED',
3539
':virusScanStatusFailedTemplateStatus': 'VIRUS_SCAN_FAILED',
3640
},

tests/test-team/helpers/use-cases/simulate-passed-validation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,19 @@ export class SimulatePassedValidation implements IUseCase<Template> {
2929
id: this.#config.templateId,
3030
},
3131
UpdateExpression: [
32+
'ADD #lockNumber :lockNumberIncrement',
3233
'SET files.pdfTemplate.virusScanStatus = :virusScanStatus',
3334
'templateStatus = :readyForSubmissionStatus',
3435
'files.proofs = :proofs',
3536
...(this.#config.hasTestData
3637
? ['files.testDataCsv.virusScanStatus = :virusScanStatus']
3738
: []),
3839
].join(', '),
40+
ExpressionAttributeNames: {
41+
'#lockNumber': 'lockNumber',
42+
},
3943
ExpressionAttributeValues: {
44+
':lockNumberIncrement': 1,
4045
':virusScanStatus': 'PASSED',
4146
':readyForSubmissionStatus': 'PROOF_AVAILABLE',
4247
':proofs': {

tests/test-team/template-mgmt-api-tests/create-template.api.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ test.describe('POST /v1/template', () => {
145145
templateStatus: 'NOT_YET_SUBMITTED',
146146
templateType: template.templateType,
147147
updatedAt: expect.stringMatching(isoDateRegExp),
148+
lockNumber: 0,
148149
},
149150
});
150151

@@ -353,6 +354,7 @@ test.describe('POST /v1/template', () => {
353354
templateStatus: 'NOT_YET_SUBMITTED',
354355
templateType: template.templateType,
355356
updatedAt: expect.stringMatching(isoDateRegExp),
357+
lockNumber: 0,
356358
},
357359
});
358360

@@ -562,6 +564,7 @@ test.describe('POST /v1/template', () => {
562564
templateStatus: 'NOT_YET_SUBMITTED',
563565
templateType: template.templateType,
564566
updatedAt: expect.stringMatching(isoDateRegExp),
567+
lockNumber: 0,
565568
},
566569
});
567570

tests/test-team/template-mgmt-api-tests/delete-template.api.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,3 +789,9 @@ test.describe('DELETE /v1/template/:templateId', () => {
789789
});
790790
});
791791
});
792+
793+
/**
794+
* TODO: CCM-12327
795+
* - tests for missing / invalid lock number header
796+
* - add in these headers to valid tests
797+
*/

tests/test-team/template-mgmt-api-tests/request-proof.api.spec.ts

Lines changed: 118 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ test.describe('POST /v1/template/:templateId/proof', () => {
2727

2828
test('returns 401 if no auth token', async ({ request }) => {
2929
const response = await request.post(
30-
`${process.env.API_BASE_URL}/v1/template/some-template/proof`
30+
`${process.env.API_BASE_URL}/v1/template/some-template/proof`,
31+
{
32+
headers: {
33+
'X-Lock-Number': '0',
34+
},
35+
}
3136
);
3237

3338
const result = await response.json();
@@ -45,6 +50,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
4550
{
4651
headers: {
4752
Authorization: await userProofingEnabled.getAccessToken(),
53+
'X-Lock-Number': '0',
4854
},
4955
}
5056
);
@@ -60,22 +66,21 @@ test.describe('POST /v1/template/:templateId/proof', () => {
6066
test('returns 404 if template exists but is owned by a different client', async ({
6167
request,
6268
}) => {
63-
const userProofingEnabledtemplateId = randomUUID();
69+
const template = TemplateFactory.uploadLetterTemplate(
70+
randomUUID(),
71+
userProofingEnabled,
72+
'userProofingEnabledtemplate',
73+
'PENDING_PROOF_REQUEST'
74+
);
6475

65-
await templateStorageHelper.seedTemplateData([
66-
TemplateFactory.uploadLetterTemplate(
67-
userProofingEnabledtemplateId,
68-
userProofingEnabled,
69-
'userProofingEnabledtemplate',
70-
'PENDING_PROOF_REQUEST'
71-
),
72-
]);
76+
await templateStorageHelper.seedTemplateData([template]);
7377

7478
const updateResponse = await request.post(
75-
`${process.env.API_BASE_URL}/v1/template/${userProofingEnabledtemplateId}/proof`,
79+
`${process.env.API_BASE_URL}/v1/template/${template.id}/proof`,
7680
{
7781
headers: {
7882
Authorization: await differentClientUser.getAccessToken(),
83+
'X-Lock-Number': String(template.lockNumber),
7984
},
8085
}
8186
);
@@ -126,6 +131,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
126131
{
127132
headers: {
128133
Authorization: await userProofingEnabled.getAccessToken(),
134+
'X-Lock-Number': String(template.lockNumber),
129135
},
130136
}
131137
);
@@ -141,6 +147,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
141147
name: template.name,
142148
templateStatus: 'WAITING_FOR_PROOF',
143149
templateType: template.templateType,
150+
lockNumber: template.lockNumber + 1,
144151
}),
145152
});
146153

@@ -176,6 +183,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
176183
{
177184
headers: {
178185
Authorization: await userProofingEnabled.getAccessToken(),
186+
'X-Lock-Number': String(template.lockNumber),
179187
},
180188
}
181189
);
@@ -209,6 +217,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
209217
{
210218
headers: {
211219
Authorization: await userProofingEnabled.getAccessToken(),
220+
'X-Lock-Number': String(template.lockNumber),
212221
},
213222
}
214223
);
@@ -257,6 +266,7 @@ test.describe('POST /v1/template/:templateId/proof', () => {
257266
{
258267
headers: {
259268
Authorization: await userProofingEnabled.getAccessToken(),
269+
'X-Lock-Number': String(template.lockNumber),
260270
},
261271
}
262272
);
@@ -277,4 +287,101 @@ test.describe('POST /v1/template/:templateId/proof', () => {
277287

278288
expect(result.data.updatedAt).toBeDateRoughlyBetween([start, new Date()]);
279289
});
290+
291+
test('returns 400 if the lock number header is not set', async ({
292+
request,
293+
}) => {
294+
const template = {
295+
...TemplateFactory.uploadLetterTemplate(
296+
randomUUID(),
297+
userProofingEnabled,
298+
'userProofingEnabledtemplate',
299+
'PENDING_PROOF_REQUEST'
300+
),
301+
files: {
302+
pdfTemplate: {
303+
virusScanStatus: 'PASSED',
304+
currentVersion: randomUUID(),
305+
fileName: 'template.pdf',
306+
},
307+
testDataCsv: {
308+
virusScanStatus: 'PASSED',
309+
currentVersion: randomUUID(),
310+
fileName: 'data.csv',
311+
},
312+
},
313+
personalisationParameters: ['nhsNumber'],
314+
campaignId: userProofingEnabled.campaignIds?.[0],
315+
};
316+
317+
await templateStorageHelper.seedTemplateData([template]);
318+
319+
const response = await request.post(
320+
`${process.env.API_BASE_URL}/v1/template/${template.id}/proof`,
321+
{
322+
headers: {
323+
Authorization: await userProofingEnabled.getAccessToken(),
324+
},
325+
}
326+
);
327+
328+
const result = await response.json();
329+
const debug = JSON.stringify(result, null, 2);
330+
331+
expect(response.status(), debug).toBe(400);
332+
333+
expect(result).toEqual({
334+
statusCode: 400,
335+
technicalMessage: 'Invalid lock number',
336+
});
337+
});
338+
339+
test('returns 400 if the lock number header does not match the current one', async ({
340+
request,
341+
}) => {
342+
const template = {
343+
...TemplateFactory.uploadLetterTemplate(
344+
randomUUID(),
345+
userProofingEnabled,
346+
'userProofingEnabledtemplate',
347+
'PENDING_PROOF_REQUEST'
348+
),
349+
files: {
350+
pdfTemplate: {
351+
virusScanStatus: 'PASSED',
352+
currentVersion: randomUUID(),
353+
fileName: 'template.pdf',
354+
},
355+
testDataCsv: {
356+
virusScanStatus: 'PASSED',
357+
currentVersion: randomUUID(),
358+
fileName: 'data.csv',
359+
},
360+
},
361+
personalisationParameters: ['nhsNumber'],
362+
campaignId: userProofingEnabled.campaignIds?.[0],
363+
};
364+
365+
await templateStorageHelper.seedTemplateData([template]);
366+
367+
const response = await request.post(
368+
`${process.env.API_BASE_URL}/v1/template/${template.id}/proof`,
369+
{
370+
headers: {
371+
Authorization: await userProofingEnabled.getAccessToken(),
372+
'X-Lock-Number': String(template.lockNumber + 1),
373+
},
374+
}
375+
);
376+
377+
const result = await response.json();
378+
const debug = JSON.stringify(result, null, 2);
379+
380+
expect(response.status(), debug).toBe(400);
381+
382+
expect(result).toEqual({
383+
statusCode: 400,
384+
technicalMessage: 'Invalid lock number',
385+
});
386+
});
280387
});

0 commit comments

Comments
 (0)