|
1 | 1 | import { MoreInformation } from "@src/app/_components/content/MoreInformation"; |
2 | 2 | import { VaccineType } from "@src/models/vaccine"; |
| 3 | +import { ActionDisplayType, ButtonUrl, Content, Label } from "@src/services/eligibility-api/types"; |
3 | 4 | import { Campaigns } from "@src/utils/campaigns/types"; |
4 | 5 | import config from "@src/utils/config"; |
5 | 6 | import { ConfigMock, configBuilder } from "@test-data/config/builders"; |
6 | | -import { mockStyledContent, mockStyledContentWithoutWhatSection } from "@test-data/content-api/data"; |
| 7 | +import { |
| 8 | + genericVaccineContentAPIResponse, |
| 9 | + mockStyledContent, |
| 10 | + mockStyledContentWithoutWhatSection, |
| 11 | +} from "@test-data/content-api/data"; |
7 | 12 | import { render, screen } from "@testing-library/react"; |
| 13 | +import { headers } from "next/headers"; |
8 | 14 |
|
9 | 15 | jest.mock("sanitize-data", () => ({ sanitize: jest.fn() })); |
10 | 16 | jest.mock("@src/utils/config"); |
| 17 | +jest.mock("next/headers"); |
| 18 | + |
| 19 | +describe("MoreInformation for COVID", () => { |
| 20 | + const mockedConfig = config as ConfigMock; |
| 21 | + const covid19VaccineType: VaccineType = VaccineType.COVID_19; |
| 22 | + |
| 23 | + beforeEach(() => { |
| 24 | + const defaultConfig = configBuilder() |
| 25 | + .withCampaigns( |
| 26 | + Campaigns.fromJson( |
| 27 | + JSON.stringify({ |
| 28 | + COVID_19: [ |
| 29 | + { start: "2025-11-01T09:00:00Z", end: "2026-01-31T09:00:00Z" }, |
| 30 | + { start: "2026-11-01T09:00:00Z", end: "2027-01-31T09:00:00Z" }, |
| 31 | + ], |
| 32 | + }), |
| 33 | + )!, |
| 34 | + ) |
| 35 | + .build(); |
| 36 | + Object.assign(mockedConfig, defaultConfig); |
| 37 | + |
| 38 | + const mockHeaders = { |
| 39 | + get: jest.fn(), |
| 40 | + }; |
| 41 | + (headers as jest.Mock).mockResolvedValue(mockHeaders); |
| 42 | + }); |
| 43 | + |
| 44 | + jest.useFakeTimers(); |
| 45 | + |
| 46 | + it("should return standard vaccine content and additional content for COVID-19 vaccine", async () => { |
| 47 | + jest.setSystemTime(new Date("2025-10-01")); |
| 48 | + |
| 49 | + render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: covid19VaccineType })); |
| 50 | + |
| 51 | + // COVID-19 vaccine content (closed campaign) |
| 52 | + expectExpanderBlockToBePresent("How to get the vaccine", "How Section styled component"); |
| 53 | + expectExpanderBlockToBePresent("Callout Heading", ""); |
| 54 | + // expect(pageCopyForCovid19Vaccine.recommendation?.heading).toEqual("The COVID-19 vaccine is recommended if you:"); |
| 55 | + }); |
| 56 | + |
| 57 | + it("should return a callout but no actions when no campaign is active", async () => { |
| 58 | + // Given |
| 59 | + jest.setSystemTime(new Date("2025-10-01")); |
| 60 | + |
| 61 | + const expected = { |
| 62 | + callout: { |
| 63 | + heading: "Booking service closed", |
| 64 | + content: |
| 65 | + "You can no longer book a COVID-19 vaccination using this online service\n\n" + |
| 66 | + "Bookings can also no longer be made through the 119 service.\n\n" + |
| 67 | + "COVID-19 vaccinations will be available again in spring.", |
| 68 | + contentType: "markdown", |
| 69 | + }, |
| 70 | + }; |
| 71 | + |
| 72 | + // When |
| 73 | + const pageCopy = await buildFilteredContentForCovid19Vaccine(JSON.stringify(genericVaccineContentAPIResponse)); |
| 74 | + |
| 75 | + // Then |
| 76 | + expect(pageCopy).toEqual(expect.objectContaining(expected)); |
| 77 | + expect(pageCopy.actions).toHaveLength(0); |
| 78 | + }); |
| 79 | + |
| 80 | + it("should return actions but no callout when no campaign is active", async () => { |
| 81 | + // Given |
| 82 | + jest.setSystemTime(new Date("2025-12-01")); |
| 83 | + |
| 84 | + const expected = { |
| 85 | + actions: [ |
| 86 | + { |
| 87 | + type: ActionDisplayType.buttonWithInfo, |
| 88 | + content: "## If this applies to you\n\n### Book an appointment online at a pharmacy" as Content, |
| 89 | + button: { |
| 90 | + label: "Continue to booking" as Label, |
| 91 | + url: new URL("https://test-nbs-url.example.com/sausages") as ButtonUrl, |
| 92 | + }, |
| 93 | + delineator: true, |
| 94 | + }, |
| 95 | + { |
| 96 | + type: ActionDisplayType.actionLinkWithInfo, |
| 97 | + content: ("## Get vaccinated without an appointment\n\n" + |
| 98 | + "You can find a walk-in COVID-19 vaccination site to get a vaccination without an appointment. " + |
| 99 | + "You do not need to be registered with a GP.") as Content, |
| 100 | + button: { |
| 101 | + label: "Find a walk-in COVID-19 vaccination site" as Label, |
| 102 | + url: new URL( |
| 103 | + "https://www.nhs.uk/nhs-services/vaccination-and-booking-services/find-a-walk-in-covid-19-vaccination-site/", |
| 104 | + ) as ButtonUrl, |
| 105 | + }, |
| 106 | + delineator: false, |
| 107 | + }, |
| 108 | + ], |
| 109 | + }; |
| 110 | + |
| 111 | + // When |
| 112 | + const pageCopy = await buildFilteredContentForCovid19Vaccine(JSON.stringify(genericVaccineContentAPIResponse)); |
| 113 | + |
| 114 | + // Then |
| 115 | + expect(pageCopy).toEqual(expect.objectContaining(expected)); |
| 116 | + expect(pageCopy.callout).toBeUndefined(); |
| 117 | + }); |
| 118 | + |
| 119 | + describe("with x-e2e-datetime header set", () => { |
| 120 | + it("should return a callout but no actions when no campaign is active", async () => { |
| 121 | + const mockHeaders = { |
| 122 | + get: jest.fn((key: string) => { |
| 123 | + if (key === "x-e2e-datetime") return "2025-10-01T12:00:00Z"; |
| 124 | + return null; |
| 125 | + }), |
| 126 | + }; |
| 127 | + (headers as jest.Mock).mockResolvedValue(mockHeaders); |
| 128 | + |
| 129 | + const pageCopy = await buildFilteredContentForCovid19Vaccine(JSON.stringify(genericVaccineContentAPIResponse)); |
| 130 | + |
| 131 | + expect(pageCopy.callout).not.toBeUndefined(); |
| 132 | + expect(pageCopy.actions).toHaveLength(0); |
| 133 | + }); |
| 134 | + |
| 135 | + it("should return actions but no callout when no campaign is active", async () => { |
| 136 | + const mockHeaders = { |
| 137 | + get: jest.fn((key: string) => { |
| 138 | + if (key === "x-e2e-datetime") return "2025-12-01T12:00:00Z"; |
| 139 | + return null; |
| 140 | + }), |
| 141 | + }; |
| 142 | + (headers as jest.Mock).mockResolvedValue(mockHeaders); |
| 143 | + |
| 144 | + const pageCopy = await buildFilteredContentForCovid19Vaccine(JSON.stringify(genericVaccineContentAPIResponse)); |
| 145 | + |
| 146 | + expect(pageCopy.callout).toBeUndefined(); |
| 147 | + expect(pageCopy.actions).not.toHaveLength(0); |
| 148 | + }); |
| 149 | + }); |
| 150 | +}); |
11 | 151 |
|
12 | 152 | describe("MoreInformation component ", () => { |
13 | 153 | const mockedConfig = config as ConfigMock; |
@@ -88,57 +228,59 @@ describe("MoreInformation component ", () => { |
88 | 228 | }); |
89 | 229 | }); |
90 | 230 |
|
91 | | - it("should not include 'how to get' section for RSV_PREGNANCY ", async () => { |
92 | | - const vaccineType = VaccineType.RSV_PREGNANCY; |
93 | | - render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
| 231 | + describe("MoreInformation", () => { |
| 232 | + it("should not include 'how to get' section for RSV_PREGNANCY ", async () => { |
| 233 | + const vaccineType = VaccineType.RSV_PREGNANCY; |
| 234 | + render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
94 | 235 |
|
95 | | - const heading: HTMLElement | null = screen.queryByText("How to get the vaccine"); |
| 236 | + const heading: HTMLElement | null = screen.queryByText("How to get the vaccine"); |
96 | 237 |
|
97 | | - expect(heading).not.toBeInTheDocument(); |
98 | | - }); |
| 238 | + expect(heading).not.toBeInTheDocument(); |
| 239 | + }); |
| 240 | + |
| 241 | + it("should not include 'how to get' section for RSV ", async () => { |
| 242 | + const vaccineType = VaccineType.RSV; |
| 243 | + render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
99 | 244 |
|
100 | | - it("should not include 'how to get' section for RSV ", async () => { |
101 | | - const vaccineType = VaccineType.RSV; |
102 | | - render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
| 245 | + const heading: HTMLElement | null = screen.queryByText("How to get the vaccine"); |
103 | 246 |
|
104 | | - const heading: HTMLElement | null = screen.queryByText("How to get the vaccine"); |
| 247 | + expect(heading).not.toBeInTheDocument(); |
| 248 | + }); |
105 | 249 |
|
106 | | - expect(heading).not.toBeInTheDocument(); |
107 | | - }); |
| 250 | + it("should display webpage link to more information about vaccine", async () => { |
| 251 | + const vaccineType = VaccineType.RSV; |
| 252 | + render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
108 | 253 |
|
109 | | - it("should display webpage link to more information about vaccine", async () => { |
110 | | - const vaccineType = VaccineType.RSV; |
111 | | - render(await MoreInformation({ styledVaccineContent: mockStyledContent, vaccineType: vaccineType })); |
| 254 | + const webpageLink: HTMLElement = screen.getByRole("link", { |
| 255 | + name: "Find out more about the RSV vaccine", |
| 256 | + }); |
112 | 257 |
|
113 | | - const webpageLink: HTMLElement = screen.getByRole("link", { |
114 | | - name: "Find out more about the RSV vaccine", |
| 258 | + expect(webpageLink).toBeInTheDocument(); |
| 259 | + expect(webpageLink).toHaveAttribute("href", "https://test.example.com/"); |
| 260 | + expect(webpageLink).toHaveAttribute("target", "_blank"); |
115 | 261 | }); |
116 | 262 |
|
117 | | - expect(webpageLink).toBeInTheDocument(); |
118 | | - expect(webpageLink).toHaveAttribute("href", "https://test.example.com/"); |
119 | | - expect(webpageLink).toHaveAttribute("target", "_blank"); |
120 | | - }); |
121 | | - |
122 | | - it("should not display whatItIsFor section if undefined in content", async () => { |
123 | | - const vaccineType = VaccineType.RSV; |
124 | | - render( |
125 | | - await MoreInformation({ styledVaccineContent: mockStyledContentWithoutWhatSection, vaccineType: vaccineType }), |
126 | | - ); |
| 263 | + it("should not display whatItIsFor section if undefined in content", async () => { |
| 264 | + const vaccineType = VaccineType.RSV; |
| 265 | + render( |
| 266 | + await MoreInformation({ styledVaccineContent: mockStyledContentWithoutWhatSection, vaccineType: vaccineType }), |
| 267 | + ); |
127 | 268 |
|
128 | | - const whatItIsForHeading: HTMLElement | null = screen.queryByText("What the vaccine is for"); |
129 | | - const whatItIsForContent: HTMLElement | null = screen.queryByText("What Section styled component"); |
| 269 | + const whatItIsForHeading: HTMLElement | null = screen.queryByText("What the vaccine is for"); |
| 270 | + const whatItIsForContent: HTMLElement | null = screen.queryByText("What Section styled component"); |
130 | 271 |
|
131 | | - expect(whatItIsForHeading).not.toBeInTheDocument(); |
132 | | - expect(whatItIsForContent).not.toBeInTheDocument(); |
133 | | - }); |
| 272 | + expect(whatItIsForHeading).not.toBeInTheDocument(); |
| 273 | + expect(whatItIsForContent).not.toBeInTheDocument(); |
| 274 | + }); |
134 | 275 |
|
135 | | - it("should display whoVaccineIsFor section even if whatItIsFor is undefined in content", async () => { |
136 | | - const vaccineType = VaccineType.RSV; |
137 | | - render( |
138 | | - await MoreInformation({ styledVaccineContent: mockStyledContentWithoutWhatSection, vaccineType: vaccineType }), |
139 | | - ); |
| 276 | + it("should display whoVaccineIsFor section even if whatItIsFor is undefined in content", async () => { |
| 277 | + const vaccineType = VaccineType.RSV; |
| 278 | + render( |
| 279 | + await MoreInformation({ styledVaccineContent: mockStyledContentWithoutWhatSection, vaccineType: vaccineType }), |
| 280 | + ); |
140 | 281 |
|
141 | | - expectExpanderBlockToBePresent("Who should have the vaccine", "Who Section styled component"); |
| 282 | + expectExpanderBlockToBePresent("Who should have the vaccine", "Who Section styled component"); |
| 283 | + }); |
142 | 284 | }); |
143 | 285 | }); |
144 | 286 |
|
|
0 commit comments