Skip to content

Commit 3820d92

Browse files
CCM-12950: Add Functional Tests for Events (#449)
* new tests * Fix vulnerabilities * update * update lockfile * lint errors * fix * add sandbox tests * fix * add test time out * review fix * fix --------- Co-authored-by: Steve Buxton <steve.buxton@nhs.net>
1 parent 1172474 commit 3820d92

23 files changed

+717
-63
lines changed

.github/actions/test-types.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[
2-
"component"
2+
"component",
3+
"sandbox"
34
]

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ config:: _install-dependencies version # Configure development environment (main
104104
test-component:
105105
(cd tests && npm install && npm run test:component)
106106

107+
test-sandbox:
108+
(cd tests && npm install && npm run test:sandbox)
109+
107110
test-performance:
108111
(cd tests && npm install && npm run test:performance)
109112

package-lock.json

Lines changed: 94 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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";
6+
import { createValidRequestHeaders } from "tests/constants/request-headers";
7+
import getRestApiGatewayBaseUrl from "tests/helpers/aws-gateway-helper";
8+
import { SUPPLIER_LETTERS, envName } from "tests/constants/api-constants";
9+
import {
10+
pollSupplierAllocatorLogForResolvedSpec,
11+
pollUpsertLetterLogForError,
12+
} from "tests/helpers/aws-cloudwatch-helper";
13+
import { supplierDataSetup } from "tests/helpers/suppliers-setup-helper";
14+
import { pollForLettersInDb } from "tests/helpers/poll-for-letters-helper";
15+
16+
let baseUrl: string;
17+
18+
test.beforeAll(async () => {
19+
baseUrl = await getRestApiGatewayBaseUrl();
20+
});
21+
22+
test.describe("Event Subscription SNS Tests", () => {
23+
test.setTimeout(180_000); // 3 minutes for long running polling
24+
test(`Verify that the publish event to nhs-${envName}-supapi-eventsub topic inserts data into db`, async ({
25+
request,
26+
}) => {
27+
const domainId = randomUUID();
28+
logger.info(`Testing event subscription with domainId: ${domainId}`);
29+
const preparedEvent = createPreparedV1Event({ domainId });
30+
const response = await sendSnsEvent(preparedEvent);
31+
32+
expect(response.MessageId).toBeTruthy();
33+
34+
// poll supplier allocator to check if supplier has been allocated
35+
const message = await pollSupplierAllocatorLogForResolvedSpec(domainId);
36+
const supplierAllocatorLog = JSON.parse(message) as {
37+
msg?: { supplierSpec?: { supplierId?: string } };
38+
};
39+
const supplierId = supplierAllocatorLog.msg?.supplierSpec?.supplierId;
40+
41+
logger.info(
42+
`Supplier ${supplierId} allocated for domainId ${domainId} in supplier allocator lambda`,
43+
);
44+
if (!supplierId) {
45+
throw new Error("supplierId was not found in supplier allocator log");
46+
}
47+
48+
// check if supplier exists in suppliers table
49+
await supplierDataSetup(supplierId);
50+
51+
// poll for letter to be inserted in db with status PENDING
52+
const { letterStatus, statusCode } = await pollForLettersInDb(
53+
request,
54+
supplierId,
55+
domainId,
56+
baseUrl,
57+
);
58+
59+
expect(statusCode).toBe(200);
60+
expect(letterStatus).toBe("PENDING");
61+
});
62+
63+
test("Verify that the publish event with 'CANCELLED' status throws error", async ({
64+
request,
65+
}) => {
66+
const domainId = randomUUID();
67+
logger.info(`Testing event subscription with domainId: ${domainId}`);
68+
const preparedEvent = createPreparedV1Event({
69+
domainId,
70+
status: "CANCELLED",
71+
});
72+
const response = await sendSnsEvent(preparedEvent);
73+
74+
expect(response.MessageId).toBeTruthy();
75+
76+
// poll supplier allocator to check if supplier has been allocated
77+
const message = await pollSupplierAllocatorLogForResolvedSpec(domainId);
78+
const supplierAllocatorLog = JSON.parse(message) as {
79+
msg?: { supplierSpec?: { supplierId?: string } };
80+
};
81+
const supplierId = supplierAllocatorLog.msg?.supplierSpec?.supplierId;
82+
83+
logger.info(
84+
`Supplier ${supplierId} allocated for domainId ${domainId} in supplier allocator lambda`,
85+
);
86+
if (!supplierId) {
87+
throw new Error("supplierId was not found in supplier allocator log");
88+
}
89+
90+
const headers = createValidRequestHeaders(supplierId);
91+
92+
const getLetterResponse = await request.get(
93+
`${baseUrl}/${SUPPLIER_LETTERS}/${domainId}`,
94+
{
95+
headers,
96+
},
97+
);
98+
99+
expect(getLetterResponse.status()).toBe(500);
100+
await pollUpsertLetterLogForError(
101+
"Message did not match an expected schema",
102+
domainId,
103+
);
104+
});
105+
106+
test("Verify that the duplicate event throws an error", async () => {
107+
const domainId = randomUUID();
108+
logger.info(`Testing event subscription with domainId: ${domainId}`);
109+
const preparedEvent = createPreparedV1Event({
110+
domainId,
111+
status: "PREPARED",
112+
});
113+
const response = await sendSnsEvent(preparedEvent);
114+
115+
expect(response.MessageId).toBeTruthy();
116+
117+
// poll supplier allocator to check if supplier has been allocated
118+
const message = await pollSupplierAllocatorLogForResolvedSpec(domainId);
119+
const supplierAllocatorLog = JSON.parse(message) as {
120+
msg?: { supplierSpec?: { supplierId?: string } };
121+
};
122+
const supplierId = supplierAllocatorLog.msg?.supplierSpec?.supplierId;
123+
124+
logger.info(
125+
`Supplier ${supplierId} allocated for domainId ${domainId} in supplier allocator lambda`,
126+
);
127+
if (!supplierId) {
128+
throw new Error("supplierId was not found in supplier allocator log");
129+
}
130+
131+
// send same event again to simulate duplicate event
132+
const duplicateResponse = await sendSnsEvent(preparedEvent);
133+
expect(duplicateResponse.MessageId).toBeTruthy();
134+
135+
// poll supplier upsert to check if duplicate event was processed
136+
await pollUpsertLetterLogForError(
137+
`Letter with id ${domainId} already exists for supplier ${supplierId}"`,
138+
);
139+
});
140+
});

0 commit comments

Comments
 (0)