Skip to content

Commit 629aa98

Browse files
MWClayson-NHSCopilot
andcommitted
copilot comment
Co-authored-by: Copilot <copilot@github.com>
1 parent 368486d commit 629aa98

2 files changed

Lines changed: 81 additions & 3 deletions

File tree

application/CohortManager/src/Web/app/lib/removeDummyGpCode.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@ jest.mock("./formValidationSchemas", () => {
2525
});
2626

2727
import { removeDummyGpCode } from "./removeDummyGpCode";
28+
import { auth } from "./auth";
2829
import { redirect } from "next/navigation";
2930

3031
const mockRedirect = redirect as jest.MockedFunction<typeof redirect>;
32+
const mockAuth = auth as jest.MockedFunction<typeof auth>;
3133

3234
describe("removeDummyGpCode", () => {
3335
beforeEach(() => {
3436
jest.clearAllMocks();
3537
process.env.REMOVE_DUMMY_GP_CODE_API_URL = "https://api.example.com";
38+
mockAuth.mockResolvedValue({
39+
idToken: "id-token",
40+
accessToken: "access-token",
41+
} as Awaited<ReturnType<typeof auth>>);
3642
global.fetch = jest.fn();
3743
});
3844

@@ -167,6 +173,8 @@ describe("removeDummyGpCode", () => {
167173
method: "POST",
168174
headers: {
169175
"Content-Type": "application/json",
176+
Authorization: "Bearer id-token",
177+
"X-Access-Token": "Bearer access-token",
170178
},
171179
body: JSON.stringify({
172180
nhs_number: "1234567890",
@@ -210,6 +218,64 @@ describe("removeDummyGpCode", () => {
210218
});
211219

212220
describe("unexpected errors", () => {
221+
it("returns session error when auth tokens are missing", async () => {
222+
mockSafeParse.mockReturnValue({
223+
success: true,
224+
data: {
225+
nhsNumber: "1234567890",
226+
forename: "Jane",
227+
surname: "Smith",
228+
dateOfBirth: "1990-01-15",
229+
serviceNowTicketNumber: "CS1234567",
230+
},
231+
});
232+
233+
mockAuth.mockResolvedValue({
234+
idToken: undefined,
235+
accessToken: "access-token",
236+
} as Awaited<ReturnType<typeof auth>>);
237+
238+
const formData = createFormData();
239+
const result = await removeDummyGpCode(null, formData);
240+
241+
expect(result).toEqual({
242+
error: "Your session has expired or is invalid. Please sign in again.",
243+
values: expect.objectContaining({ nhsNumber: "1234567890" }),
244+
});
245+
expect(fetch).not.toHaveBeenCalled();
246+
});
247+
248+
it("returns session error for 401/403 responses", async () => {
249+
mockSafeParse.mockReturnValue({
250+
success: true,
251+
data: {
252+
nhsNumber: "1234567890",
253+
forename: "Jane",
254+
surname: "Smith",
255+
dateOfBirth: "1990-01-15",
256+
serviceNowTicketNumber: "CS1234567",
257+
},
258+
});
259+
260+
global.fetch = jest
261+
.fn()
262+
.mockResolvedValueOnce({ status: 401 })
263+
.mockResolvedValueOnce({ status: 403 });
264+
265+
const formData = createFormData();
266+
const firstResult = await removeDummyGpCode(null, formData);
267+
const secondResult = await removeDummyGpCode(null, formData);
268+
269+
expect(firstResult).toEqual({
270+
error: "Your session has expired or is invalid. Please sign in again.",
271+
values: expect.objectContaining({ nhsNumber: "1234567890" }),
272+
});
273+
expect(secondResult).toEqual({
274+
error: "Your session has expired or is invalid. Please sign in again.",
275+
values: expect.objectContaining({ nhsNumber: "1234567890" }),
276+
});
277+
});
278+
213279
it("returns error state with generic message on non-202/non-400 response", async () => {
214280
mockSafeParse.mockReturnValue({
215281
success: true,

application/CohortManager/src/Web/app/lib/removeDummyGpCode.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,16 @@ export async function removeDummyGpCode(
7777
"Content-Type": "application/json",
7878
};
7979

80-
if (bearerToken && accessToken) {
81-
headers.Authorization = `Bearer ${bearerToken}`;
82-
headers["X-Access-Token"] = `Bearer ${accessToken}`;
80+
if (!bearerToken || !accessToken) {
81+
return {
82+
error: "Your session has expired or is invalid. Please sign in again.",
83+
values: submittedValues,
84+
};
8385
}
8486

87+
headers.Authorization = `Bearer ${bearerToken}`;
88+
headers["X-Access-Token"] = `Bearer ${accessToken}`;
89+
8590
let response: Response;
8691
try {
8792
response = await fetch(apiUrl, {
@@ -107,5 +112,12 @@ export async function removeDummyGpCode(
107112
return { error: "The participant could not be found or the details provided do not match", values: submittedValues };
108113
}
109114

115+
if (response.status === 401 || response.status === 403) {
116+
return {
117+
error: "Your session has expired or is invalid. Please sign in again.",
118+
values: submittedValues,
119+
};
120+
}
121+
110122
return { error: "An unexpected error occurred. Please try again later.", values: submittedValues };
111123
}

0 commit comments

Comments
 (0)