Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cdd 2180 #563

Merged
merged 18 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6b4c4fb
CDD-2180: configured first pass at showMore functionality
luketowell Dec 19, 2024
3155b56
CDD-2180: implemented functionality for show more and show less buttons
luketowell Dec 20, 2024
e7bcb2c
CDD-2180: updated the mock-server landing page mocks and updated the …
luketowell Jan 6, 2025
91a5533
CDD-2180: reformatting passing of parameters
luketowell Jan 6, 2025
781a601
CDD-2180: Updated test function signatures for renderSection and rend…
luketowell Jan 6, 2025
f7e7486
CDD-2180: Updated e2e tests for playwright
luketowell Jan 6, 2025
88760a1
Merge branch 'main' into feature/CDD-2180
luketowell Jan 6, 2025
ade4892
CDD-2180: abstracted out show more logic and added tests
luketowell Jan 6, 2025
9b11f49
CDD-2180: added playwright tests
luketowell Jan 6, 2025
05e80f9
CDD-2180: added playwright tests for the showMore and showLess functi…
luketowell Jan 6, 2025
34be85b
CDD-2180: Updated e2e tests so that it counts number of cards display…
luketowell Jan 9, 2025
7f80d13
CDD-2180: Updated the arrows in the UI to be filled down and right ar…
luketowell Jan 9, 2025
0a082b4
CDD-2180: Fixed the count test
luketowell Jan 9, 2025
99a133e
CDD-2180: refactored tests based on PR feedback
luketowell Jan 9, 2025
e2b851e
CDD-2180: refactored test names based on PR feedback
luketowell Jan 9, 2025
b13c579
CDD-2180: updated github action for upload-artifact version change
luketowell Jan 9, 2025
a5176c7
CDD-2180: updated tests
luketowell Jan 13, 2025
a1452ae
Merge branch 'main' into feature/CDD-2180
luketowell Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/app/utils/show-more.utils.spec.ts",
"outFiles": ["${workspaceFolder}/**/*.js"]
}
]
}
53 changes: 50 additions & 3 deletions e2e/fixtures/pages/landing/landing.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,53 @@ export class LandingPage {
await expect(card.getByText(sub_title)).toBeVisible()
}

async hasNoLandingPageCard({ title, sub_title }: { title: string; sub_title: string }) {
const section = this.page.getByRole('region', { name: 'Respiratory viruses' })
const card = section.getByRole('link', { name: title })

await expect(card.getByRole('heading', { level: 3, name: title })).toBeHidden()
await expect(card.getByText(sub_title)).toBeHidden()
}

async hasXCardsInSection(section: string, expectedNumberOfCards: number) {
const selectedSection = this.page.getByRole('region', { name: section })
const cardCount = await selectedSection.getByTestId('card-wrapper').count()

expect(cardCount).toBe(expectedNumberOfCards)
}

async hasShowMoreButton() {
const section = this.page.getByRole('region', { name: 'Respiratory viruses' })
const showMoreButton = section.getByRole('link', { name: 'Show More' })

await expect(showMoreButton).toBeVisible()
}

async hasNoShowMoreButton() {
const section = this.page.getByRole('region', { name: 'Outbreaks' })
const showMoreButton = section.getByRole('link', { name: 'Show More' })

await expect(showMoreButton).toBeHidden()
}
async hasShowLessButton() {
const section = this.page.getByRole('region', { name: 'Respiratory viruses' })
const showLessButton = section.getByRole('link', { name: 'Show Less' })

await expect(showLessButton).toBeVisible()
}

async clickShowMoreButton() {
const section = this.page.getByRole('region', { name: 'Respiratory viruses' })
const showMoreButton = section.getByRole('link', { name: 'Show More' })
await showMoreButton.click()
}

async clickShowLessButton() {
const section = this.page.getByRole('region', { name: 'Respiratory viruses' })
const showLessButton = section.getByRole('link', { name: 'Show Less' })
await showLessButton.click()
}

async hasHealthTopicCard(
name: string,
{ tagline, trendPercent, trendDescription }: { tagline: string; trendPercent: string; trendDescription: string }
Expand All @@ -84,7 +131,7 @@ export class LandingPage {
}

async hasWeatherHealthAlertsCard(name: string, { tagline, map = true }: { tagline: string; map?: boolean }) {
const section = this.page.getByRole('region', { name: 'Weather health alerts' })
const section = this.page.getByRole('region', { name: 'Weather and climate risks' })
const card = section.getByRole('link', { name })

await expect(section).toBeVisible()
Expand All @@ -105,13 +152,13 @@ export class LandingPage {
}

async clickMinimapCard(name: string) {
const section = this.page.getByRole('region', { name: 'Weather health alerts' })
const section = this.page.getByRole('region', { name: 'Weather and climate risks' })
const card = section.getByRole('link', { name })
await card.click()
}

async clickMinimapCardRegionByMap(name: string, regionId: string) {
const section = this.page.getByRole('region', { name: 'Weather health alerts' })
const section = this.page.getByRole('region', { name: 'Weather and climate risks' })
const card = section.getByRole('link', { name })
const map = card.getByRole('application', { name: 'Map of weather health alerts' })
await expect(map).toBeVisible()
Expand Down
93 changes: 88 additions & 5 deletions e2e/tests/landing/landing.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ test.describe('Landing page - tablet @tabletOnly', () => {

test('Card', async ({ landingPage }) => {
await test.step('displays a Weather Health Alerts card', async () => {
await landingPage.hasWeatherHealthAlertsCard('Heat health alerts', { tagline: 'Across England', map: true })
await landingPage.hasWeatherHealthAlertsCard('Cold health alerts', { tagline: 'Alerts in England', map: true })
})
})

test('Open map after clicking a minimap region', async ({ landingPage, weatherHealthAlertsMapPage }) => {
await test.step('click minimap card', async () => {
await landingPage.clickMinimapCardRegionByMap('Heat health alerts', 'E12000004')
await landingPage.clickMinimapCardRegionByMap('Cold health alerts', 'E12000004')
})
await test.step('shows map', async () => {
await weatherHealthAlertsMapPage.hasMapDialog()
Expand Down Expand Up @@ -64,18 +64,101 @@ test.describe('Landing page - desktop @desktopOnly', () => {
sub_title: 'Healthcare admission rates',
})
await landingPage.hasLandingPageCard({
title: 'RSV',
title: 'Respiratory syncytial virus (RSV)',
sub_title: 'Healthcare admission rates',
})
})

test('displays the showMore button with more than 3 charts', async ({ landingPage }) => {
await landingPage.hasXCardsInSection('Respiratory viruses', 3)
await landingPage.hasShowMoreButton()
})

test('doesnt display the showMore button with 3 or less charts', async ({ landingPage }) => {
await landingPage.hasNoShowMoreButton()
})

test('expands the region charts after clicking showMore button', async ({ landingPage }) => {
await test.step('click show more button', async () => {
await landingPage.clickShowMoreButton()
})
await test.step('All charts', async () => {
await landingPage.hasLandingPageCard({
title: 'COVID-19',
sub_title: 'Cases Reported',
})
await landingPage.hasLandingPageCard({
title: 'Influenza',
sub_title: 'Healthcare admission rates',
})
await landingPage.hasLandingPageCard({
title: 'Respiratory syncytial virus (RSV)',
sub_title: 'Healthcare admission rates',
})
await landingPage.hasLandingPageCard({
title: 'COVID-19 v2',
sub_title: 'Testing Positivity',
})
await landingPage.hasLandingPageCard({
title: 'Influenza v2',
sub_title: 'Testing Positivity',
})
await landingPage.hasLandingPageCard({
title: 'Respiratory syncytial virus (RSV) v2',
sub_title: 'Testing Positivity',
})
})
await test.step('displays show less button once expanded', async () => {
await landingPage.hasShowLessButton()
})
})

test('minimises the region charts after clicking showLess button', async ({ landingPage }) => {
await test.step('click show more button', async () => {
await landingPage.clickShowMoreButton()
})
await landingPage.hasXCardsInSection('Respiratory viruses', 6)
await test.step('displays show less button once expanded', async () => {
await landingPage.hasShowLessButton()
})
await test.step('click show more button', async () => {
await landingPage.clickShowLessButton()
})
await test.step('All charts', async () => {
await landingPage.hasLandingPageCard({
title: 'COVID-19',
sub_title: 'Cases Reported',
})
await landingPage.hasLandingPageCard({
title: 'Influenza',
sub_title: 'Healthcare admission rates',
})
await landingPage.hasLandingPageCard({
title: 'Respiratory syncytial virus (RSV)',
sub_title: 'Healthcare admission rates',
})
await landingPage.hasNoLandingPageCard({
title: 'COVID-19 v2',
sub_title: 'Testing Positivity',
})
await landingPage.hasNoLandingPageCard({
title: 'Influenza v2',
sub_title: 'Testing Positivity',
})
await landingPage.hasNoLandingPageCard({
title: 'Respiratory syncytial virus (RSV) v2',
sub_title: 'Testing Positivity',
})
})
})

test('displays the Weather health alerts header', async ({ landingPage }) => {
await landingPage.hasWeatherHealthAlertsCard('Heat health alerts', { tagline: 'Across England', map: true })
await landingPage.hasWeatherHealthAlertsCard('Cold health alerts', { tagline: 'Alerts in England', map: true })
})

test('Open map after clicking a minimap region', async ({ landingPage, weatherHealthAlertsMapPage }) => {
await test.step('click minimap card', async () => {
await landingPage.clickMinimapCardRegionByMap('Heat health alerts', 'E12000004')
await landingPage.clickMinimapCardRegionByMap('Cold health alerts', 'E12000004')
})
await test.step('shows map', async () => {
await weatherHealthAlertsMapPage.hasMapDialog()
Expand Down
16 changes: 14 additions & 2 deletions src/app/components/cms/pages/Landing.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { View } from '@/app/components/ui/ukhsa'
import { PageComponentBaseProps } from '@/app/types'
import { getLandingPage } from '@/app/utils/cms'
import { renderSection } from '@/app/utils/cms.utils'

export default async function LandingPage() {
export default async function LandingPage({ searchParams: { section } }: PageComponentBaseProps<{ section?: string }>) {
let processedSectionParams: string[] = []

if (section) {
processedSectionParams = processedParams(section)
}
const { body } = await getLandingPage()

return <View>{body.map(renderSection)}</View>
return <View>{body.map(renderSection.bind(null, processedSectionParams))}</View>
}

const processedParams = (value: string | string[]) => {
const emptyArray: string[] = []

return emptyArray.concat(value).map((section) => section.toLowerCase())
}
2 changes: 1 addition & 1 deletion src/app/components/cms/pages/Topic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default async function TopicPage({
<PageSectionWithContents>
{body.map(({ id, value }) => (
<PageSection key={id} heading={value.heading}>
{value.content.map(renderCard)}
{value.content.map(renderCard.bind(null, value.heading, []))}
</PageSection>
))}
</PageSectionWithContents>
Expand Down
24 changes: 12 additions & 12 deletions src/app/utils/cms.utils.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ jest.mock('../components/cms', () => ({

describe('Displaying a section from the cms home page', () => {
test('renders a heading that links to the topic page', () => {
render(renderSection(mockSectionWithLink))
render(renderSection([], mockSectionWithLink))
expect(screen.getByRole('heading', { level: 2, name: 'COVID-19' })).toBeInTheDocument()
expect(screen.getByRole('link', { name: 'COVID-19' })).toHaveAttribute('href', '/topics/covid-19')

render(renderSection(mockSectionWithLongHeading))
render(renderSection([], mockSectionWithLongHeading))
expect(screen.getByRole('heading', { level: 2, name: 'Other respiratory viruses' })).toBeInTheDocument()
expect(screen.getByRole('link', { name: 'Other respiratory viruses' })).toHaveAttribute(
'href',
Expand All @@ -56,27 +56,27 @@ describe('Displaying a section from the cms home page', () => {
})

test('renders a heading with no link', () => {
render(renderSection(mockSectionNoLink))
render(renderSection([], mockSectionNoLink))
expect(screen.getByRole('heading', { level: 2, name: 'COVID-19' })).toBeInTheDocument()
})

test('renders a card', () => {
render(renderSection(mockSectionWithCard))
render(renderSection([], mockSectionWithCard))
expect(screen.getByText('This is some cms content')).toBeInTheDocument()
})
})

describe('Text card', () => {
test('text card displays correctly', () => {
render(renderCard(mockTextCard))
render(renderCard('Text card heading', [], mockTextCard))
expect(screen.getByRole('heading', { level: 3, name: 'Text card heading' })).toBeInTheDocument()
expect(screen.getByText('Text card body')).toBeInTheDocument()
})
})

describe('Headline numbers row card', () => {
test('displays a row of columns containing a heading and metric data', () => {
render(renderCard(mockHeadlineNumbersRowCard))
render(renderCard('', [], mockHeadlineNumbersRowCard))

expect(screen.getByTestId('headline-row')).toHaveClass('ukhsa-headline-numbers-row-card')

Expand Down Expand Up @@ -110,12 +110,12 @@ describe('Headline numbers row card', () => {
})

test('displays five columns on desktop devices when the default amount of columns (5) is set', () => {
render(renderCard(mockHeadlineNumbersRowCard))
render(renderCard('', [], mockHeadlineNumbersRowCard))
expect(screen.getByTestId('headline-row').firstChild).toHaveClass('md:grid-cols-5')
})

test('displays a mobile first in a two column layout, then a three-col layout for larger devices', () => {
render(renderCard(mockHeadlineNumbersRowCardWithOneColumn))
render(renderCard('', [], mockHeadlineNumbersRowCardWithOneColumn))
const gridRow = screen.getByTestId('headline-row').firstChild
expect(gridRow).toHaveClass('grid-cols-2 sm:grid-cols-3')
expect(gridRow).not.toHaveClass('md:grid-cols-5')
Expand All @@ -124,7 +124,7 @@ describe('Headline numbers row card', () => {

describe('Chart row card', () => {
test('chart card displays correctly', () => {
render(renderCard(mockChartRowCardWithSingleChartCard))
render(renderCard('', [], mockChartRowCardWithSingleChartCard))

expect(screen.getAllByRole('article')).toHaveLength(1)

Expand Down Expand Up @@ -153,7 +153,7 @@ describe('Chart row card', () => {
})

test('chart card with headline and trend', () => {
render(renderCard(mockChartRowCardWithChartHeadlineAndTrendCard))
render(renderCard('', [], mockChartRowCardWithChartHeadlineAndTrendCard))

// Heading and description
const article = screen.getByRole('article', { name: 'Chart heading 1' })
Expand All @@ -163,13 +163,13 @@ describe('Chart row card', () => {
})

test('chart card in a full width column', () => {
render(renderCard(mockChartRowCardWithSingleChartCard))
render(renderCard('', [], mockChartRowCardWithSingleChartCard))
const article = screen.getByRole('article', { name: 'Chart heading 1' })
expect(article.parentElement).toHaveClass('lg:w-full')
})

test('chart cards in two columns', () => {
render(renderCard(mockChartRowCardWithDualChartCard))
render(renderCard('', [], mockChartRowCardWithDualChartCard))
const article1 = screen.getByRole('article', { name: 'Chart heading 1' })
const article2 = screen.getByRole('article', { name: 'Chart heading 2' })
expect(article1.parentElement).toHaveClass('lg:w-1/2')
Expand Down
Loading
Loading