Skip to content

Commit e58602b

Browse files
VIA-299 SB Display callout component.
1 parent 502e8ac commit e58602b

File tree

9 files changed

+104
-1
lines changed

9 files changed

+104
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Callout } from "@src/app/_components/content/Callout";
2+
import { VaccineType } from "@src/models/vaccine";
3+
import { mockStyledContent } from "@test-data/content-api/data";
4+
import { render, screen } from "@testing-library/react";
5+
import React from "react";
6+
7+
describe("Callout component", () => {
8+
it("renders correctly", () => {
9+
const vaccineType = VaccineType.HIB_MENC;
10+
11+
render(<Callout styledVaccineContent={mockStyledContent} vaccineType={vaccineType} />);
12+
13+
const CalloutText: HTMLElement = screen.getByTestId("callout");
14+
15+
expect(CalloutText).toBeInTheDocument();
16+
});
17+
18+
it("does not render for vaccines for which they should not be shown", () => {
19+
const vaccineType = VaccineType.SHINGLES;
20+
21+
render(<Callout styledVaccineContent={mockStyledContent} vaccineType={vaccineType} />);
22+
23+
const CalloutText: HTMLElement | null = screen.queryByTestId("Callout-text");
24+
25+
expect(CalloutText).not.toBeInTheDocument();
26+
});
27+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import WarningCallout from "@src/app/_components/nhs-frontend/WarningCallout";
2+
import { VaccineInfo, VaccineType } from "@src/models/vaccine";
3+
import { StyledVaccineContent } from "@src/services/content-api/types";
4+
import { JSX } from "react";
5+
6+
const Callout = (props: { styledVaccineContent: StyledVaccineContent; vaccineType: VaccineType }): JSX.Element => {
7+
const element =
8+
props.styledVaccineContent.callout && VaccineInfo[props.vaccineType].showWarningCallout ? (
9+
<WarningCallout
10+
heading={props.styledVaccineContent.callout.heading}
11+
content={props.styledVaccineContent.callout.content}
12+
/>
13+
) : (
14+
<></>
15+
);
16+
return element;
17+
};
18+
export { Callout };
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use client";
2+
3+
interface WarningCalloutProps {
4+
heading: string;
5+
content: string;
6+
}
7+
8+
const WarningCallout = ({ heading, content }: WarningCalloutProps) => {
9+
return (
10+
<div data-testid="callout" className="nhsuk-warning-callout">
11+
<h3 className="nhsuk-warning-callout__label">
12+
<span role="text">
13+
<span className="nhsuk-u-visually-hidden">Important: </span>
14+
{heading}
15+
</span>
16+
</h3>
17+
<div data-testid="callout-text" dangerouslySetInnerHTML={{ __html: content || "" }} />
18+
</div>
19+
);
20+
};
21+
22+
export default WarningCallout;

src/app/_components/vaccine/Vaccine.test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ describe("Any vaccine page", () => {
125125
expect(overviewText).toBeInTheDocument();
126126
});
127127

128+
it("should include callout text", async () => {
129+
await renderNamedVaccinePage(VaccineType.HIB_MENC);
130+
131+
const overviewText: HTMLElement = screen.getByTestId("callout");
132+
133+
expect(overviewText).toBeInTheDocument();
134+
});
135+
128136
it("should include lowercase vaccine name in more information text", async () => {
129137
const expectedMoreInformationHeading: string = "More information about the RSV vaccine";
130138

@@ -189,6 +197,14 @@ describe("Any vaccine page", () => {
189197
expect(overviewText).not.toBeInTheDocument();
190198
});
191199

200+
it("should not display callout", async () => {
201+
await renderNamedVaccinePage(VaccineType.HIB_MENC);
202+
203+
const overviewText: HTMLElement | null = screen.queryByTestId("callout");
204+
205+
expect(overviewText).not.toBeInTheDocument();
206+
});
207+
192208
it("should not display vaccine info expanders", async () => {
193209
await renderRsvVaccinePage();
194210

src/app/_components/vaccine/Vaccine.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use server";
22

33
import { auth } from "@project/auth";
4+
import { Callout } from "@src/app/_components/content/Callout";
45
import { FindOutMoreLink } from "@src/app/_components/content/FindOutMore";
56
import { HowToGetVaccineFallback } from "@src/app/_components/content/HowToGetVaccineFallback";
67
import { MoreInformation } from "@src/app/_components/content/MoreInformation";
@@ -65,8 +66,12 @@ const VaccineComponent = async ({ vaccineType }: VaccineProps): Promise<JSX.Elem
6566
return (
6667
<div className={styles.tableCellSpanHide}>
6768
{contentError != ContentErrorTypes.CONTENT_LOADING_ERROR && styledVaccineContent != undefined && (
68-
<Overview styledVaccineContent={styledVaccineContent} vaccineType={vaccineType} />
69+
<>
70+
<Overview styledVaccineContent={styledVaccineContent} vaccineType={vaccineType} />
71+
<Callout styledVaccineContent={styledVaccineContent} vaccineType={vaccineType} />
72+
</>
6973
)}
74+
7075
{/* Eligibility section for RSV */}
7176
{vaccineType === VaccineType.RSV && eligibilityForPerson !== undefined && (
7277
<EligibilityVaccinePageContent

src/models/vaccine.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export type VaccineDetails = {
3434
contentPath: UrlPathFragment;
3535
cacheFilename: Filename;
3636
nboPath: UrlPathFragment;
37+
showWarningCallout?: boolean;
3738
};
3839

3940
type displayName = {
@@ -274,6 +275,7 @@ const VaccineInfo: Record<VaccineType, VaccineDetails> = {
274275
contentPath: "vaccinations/hib-menc-vaccine" as UrlPathFragment,
275276
cacheFilename: "hib-menc-vaccine.json" as Filename,
276277
nboPath: "hib-menc-vaccine" as UrlPathFragment,
278+
showWarningCallout: true,
277279
},
278280
};
279281

src/services/content-api/parsers/content-styling-service.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,15 @@ describe("ContentStylingService", () => {
213213
headline: "Side effects of the generic vaccine",
214214
subsections: [mockMarkdownSubsection, mockUrgentSubsection],
215215
};
216+
const mockCallout: HeadingWithContent = { heading: "Callout Heading", content: "Callout content" };
216217
const mockContent: VaccinePageContent = {
217218
overview: { content: "This is an overview", containsHtml: false },
218219
whatVaccineIsFor: mockWhatSection,
219220
whoVaccineIsFor: mockWhoSection,
220221
howToGetVaccine: mockHowSection,
221222
vaccineSideEffects: mockSideEffectsSection,
222223
webpageLink: new URL("https://test.example.com/"),
224+
callout: mockCallout,
223225
};
224226

225227
const styledVaccineContent: StyledVaccineContent = await getStyledContentForVaccine(vaccine, mockContent, false);
@@ -230,6 +232,7 @@ describe("ContentStylingService", () => {
230232
expect(styledVaccineContent.whoVaccineIsFor.heading).toEqual(mockWhoSection.headline);
231233
expect(styledVaccineContent.howToGetVaccine.heading).toEqual(mockHowSection.headline);
232234
expect(styledVaccineContent.vaccineSideEffects.heading).toEqual(mockSideEffectsSection.headline);
235+
expect(styledVaccineContent.callout?.heading).toEqual(mockCallout.heading);
233236

234237
const expectedRsvHowToGetSection = "<div><p>para1</p><p>para2</p></div>";
235238
const expectedRsvPregnancyHowToGetSection = `<div><div><p>para3</p><p>para4</p></div></div>`;

src/services/content-api/parsers/content-styling-service.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ const styleHowToGetSection = (
138138
}
139139
};
140140

141+
function styleCallout(callout: HeadingWithContent | undefined): HeadingWithContent | undefined {
142+
if (callout) {
143+
return { heading: callout.heading, content: callout.content };
144+
}
145+
return undefined;
146+
}
147+
141148
const getStyledContentForVaccine = async (
142149
vaccine: VaccineType,
143150
filteredContent: VaccinePageContent,
@@ -151,6 +158,7 @@ const getStyledContentForVaccine = async (
151158
const whoVaccineIsFor: StyledPageSection = styleSection(filteredContent.whoVaccineIsFor);
152159
const howToGetVaccine: StyledPageSection = styleHowToGetSection(vaccine, filteredContent.howToGetVaccine, fragile);
153160
const vaccineSideEffects: StyledPageSection = styleSection(filteredContent.vaccineSideEffects);
161+
const callout: HeadingWithContent | undefined = styleCallout(filteredContent.callout);
154162
const webpageLink: URL = filteredContent.webpageLink;
155163

156164
return {
@@ -160,6 +168,7 @@ const getStyledContentForVaccine = async (
160168
howToGetVaccine,
161169
vaccineSideEffects,
162170
webpageLink,
171+
callout,
163172
};
164173
};
165174

test-data/content-api/data.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ export const mockStyledContent: StyledVaccineContent = {
591591
component: <div>Side effects section styled component</div>,
592592
},
593593
webpageLink: new URL("https://test.example.com/"),
594+
callout: { heading: "Callout Heading", content: "Callout content" },
594595
};
595596

596597
export const mockStyledContentWithHtmlOverview: StyledVaccineContent = {

0 commit comments

Comments
 (0)