Skip to content

Commit f842a0e

Browse files
Added component tests for letters post endpoint
1 parent b867ae2 commit f842a0e

5 files changed

Lines changed: 331 additions & 30 deletions

File tree

scripts/utilities/letter-test-data/src/helpers/create_letter_helpers.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ export async function createLetter(params: {
1616
letterRepository: LetterRepository;
1717
}) {
1818
const {
19-
letterId,
2019
bucketName,
21-
supplierId,
22-
targetFilename,
23-
specificationId,
2420
groupId,
25-
status,
21+
letterId,
2622
letterRepository,
23+
specificationId,
24+
status,
25+
supplierId,
26+
targetFilename,
2727
} = params;
2828

2929
await uploadFile(
@@ -39,7 +39,7 @@ export async function createLetter(params: {
3939
specificationId,
4040
groupId,
4141
url: `s3://${bucketName}/${supplierId}/${targetFilename}`,
42-
status: status,
42+
status,
4343
createdAt: new Date().toISOString(),
4444
updatedAt: new Date().toISOString(),
4545
};
@@ -56,22 +56,16 @@ export function createLetterDto(params: {
5656
status: LetterStatusType;
5757
url: string;
5858
}) {
59-
const {
60-
letterId,
61-
supplierId,
62-
specificationId,
63-
groupId,
64-
status,
65-
url,
66-
} = params;
59+
const { groupId, letterId, specificationId, status, supplierId, url } =
60+
params;
6761

6862
const letter: Omit<Letter, "ttl" | "supplierStatus" | "supplierStatusSk"> = {
6963
id: letterId,
7064
supplierId,
7165
specificationId,
7266
groupId,
73-
url: url,
74-
status: status,
67+
url,
68+
status,
7569
createdAt: new Date().toISOString(),
7670
updatedAt: new Date().toISOString(),
7771
};
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import { RequestHeaders } from "../../../constants/request-headers";
2+
import { SUPPLIERID } from "../../../constants/api-constants";
3+
import {
4+
ErrorMessageBody,
5+
PostMessageRequestBody,
6+
} from "../../../helpers/common-types";
7+
import { SupplierApiLetters } from "../../../helpers/generate-fetch-test-data";
8+
9+
export function postLettersRequestHeaders(): RequestHeaders {
10+
let requestHeaders: RequestHeaders;
11+
requestHeaders = {
12+
"NHSD-Supplier-ID": SUPPLIERID,
13+
"NHSD-Correlation-ID": "12344",
14+
"X-Request-ID": "requestId1",
15+
};
16+
return requestHeaders;
17+
}
18+
19+
export function postLettersInvalidRequestHeaders(): RequestHeaders {
20+
let requestHeaders: RequestHeaders;
21+
requestHeaders = {
22+
"NHSD-Supplier-ID": SUPPLIERID,
23+
"NHSD-Correlation-ID": "12344",
24+
// Request Id is missing
25+
};
26+
return requestHeaders;
27+
}
28+
29+
export function postValidRequestBody(
30+
letters: SupplierApiLetters[],
31+
): PostMessageRequestBody {
32+
let requestBody: PostMessageRequestBody;
33+
34+
requestBody = {
35+
data: [
36+
{
37+
type: "Letter",
38+
id: letters[0].id,
39+
attributes: {
40+
status: "ACCEPTED",
41+
},
42+
},
43+
{
44+
type: "Letter",
45+
id: letters[1].id,
46+
attributes: {
47+
status: "REJECTED",
48+
reasonCode: "R01",
49+
reasonText: "Test Reason",
50+
},
51+
},
52+
{
53+
type: "Letter",
54+
id: letters[2].id,
55+
attributes: {
56+
status: "PRINTED",
57+
},
58+
},
59+
{
60+
type: "Letter",
61+
id: letters[3].id,
62+
attributes: {
63+
status: "CANCELLED",
64+
},
65+
},
66+
],
67+
};
68+
return requestBody;
69+
}
70+
71+
export function postInvalidStatusRequestBody(
72+
letters: SupplierApiLetters[],
73+
): PostMessageRequestBody {
74+
let requestBody: PostMessageRequestBody;
75+
76+
requestBody = {
77+
data: [
78+
{
79+
type: "Letter",
80+
id: letters[0].id,
81+
attributes: {
82+
status: "ACCEPTED",
83+
},
84+
},
85+
{
86+
type: "Letter",
87+
id: letters[1].id,
88+
attributes: {
89+
status: "SENDING", // Invalid letter status
90+
},
91+
},
92+
],
93+
};
94+
return requestBody;
95+
}
96+
97+
export function postDuplicateIDRequestBody(
98+
letters: SupplierApiLetters[],
99+
): PostMessageRequestBody {
100+
let requestBody: PostMessageRequestBody;
101+
102+
requestBody = {
103+
data: [
104+
{
105+
type: "Letter",
106+
id: letters[0].id,
107+
attributes: {
108+
status: "ACCEPTED",
109+
},
110+
},
111+
{
112+
type: "Letter",
113+
id: letters[0].id, // Duplicate id
114+
attributes: {
115+
status: "REJECTED",
116+
},
117+
},
118+
],
119+
};
120+
return requestBody;
121+
}
122+
123+
export function postInvalidStatusResponseBody(): ErrorMessageBody {
124+
let responseBody: ErrorMessageBody;
125+
126+
responseBody = {
127+
errors: [
128+
{
129+
id: "12344",
130+
code: "NOTIFY_INVALID_REQUEST",
131+
links: {
132+
about:
133+
"https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier",
134+
},
135+
status: "400",
136+
title: "Invalid request",
137+
detail: "The request body is invalid",
138+
},
139+
],
140+
};
141+
return responseBody;
142+
}
143+
144+
export function postDuplicateIDResponseBody(): ErrorMessageBody {
145+
let responseBody: ErrorMessageBody;
146+
147+
responseBody = {
148+
errors: [
149+
{
150+
id: "12344",
151+
code: "NOTIFY_INVALID_REQUEST",
152+
links: {
153+
about:
154+
"https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier",
155+
},
156+
status: "400",
157+
title: "Invalid request",
158+
detail:
159+
"The request cannot include multiple letter objects with the same id",
160+
},
161+
],
162+
};
163+
return responseBody;
164+
}
165+
166+
export function post500ErrorResponseBody(): ErrorMessageBody {
167+
let responseBody: ErrorMessageBody;
168+
169+
responseBody = {
170+
errors: [
171+
{
172+
id: "12344",
173+
code: "NOTIFY_INTERNAL_SERVER_ERROR",
174+
links: {
175+
about:
176+
"https://digital.nhs.uk/developer/api-catalogue/nhs-notify-supplier",
177+
},
178+
status: "500",
179+
title: "Internal server error",
180+
detail: "Unexpected error",
181+
},
182+
],
183+
};
184+
return responseBody;
185+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { expect, test } from "@playwright/test";
2+
import { SUPPLIERID, SUPPLIER_LETTERS } from "../../constants/api-constants";
3+
import getRestApiGatewayBaseUrl from "../../helpers/aws-gateway-helper";
4+
import {
5+
post500ErrorResponseBody,
6+
postDuplicateIDRequestBody,
7+
postDuplicateIDResponseBody,
8+
postInvalidStatusRequestBody,
9+
postInvalidStatusResponseBody,
10+
postLettersRequestHeaders,
11+
postValidRequestBody,
12+
} from "./testCases/update-multiple-letter-status";
13+
import {
14+
createTestData,
15+
getLettersBySupplier,
16+
} from "../../helpers/generate-fetch-test-data";
17+
18+
let baseUrl: string;
19+
20+
test.beforeAll(async () => {
21+
baseUrl = await getRestApiGatewayBaseUrl();
22+
});
23+
24+
test.describe("API Gateway Tests to Verify post Status Endpoint", () => {
25+
test(`post /letters returns 202 and status is updated for multiple letters`, async ({
26+
request,
27+
}) => {
28+
await createTestData(SUPPLIERID, 4);
29+
const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 4);
30+
31+
if (!letters?.length) {
32+
test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`);
33+
return;
34+
}
35+
36+
const headers = postLettersRequestHeaders();
37+
const body = postValidRequestBody(letters);
38+
39+
const response = await request.post(`${baseUrl}/${SUPPLIER_LETTERS}`, {
40+
headers,
41+
data: body,
42+
});
43+
44+
expect(response.status()).toBe(202);
45+
});
46+
47+
test(`Post /letters returns 400 if request has invalid status`, async ({
48+
request,
49+
}) => {
50+
await createTestData(SUPPLIERID, 2);
51+
const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 2);
52+
53+
if (!letters?.length) {
54+
test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`);
55+
return;
56+
}
57+
58+
const headers = postLettersRequestHeaders();
59+
const body = postInvalidStatusRequestBody(letters);
60+
61+
const response = await request.post(`${baseUrl}/${SUPPLIER_LETTERS}`, {
62+
headers,
63+
data: body,
64+
});
65+
66+
const responseBody = await response.json();
67+
68+
expect(response.status()).toBe(400);
69+
expect(responseBody).toMatchObject(postInvalidStatusResponseBody());
70+
});
71+
72+
test(`Post /letters returns 400 if request has duplicate id`, async ({
73+
request,
74+
}) => {
75+
await createTestData(SUPPLIERID, 2);
76+
const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 2);
77+
78+
if (!letters?.length) {
79+
test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`);
80+
return;
81+
}
82+
83+
const headers = postRequestHeaders();
84+
const body = postDuplicateIDRequestBody(letters);
85+
86+
const response = await request.post(`${baseUrl}/${SUPPLIER_LETTERS}`, {
87+
headers,
88+
data: body,
89+
});
90+
91+
const responseBody = await response.json();
92+
93+
expect(response.status()).toBe(400);
94+
expect(responseBody).toMatchObject(postDuplicateIDResponseBody());
95+
});
96+
97+
test(`Post /letters returns 500 if request has invalid header`, async ({
98+
request,
99+
}) => {
100+
await createTestData(SUPPLIERID, 4);
101+
const letters = await getLettersBySupplier(SUPPLIERID, "PENDING", 4);
102+
103+
if (!letters?.length) {
104+
test.fail(true, `No PENDING letters found for supplier ${SUPPLIERID}`);
105+
return;
106+
}
107+
108+
const headers = postInvalidRequestHeaders();
109+
const body = postValidRequestBody(letters);
110+
111+
const response = await request.post(`${baseUrl}/${SUPPLIER_LETTERS}`, {
112+
headers,
113+
data: body,
114+
});
115+
116+
const responseBody = await response.json();
117+
118+
expect(response.status()).toBe(500);
119+
expect(responseBody).toMatchObject(post500ErrorResponseBody());
120+
});
121+
});

tests/helpers/common-types.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
export type PostMessageRequestBody = {
2+
data: PostLettersRequest[];
3+
};
4+
5+
type PostLettersRequest = {
6+
type: string;
7+
id: string;
8+
attributes: {
9+
reasonCode?: string;
10+
reasonText?: string;
11+
status: string;
12+
};
13+
};
14+
115
export type ErrorLink = {
216
about: string;
317
};

0 commit comments

Comments
 (0)