From a8c029e1e11b82a137a5109fe99c6639e93fe656 Mon Sep 17 00:00:00 2001
From: Ankur Jain <174601014+ankur-jain-nhs@users.noreply.github.com>
Date: Wed, 25 Mar 2026 13:21:54 +0000
Subject: [PATCH 1/5] AJ/KB Add support for care headers in RSV vaccine
---
.tool-versions | 1 +
.../eligibility/RSVEligibilityFallback.tsx | 5 +--
src/app/constants.ts | 1 -
.../content-api/parsers/custom/rsv.tsx | 39 ++++++++++++-------
wiremock/__files/rsv-vaccine.json | 2 +-
5 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/.tool-versions b/.tool-versions
index afe3f576..f108ae85 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -4,6 +4,7 @@ terraform 1.11.2
pre-commit 3.6.0
vale 3.6.0
nodejs 22.13.1
+gitleaks 8.30.1
# ==============================================================================
# The section below is reserved for Docker image versions.
diff --git a/src/app/_components/eligibility/RSVEligibilityFallback.tsx b/src/app/_components/eligibility/RSVEligibilityFallback.tsx
index f437434a..c23bdf97 100644
--- a/src/app/_components/eligibility/RSVEligibilityFallback.tsx
+++ b/src/app/_components/eligibility/RSVEligibilityFallback.tsx
@@ -1,8 +1,6 @@
-import { PharmacyBookingInfo } from "@src/app/_components/nbs/PharmacyBookingInfo";
import Expander from "@src/app/_components/nhs-frontend/Expander";
import NonUrgentCareCard from "@src/app/_components/nhs-frontend/NonUrgentCareCard";
import styles from "@src/app/_components/vaccine/styles.module.css";
-import { HEADINGS } from "@src/app/constants";
import { VaccineTypes } from "@src/models/vaccine";
import React, { JSX } from "react";
@@ -23,8 +21,7 @@ const RSVEligibilityFallback = (props: {
}
/>
-
-
+
);
diff --git a/src/app/constants.ts b/src/app/constants.ts
index a400d7ee..e43b3d47 100644
--- a/src/app/constants.ts
+++ b/src/app/constants.ts
@@ -7,5 +7,4 @@ export const HEADINGS = {
WHAT_VACCINE_IS_FOR: "What this vaccine is for",
WHO_SHOULD_HAVE_VACCINE: "Who should have this vaccine",
HOW_TO_GET_VACCINE: "How to get the vaccine",
- IF_THIS_APPLIES: "If this applies to you",
};
diff --git a/src/services/content-api/parsers/custom/rsv.tsx b/src/services/content-api/parsers/custom/rsv.tsx
index 4bf6a291..030971fe 100644
--- a/src/services/content-api/parsers/custom/rsv.tsx
+++ b/src/services/content-api/parsers/custom/rsv.tsx
@@ -1,3 +1,5 @@
+import { PharmacyBookingInfo } from "@src/app/_components/nbs/PharmacyBookingInfo";
+import { VaccineTypes } from "@src/models/vaccine";
import { ContentParsingError } from "@src/services/content-api/parsers/custom/exceptions";
import type { StyledPageSection, VaccinePageSection, VaccinePageSubsection } from "@src/services/content-api/types";
import { logger } from "@src/utils/logger";
@@ -7,9 +9,9 @@ import React from "react";
const log: Logger = logger.child({ module: "services-content-api-parsers-custom-rsv" });
-const olderAdultsRegExp: RegExp =
- /If you're aged \d+ to \d+(?: \(or turned \d+ after .*\))?<\/h3>((?:\s*
.*?<\/p>)+)/i;
-const paragraphsRegExp: RegExp = /
.*?<\/p>/g;
+const olderAdultsRegExp: RegExp = /
If you're aged \d+ or over<\/h3>((?:\s*
.*?<\/p>)+)/i;
+const olderAdultsInCareHomeRegExp: RegExp =
+ /
If you live in a care home for older adults<\/h3>((?:\s*
.*?<\/p>)+)/i;
export const styleHowToGetSubsection = (subsection: VaccinePageSubsection, index: number, fragile: boolean) => {
if (subsection.type !== "simpleElement") {
@@ -31,26 +33,35 @@ export const styleHowToGetSubsection = (subsection: VaccinePageSubsection, index
}
}
- const paragraphsMatches = olderAdultsMatches[1].match(paragraphsRegExp);
- if (!paragraphsMatches) {
+ const olderAdultsInCareHomeMatches = olderAdultsInCareHomeRegExp.exec(subsection.text);
+ if (!olderAdultsInCareHomeMatches) {
log.warn(
- { context: { text: olderAdultsMatches[1] } },
- "HowToGetSubsection paragraph not found - has the content changed?",
+ { context: { text: subsection.text } },
+ "HowToGetSubsection care home header not found - has the content changed?",
);
if (fragile) {
- throw new ContentParsingError("HowToGetSubsection paragraph not found - has the content changed?");
+ throw new ContentParsingError("HowToGetSubsection care home header not found - has the content changed?");
} else {
return <>>;
}
}
return (
-
+ <>
+
+
+
+ >
);
};
diff --git a/wiremock/__files/rsv-vaccine.json b/wiremock/__files/rsv-vaccine.json
index 46f14043..78eae5be 100644
--- a/wiremock/__files/rsv-vaccine.json
+++ b/wiremock/__files/rsv-vaccine.json
@@ -304,7 +304,7 @@
{
"position": 0,
"identifier": "1",
- "text": "There are different ways to get the RSV vaccine.
If you're pregnant
You should be offered the RSV vaccine around the time of your 28-week antenatal appointment.
Getting vaccinated as soon as possible from 28 weeks will provide the best protection for your baby. But the vaccine can be given later if needed, including up until you go into labour.
Speak to your maternity service or GP surgery if you're 28 weeks pregnant or more and have not been offered the vaccine.
If you're aged 75 to 79 (or turned 80 after 1 September 2024)
If you're aged 75 to 79 (or turned 80 after 1 September 2024) contact your GP surgery to book your RSV vaccination.
Your GP surgery may contact you about getting the RSV vaccine. This may be by letter, text, phone call or email.
You do not need to wait to be contacted before booking your vaccination.
",
+ "text": "There are different ways to get the RSV vaccine.
If you're pregnant
You should be offered the RSV vaccine around the time of your 28-week antenatal appointment.
Getting vaccinated as soon as possible from 28 weeks will provide the best protection for your baby. But the vaccine can be given later if needed, including up until you go into labour.
Speak to your maternity service or GP surgery if you're 28 weeks pregnant or more and have not been offered the vaccine.
If you're aged 75 or over
Contact your GP surgery to book your RSV vaccination.
Your GP surgery may contact you about getting the RSV vaccine. This may be by letter, text, phone call or email.
You do not need to wait to be contacted before booking your vaccination.
If you live in a care home for older adults
Speak to a member of staff at your care home or your GP surgery about how to get the RSV vaccine.
Your GP surgery may contact you about getting the RSV vaccine. This may be by letter, text, phone call or email.
",
"@type": "WebPageElement",
"name": "markdown",
"headline": ""
From ba8e56b78f6d7330df354497c28bec70bfe20498 Mon Sep 17 00:00:00 2001
From: Ankur Jain <174601014+ankur-jain-nhs@users.noreply.github.com>
Date: Wed, 25 Mar 2026 14:49:50 +0000
Subject: [PATCH 2/5] AJ/KB Display the rsv eligibility fallback as per new
content
---
.../RSVEligibilityFallback.test.tsx | 29 ++-----------------
.../parsers/content-styling-service.test.tsx | 10 +++++--
.../content-api/parsers/custom/both.test.tsx | 21 +++++---------
.../content-api/parsers/custom/rsv.tsx | 6 ++--
4 files changed, 19 insertions(+), 47 deletions(-)
diff --git a/src/app/_components/eligibility/RSVEligibilityFallback.test.tsx b/src/app/_components/eligibility/RSVEligibilityFallback.test.tsx
index 9317a9eb..6a52fc88 100644
--- a/src/app/_components/eligibility/RSVEligibilityFallback.test.tsx
+++ b/src/app/_components/eligibility/RSVEligibilityFallback.test.tsx
@@ -1,22 +1,13 @@
import { RSVEligibilityFallback } from "@src/app/_components/eligibility/RSVEligibilityFallback";
-import { PharmacyBookingInfo } from "@src/app/_components/nbs/PharmacyBookingInfo";
import { VaccineTypes } from "@src/models/vaccine";
import { render, screen, within } from "@testing-library/react";
-jest.mock("@src/app/_components/nbs/PharmacyBookingInfo", () => ({
- PharmacyBookingInfo: jest
- .fn()
- .mockImplementation(() => Pharmacy booking test
),
-}));
-
describe("RSVEligibilityFallback", () => {
const vaccineType = VaccineTypes.RSV;
const howToGetVaccineFallback = How Section styled component
;
it("should display fallback care card", async () => {
- await render(
- ,
- );
+ render();
const fallbackHeading: HTMLElement = screen.getByText("The RSV vaccine is recommended if you:");
const fallbackBulletPoint1: HTMLElement = screen.getByText("are aged 75 or over");
@@ -27,27 +18,13 @@ describe("RSVEligibilityFallback", () => {
expect(fallbackBulletPoint2).toBeVisible();
});
- it("should include Pharmacy booking info for specified vaccine", () => {
- render();
-
- const pharmacyBookingInfo: HTMLElement = screen.getByTestId("pharmacy-booking-info");
- expect(pharmacyBookingInfo).toBeVisible();
-
- expect(PharmacyBookingInfo).toHaveBeenCalledWith(
- {
- vaccineType: vaccineType,
- },
- undefined,
- );
- });
-
- it("should display 'If this applies' paragraph with provided how-to-get content", async () => {
+ it("should display provided how-to-get content", async () => {
render();
const fallback = screen.getByTestId("elid-fallback");
const fallbackHeading: HTMLElement = within(fallback).getByRole("heading", {
- name: "If this applies to you",
+ name: "",
level: 3,
});
const howToGetContent: HTMLElement = within(fallback).getByText("How Section styled component");
diff --git a/src/services/content-api/parsers/content-styling-service.test.tsx b/src/services/content-api/parsers/content-styling-service.test.tsx
index aad8b25f..9c6ab5f6 100644
--- a/src/services/content-api/parsers/content-styling-service.test.tsx
+++ b/src/services/content-api/parsers/content-styling-service.test.tsx
@@ -20,6 +20,9 @@ const mockNBSBookingActionHTML = "NBS Booking Link Test";
jest.mock("@src/app/_components/nbs/NBSBookingAction", () => ({
NBSBookingAction: () => mockNBSBookingActionHTML,
}));
+jest.mock("@src/app/_components/nbs/PharmacyBookingInfo", () => ({
+ PharmacyBookingInfo: () => Pharmacy Booking Info
,
+}));
jest.mock("sanitize-data", () => ({ sanitize: jest.fn() }));
describe("ContentStylingService", () => {
@@ -32,7 +35,7 @@ describe("ContentStylingService", () => {
const mockRsvMarkdownSubsection: VaccinePageSubsection = {
type: "simpleElement",
- text: "para
If you're aged 75 to 79
para1
para2
If you're pregnant
para3
para4
",
+ text: "para
If you're aged 75 or over
para1
para2
If you live in a care home for older adults
para3
para4
If you're pregnant
para5
para6
",
name: "markdown",
headline: "Headline",
};
@@ -209,8 +212,9 @@ describe("ContentStylingService", () => {
expect(styledVaccineContent.whoVaccineIsFor.heading).toEqual("Who is this Vaccine For");
expect(styledVaccineContent.howToGetVaccine.heading).toEqual("How to get this Vaccine");
- const expectedRsvSection = "";
- const expectedRsvPregnancySection = ``;
+ const expectedRsvSection =
+ "If you're aged 75 or over
para1
para2
Pharmacy Booking Info
If you live in a care home for older adults
para3
para4
";
+ const expectedRsvPregnancySection = ``;
const { container } = render(styledVaccineContent.howToGetVaccine.component);
if (vaccine === VaccineTypes.RSV) {
expect(container).toContainHTML(expectedRsvSection);
diff --git a/src/services/content-api/parsers/custom/both.test.tsx b/src/services/content-api/parsers/custom/both.test.tsx
index c721604b..a94df050 100644
--- a/src/services/content-api/parsers/custom/both.test.tsx
+++ b/src/services/content-api/parsers/custom/both.test.tsx
@@ -6,6 +6,9 @@ import { render } from "@testing-library/react";
import React from "react";
const mockNBSBookingActionHTML = "NBS Booking Link Test";
+jest.mock("@src/app/_components/nbs/PharmacyBookingInfo", () => ({
+ PharmacyBookingInfo: () => test
,
+}));
jest.mock("@src/app/_components/nbs/NBSBookingAction", () => ({
NBSBookingAction: () => mockNBSBookingActionHTML,
}));
@@ -26,14 +29,7 @@ const mockRsvInPregnancySubsection: VaccinePageSubsection = {
const mockRsvForOlderAdultsSubsection: VaccinePageSubsection = {
type: "simpleElement",
- text: "If you're aged 75 to 79
Paragraph 1
Paragraph 2
",
- headline: "",
- name: "",
-};
-
-const mockRsvForOlderAdultsNewerSubsection: VaccinePageSubsection = {
- type: "simpleElement",
- text: "If you're aged 75 to 79 (or turned 80 after 1 September 2024)
Paragraph 1
Paragraph 2
",
+ text: "If you're aged 75 or over
Paragraph 1
Paragraph 2
If you live in a care home for older adults
Paragraph 3
Paragraph 4
",
headline: "",
name: "",
};
@@ -63,12 +59,9 @@ describe("styleHowToGetSubsection for rsv in older adults", () => {
it("renders HTML if subsection contains rsv for older adults", () => {
const { container } = render(<>{styleHowToGetSubsectionForRsv(mockRsvForOlderAdultsSubsection, 0, false)}>);
- expect(container.innerHTML).toBe("");
- });
-
- it("renders HTML if newer subsection contains rsv for older adults", () => {
- const { container } = render(<>{styleHowToGetSubsectionForRsv(mockRsvForOlderAdultsNewerSubsection, 0, false)}>);
- expect(container.innerHTML).toBe("");
+ expect(container.innerHTML).toBe(
+ 'If you\'re aged 75 or over
Paragraph 1
Paragraph 2
test
If you live in a care home for older adults
Paragraph 3
Paragraph 4
',
+ );
});
});
diff --git a/src/services/content-api/parsers/custom/rsv.tsx b/src/services/content-api/parsers/custom/rsv.tsx
index 030971fe..613ce621 100644
--- a/src/services/content-api/parsers/custom/rsv.tsx
+++ b/src/services/content-api/parsers/custom/rsv.tsx
@@ -47,21 +47,19 @@ export const styleHowToGetSubsection = (subsection: VaccinePageSubsection, index
}
return (
- <>
+
);
};
From 00ae00d39d8ff87352740ecb2d9b904fdfdcc1ca Mon Sep 17 00:00:00 2001
From: Ankur Jain <174601014+ankur-jain-nhs@users.noreply.github.com>
Date: Wed, 25 Mar 2026 17:33:00 +0000
Subject: [PATCH 3/5] AJ/KB Update E2E tests for new EliD content
---
e2e/elid-copy-helper.ts | 4 ++--
e2e/general/eligibility.spec.ts | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/e2e/elid-copy-helper.ts b/e2e/elid-copy-helper.ts
index 83fa6307..8ce2ca35 100644
--- a/e2e/elid-copy-helper.ts
+++ b/e2e/elid-copy-helper.ts
@@ -20,12 +20,12 @@ export const elidCopyThatDiffersByEnvironment: Record = {
},
["integration"]: {
user15: {
- bulletPoint2: "did not turn 80 after 1 September 2024",
+ bulletPoint2: "do not live in a care home for older adults",
infoTextHeading: "If you think this is incorrect",
infoTextParagraph: "Speak to your healthcare professional if you think you should be offered this vaccine.",
},
user01: {
- bulletPoint1: "are aged between 75 and 79",
+ bulletPoint1: "are aged between 75 or over",
},
user13: {
cardParagraphTextv1: "We believe you had the RSV vaccination on 3 April 2025.",
diff --git a/e2e/general/eligibility.spec.ts b/e2e/general/eligibility.spec.ts
index bb139679..2df58502 100644
--- a/e2e/general/eligibility.spec.ts
+++ b/e2e/general/eligibility.spec.ts
@@ -28,7 +28,7 @@ test.describe("Eligibility", () => {
level: 2,
name: "We do not believe you can have it",
});
- const bulletPoint1: Locator = eligibility.getByText("are not aged 75 to 79", { exact: true }).first();
+ const bulletPoint1: Locator = eligibility.getByText("are not aged 75 or over", { exact: true }).first();
const bulletPoint2: Locator = eligibility
.getByText(elidCopyForEnvironment.user15.bulletPoint2, { exact: true })
.first();
From 861212b8ac9d9c82fcab2c4e9fbb84ba3456be7f Mon Sep 17 00:00:00 2001
From: Ankur Jain <174601014+ankur-jain-nhs@users.noreply.github.com>
Date: Wed, 25 Mar 2026 17:55:55 +0000
Subject: [PATCH 4/5] AJ/KB Update E2E tests for new EliD content
---
e2e/elid-copy-helper.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/e2e/elid-copy-helper.ts b/e2e/elid-copy-helper.ts
index 8ce2ca35..e7685370 100644
--- a/e2e/elid-copy-helper.ts
+++ b/e2e/elid-copy-helper.ts
@@ -25,7 +25,7 @@ export const elidCopyThatDiffersByEnvironment: Record = {
infoTextParagraph: "Speak to your healthcare professional if you think you should be offered this vaccine.",
},
user01: {
- bulletPoint1: "are aged between 75 or over",
+ bulletPoint1: "are aged 75 or over",
},
user13: {
cardParagraphTextv1: "We believe you had the RSV vaccination on 3 April 2025.",
From 812cf1842359ef4bcf9edf5a79d2a547a35d4fd8 Mon Sep 17 00:00:00 2001
From: Ankur Jain <174601014+ankur-jain-nhs@users.noreply.github.com>
Date: Tue, 31 Mar 2026 11:45:10 +0100
Subject: [PATCH 5/5] FIX SP/DB Use local typescript module for tsc precommit
type checking
---
.github/workflows/stage-1-commit.yaml | 2 +-
scripts/config/pre-commit.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml
index 7b0e2a4e..b4d7f966 100644
--- a/.github/workflows/stage-1-commit.yaml
+++ b/.github/workflows/stage-1-commit.yaml
@@ -144,7 +144,7 @@ jobs:
npm ci --strict-peer-deps
- name: "Check types with tsc"
run: |
- tsc --noEmit
+ npx tsc --noEmit
- name: "Run linting check"
run: |
make test-lint
diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml
index 1fd6a7fd..0211b575 100644
--- a/scripts/config/pre-commit.yaml
+++ b/scripts/config/pre-commit.yaml
@@ -3,7 +3,7 @@ repos:
hooks:
- id: check-types
name: Check types with tsc
- entry: tsc --noEmit
+ entry: npx tsc --noEmit
language: system
pass_filenames: false
- id: run-prettier