Skip to content

Commit 2a23de4

Browse files
VIA-630 Calculate age group of user and save on session
1 parent 5f4e0a5 commit 2a23de4

File tree

8 files changed

+118
-6
lines changed

8 files changed

+118
-6
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { getAgeGroup } from "@src/app/_components/hub/ageGroupHelper";
2+
import { AgeGroup } from "@src/models/ageBasedHub";
3+
4+
describe("Age group helper", () => {
5+
const expectedGroupsForEachAge = [
6+
{ age: 12, expectedAgeGroup: AgeGroup.AGE_12_to_16 },
7+
{ age: 16, expectedAgeGroup: AgeGroup.AGE_12_to_16 },
8+
{ age: 17, expectedAgeGroup: AgeGroup.AGE_17_to_24 },
9+
{ age: 24, expectedAgeGroup: AgeGroup.AGE_17_to_24 },
10+
{ age: 25, expectedAgeGroup: AgeGroup.AGE_25_to_64 },
11+
{ age: 64, expectedAgeGroup: AgeGroup.AGE_25_to_64 },
12+
{ age: 65, expectedAgeGroup: AgeGroup.AGE_65_to_74 },
13+
{ age: 74, expectedAgeGroup: AgeGroup.AGE_65_to_74 },
14+
{ age: 75, expectedAgeGroup: AgeGroup.AGE_75_to_80 },
15+
];
16+
17+
it.each(expectedGroupsForEachAge)(`returns $expectedAgeGroup for user age $age`, ({ age, expectedAgeGroup }) => {
18+
expect(getAgeGroup(age)).toEqual(expectedAgeGroup);
19+
});
20+
21+
it("returns unknown age group when age not in defined ranges", () => {
22+
expect(getAgeGroup(6)).toBe(AgeGroup.UNKNOWN_AGE_GROUP);
23+
});
24+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { AgeGroup } from "@src/models/ageBasedHub";
2+
3+
const getAgeGroup = (age: number): AgeGroup => {
4+
if (12 <= age && age <= 16) {
5+
return AgeGroup.AGE_12_to_16;
6+
}
7+
if (17 <= age && age <= 24) {
8+
return AgeGroup.AGE_17_to_24;
9+
}
10+
if (25 <= age && age <= 64) {
11+
return AgeGroup.AGE_25_to_64;
12+
}
13+
if (65 <= age && age <= 74) {
14+
return AgeGroup.AGE_65_to_74;
15+
}
16+
if (75 <= age && age <= 80) {
17+
return AgeGroup.AGE_75_to_80;
18+
}
19+
if (81 <= age) {
20+
return AgeGroup.AGE_81_PLUS;
21+
} else return AgeGroup.UNKNOWN_AGE_GROUP;
22+
};
23+
24+
export { getAgeGroup };

src/app/_components/inactivity/InactivityDialog.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import { InactivityDialog } from "@src/app/_components/inactivity/InactivityDialog";
22
import { unprotectedUrlPaths } from "@src/app/_components/inactivity/constants";
3+
import { AgeGroup } from "@src/models/ageBasedHub";
34
import { NhsNumber } from "@src/models/vaccine";
45
import useInactivityTimer from "@src/utils/auth/inactivity-timer";
6+
import { Age } from "@src/utils/auth/types";
57
import { userLogout } from "@src/utils/auth/user-logout";
68
import { render, screen } from "@testing-library/react";
79
import { Session } from "next-auth";
8-
import { Age } from "@src/utils/auth/types";
910

1011
const mockSessionValue: Partial<Session> = {
1112
expires: new Date(Date.now() + 60000).toISOString(),
1213
user: {
1314
nhs_number: "" as NhsNumber,
1415
age: 20 as Age,
16+
age_group: AgeGroup.AGE_17_to_24,
1517
},
1618
};
1719
let mockSession = { data: mockSessionValue, status: "authenticated" };

src/models/ageBasedHub.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { VaccineType } from "@src/models/vaccine";
2+
3+
enum AgeGroup {
4+
AGE_12_to_16 = "AGE_12_to_16",
5+
AGE_17_to_24 = "AGE_17_to_24",
6+
AGE_25_to_64 = "AGE_25_to_64",
7+
AGE_65_to_74 = "AGE_65_to_74",
8+
AGE_75_to_80 = "AGE_75_to_80",
9+
AGE_81_PLUS = "AGE_81_PLUS",
10+
UNKNOWN_AGE_GROUP = "UNKNOWN_AGE_GROUP",
11+
}
12+
13+
type AgeSpecificVaccineCardDetails = {
14+
vaccineName: VaccineType;
15+
cardLinkDescription: string;
16+
};
17+
18+
type AgeBasedHubDetails = {
19+
heading: string;
20+
vaccines: AgeSpecificVaccineCardDetails[];
21+
};
22+
23+
// TODO: VIA-630 remove 'undefined' from the type definition below after all hubs are implemented?
24+
const AgeBasedHubInfo: Record<AgeGroup, AgeBasedHubDetails | undefined> = {
25+
AGE_12_to_16: undefined,
26+
AGE_17_to_24: undefined,
27+
AGE_25_to_64: undefined,
28+
AGE_65_to_74: {
29+
heading: "Adults aged 65 to 74 should get these routine vaccines",
30+
vaccines: [
31+
{ vaccineName: VaccineType.PNEUMOCOCCAL, cardLinkDescription: "65 years and over" },
32+
{ vaccineName: VaccineType.FLU_FOR_ADULTS, cardLinkDescription: "65 years and over" },
33+
{ vaccineName: VaccineType.SHINGLES, cardLinkDescription: "65 to 67 and 70 to 79 years" },
34+
],
35+
},
36+
AGE_75_to_80: undefined,
37+
AGE_81_PLUS: undefined,
38+
UNKNOWN_AGE_GROUP: undefined,
39+
};
40+
41+
export { AgeGroup, AgeBasedHubInfo };

src/utils/auth/callbacks/get-updated-session.test.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { getAgeGroup } from "@src/app/_components/hub/ageGroupHelper";
2+
import { AgeGroup } from "@src/models/ageBasedHub";
13
import { NhsNumber } from "@src/models/vaccine";
24
import { getUpdatedSession } from "@src/utils/auth/callbacks/get-updated-session";
35
import { AccessToken, Age, BirthDate, ExpiresAt, IdToken } from "@src/utils/auth/types";
@@ -7,20 +9,24 @@ import { JWT } from "next-auth/jwt";
79

810
jest.mock("sanitize-data", () => ({ sanitize: jest.fn() }));
911
jest.mock("@src/utils/date", () => ({ calculateAge: jest.fn() }));
12+
jest.mock("@src/app/_components/hub/ageGroupHelper.ts", () => ({ getAgeGroup: jest.fn() }));
1013

1114
const mockBirthdate = "1995-01-01";
1215
const mockCalculatedAge = 30;
16+
const mockAgeGroup = AgeGroup.AGE_75_to_80;
1317

14-
describe("getSession", () => {
18+
describe("getUpdatedSession", () => {
1519
beforeEach(() => {
1620
(calculateAge as jest.Mock).mockImplementation(() => mockCalculatedAge);
21+
(getAgeGroup as jest.Mock).mockImplementation(() => mockAgeGroup);
1722
});
1823

19-
it("updates session user fields from token when both defined", () => {
24+
it("updates session with user fields and age information from token", () => {
2025
const session: Session = {
2126
user: {
2227
nhs_number: "" as NhsNumber,
2328
age: 0 as Age,
29+
age_group: undefined,
2430
},
2531
expires: "some-date",
2632
};
@@ -43,13 +49,15 @@ describe("getSession", () => {
4349

4450
expect(result.user.nhs_number).toBe("test-nhs-number");
4551
expect(result.user.age).toBe(mockCalculatedAge);
52+
expect(result.user.age_group).toBe(mockAgeGroup);
4653
});
4754

4855
it("does not update session if token.user is missing", () => {
4956
const session: Session = {
5057
user: {
5158
nhs_number: "old-nhs-number" as NhsNumber,
5259
age: 36 as Age,
60+
age_group: AgeGroup.AGE_25_to_64,
5361
},
5462
expires: "some-date",
5563
};
@@ -60,6 +68,7 @@ describe("getSession", () => {
6068

6169
expect(result.user.nhs_number).toBe("old-nhs-number");
6270
expect(result.user.age).toBe(36);
71+
expect(result.user.age_group).toBe(AgeGroup.AGE_25_to_64);
6372
});
6473

6574
it("does not update session if session.user is missing", () => {

src/utils/auth/callbacks/get-updated-session.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import { getAgeGroup } from "@src/app/_components/hub/ageGroupHelper";
2+
import { calculateAge } from "@src/utils/date";
13
import { logger } from "@src/utils/logger";
24
import { Session } from "next-auth";
35
import { JWT } from "next-auth/jwt";
46
import { Logger } from "pino";
5-
import { calculateAge } from "@src/utils/date";
67

78
const log: Logger = logger.child({
89
module: "utils-auth-callbacks-get-session",
@@ -12,6 +13,7 @@ const getUpdatedSession = (session: Session, token: JWT): Session => {
1213
if (token?.user && session.user) {
1314
session.user.nhs_number = token.user.nhs_number;
1415
session.user.age = calculateAge(token.user.birthdate);
16+
session.user.age_group = getAgeGroup(session.user.age);
1517
} else {
1618
log.info(
1719
{

src/utils/auth/types.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AgeGroup } from "@src/models/ageBasedHub";
12
import { NhsNumber } from "@src/models/vaccine";
23
import { Brand } from "@src/utils/types";
34
import type { DefaultSession } from "next-auth";
@@ -45,7 +46,8 @@ declare module "next-auth" {
4546
interface Session {
4647
user: {
4748
nhs_number: NhsNumber;
48-
age: Age;
49+
age?: Age;
50+
age_group?: undefined | AgeGroup;
4951
} & DefaultSession["user"];
5052
}
5153

src/utils/date.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,16 @@ describe("utils-date", () => {
6565
});
6666
});
6767
describe("calculateAge", () => {
68+
beforeAll(() => {
69+
jest.useFakeTimers();
70+
});
71+
6872
beforeEach(() => {
69-
jest.useFakeTimers().setSystemTime(new Date("2025-01-15T00:00:00.000Z").getTime());
73+
jest.setSystemTime(new Date("2025-01-15T00:00:00.000Z").getTime());
74+
});
75+
76+
afterAll(() => {
77+
jest.useRealTimers();
7078
});
7179

7280
it("should return age based on birthdate", () => {

0 commit comments

Comments
 (0)