Skip to content

Commit

Permalink
Merge pull request #556 from UKHSA-Internal/feature/CDD-2363
Browse files Browse the repository at this point in the history
Feature/cdd 2363
  • Loading branch information
luketowell authored Dec 13, 2024
2 parents b6f6951 + 9b2a76f commit 192237f
Show file tree
Hide file tree
Showing 20 changed files with 348 additions and 45 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,3 @@ yarn-error.log*

# typescript
*.tsbuildinfo
next-env.d.ts
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
"typescript.enablePromptUseWorkspaceTsdk": true,
"cSpell.words": ["Colour"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ export class WeatherHealthAlertsChildPage {
await expect(await regions.getByRole('listitem').all()).toHaveLength(9)

for (let i = 0; i < alertList.length; i++) {
const expectedStatus = alertList[i].status === 'Green' ? 'No alert' : `${alertList[i].status.toLowerCase()} alert`
const listItem = regions.getByRole('listitem').nth(i)
await expect(listItem).toBeVisible()

await expect(listItem.getByRole('heading', { level: 2, name: alertList[i].region })).toBeVisible()
await expect(listItem.getByText(alertList[i].updated)).toBeVisible()
await expect(listItem.getByText(alertList[i].status, { exact: true })).toBeVisible()
await expect(listItem.getByText(expectedStatus, { exact: true })).toBeVisible()

//TODO: Need to implement tags for mobile vs desktop tags CDD-2024
// if (this.isMobile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ export class WeatherHealthAlertsMapPage {
await expect(this.page.getByRole('button', { name: 'Exit map' })).toBeVisible()
}

async hasMapKey() {
await expect(this.page.getByTestId('map-key')).toBeVisible()
}

async hasUKHSALogo() {
await expect(this.page.getByTestId('logo-layer')).toBeVisible()
}

async hasDisplayKeyButton() {
await expect(this.page.getByRole('button', { name: 'Display key' })).toBeVisible()
}

async mapKeyCanBeMinimised() {
await expect(this.page.getByTestId('close-key-button')).toBeVisible()
await this.page.getByTestId('close-key-button').click()
}

async clickDisplayKeyButton() {
await expect(this.page.getByRole('button', { name: 'Display key' })).toBeVisible()
await this.page.getByRole('button', { name: 'Display key' }).click()
}

async hasButton(name: ButtonNames) {
await expect(this.page.getByRole('button', { name })).toBeVisible()
}
Expand Down Expand Up @@ -117,22 +139,35 @@ export class WeatherHealthAlertsMapPage {
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Enter')
}

async zoomInWithKeyboard() {
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Enter')
await this.page.keyboard.press('Enter')
}

async zoomOutWithKeyboard() {
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Enter')
await this.page.keyboard.press('Enter')
}

async closeKeyWithKeyboard() {
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Enter')
}

async openKeyWithKeyboard() {
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Tab')
await this.page.keyboard.press('Enter')
}

async accessRegionWithKeyboard(regionNumber: number) {
await this.page.keyboard.press(`Digit${regionNumber}`)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export class WeatherHealthAlertsRegionPage {
async hasAlertSummaryList({ type, status, start, end }: SummaryList) {
const wrapper = this.page.getByLabel('Alert details')

const expectedStatus = status === 'Green' ? 'No alert' : `${status.toLowerCase()} alert`

await expect(wrapper.getByText('Type')).toBeVisible()
await expect(wrapper.getByText(type)).toBeVisible()

await expect(wrapper.getByText('Colour')).toBeVisible()
await expect(wrapper.getByText(status)).toBeVisible()
await expect(wrapper.getByText('Alert', { exact: true })).toBeVisible()
await expect(wrapper.getByText(expectedStatus)).toBeVisible()

await expect(wrapper.getByText('Start')).toBeVisible()
await expect(wrapper.getByText(start)).toBeVisible()
Expand Down
105 changes: 105 additions & 0 deletions e2e/tests/weather-health-alerts/weather-health-alerts-map.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ test.describe('Weather health alerts map display', () => {
await test.step('has all buttons', async () => {
await weatherHealthAlertsMapPage.hasMapButtons()
})
await test.step('has map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
await test.step('has UKHSA logo overlay', async () => {
await weatherHealthAlertsMapPage.hasUKHSALogo()
})
})

test('Map overlay opens and can exit back to previous page', async ({ app, weatherHealthAlertsMapPage }) => {
Expand Down Expand Up @@ -182,6 +188,105 @@ test.describe('Weather Health Alerts map interactivty', () => {
await weatherHealthAlertsMapPage.hasHighlightedRegions(7)
})
})

test('Key should be visible and closable with Mouse', async ({ app, weatherHealthAlertsMapPage }) => {
await test.step('open weather health alerts page', async () => {
await app.goto('/weather-health-alerts/cold?v=map&type=cold')
})
await test.step('map is displaying', async () => {
await weatherHealthAlertsMapPage.dialogIsOpen('Weather health alerts map')
})
await test.step('check interactive map has loaded', async () => {
await weatherHealthAlertsMapPage.hasMapLeaflet()
})
await test.step('shows the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
await test.step('can close the map key', async () => {
await weatherHealthAlertsMapPage.mapKeyCanBeMinimised()
})
await test.step('shows the display key button', async () => {
await weatherHealthAlertsMapPage.hasDisplayKeyButton()
})
})

test('Key should be visible and closable with Keyboard', async ({ app, weatherHealthAlertsMapPage }) => {
await test.step('open weather health alerts page', async () => {
await app.goto('/weather-health-alerts/cold?v=map&type=cold')
})
await test.step('map is displaying', async () => {
await weatherHealthAlertsMapPage.dialogIsOpen('Weather health alerts map')
})
await test.step('check interactive map has loaded', async () => {
await weatherHealthAlertsMapPage.hasMapLeaflet()
})
await test.step('shows the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
await test.step('can close the map key', async () => {
await weatherHealthAlertsMapPage.closeKeyWithKeyboard()
})
await test.step('shows the display key button', async () => {
await weatherHealthAlertsMapPage.hasDisplayKeyButton()
})
})

test('Key should be opened using the display key button with Mouse', async ({ app, weatherHealthAlertsMapPage }) => {
await test.step('open weather health alerts page', async () => {
await app.goto('/weather-health-alerts/cold?v=map&type=cold')
})
await test.step('map is displaying', async () => {
await weatherHealthAlertsMapPage.dialogIsOpen('Weather health alerts map')
})
await test.step('check interactive map has loaded', async () => {
await weatherHealthAlertsMapPage.hasMapLeaflet()
})
await test.step('shows the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
await test.step('can close the map key', async () => {
await weatherHealthAlertsMapPage.mapKeyCanBeMinimised()
})
await test.step('shows the display key button', async () => {
await weatherHealthAlertsMapPage.hasDisplayKeyButton()
})
await test.step('click the display key button', async () => {
await weatherHealthAlertsMapPage.clickDisplayKeyButton()
})
await test.step('should display the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
})

test('Key should be opened using the display key button with Keyboard', async ({
app,
weatherHealthAlertsMapPage,
}) => {
await test.step('open weather health alerts page', async () => {
await app.goto('/weather-health-alerts/cold?v=map&type=cold')
})
await test.step('map is displaying', async () => {
await weatherHealthAlertsMapPage.dialogIsOpen('Weather health alerts map')
})
await test.step('check interactive map has loaded', async () => {
await weatherHealthAlertsMapPage.hasMapLeaflet()
})
await test.step('shows the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
await test.step('can close the map key', async () => {
await weatherHealthAlertsMapPage.closeKeyWithKeyboard()
})
await test.step('shows the display key button', async () => {
await weatherHealthAlertsMapPage.hasDisplayKeyButton()
})
await test.step('click the display key button', async () => {
await weatherHealthAlertsMapPage.openKeyWithKeyboard()
})
await test.step('should display the map key', async () => {
await weatherHealthAlertsMapPage.hasMapKey()
})
})
})

// Need to investigate flaky test: CDD-2136
Expand Down
5 changes: 5 additions & 0 deletions next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion public/locales/en/weatherHealthAlerts.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"exitBtn": "Exit map",
"trigger": "View map of weather health alerts",
"fatalError": "There is a problem with the map. Please try again later.",
"alert": "{{level}} alert",
"no-alert": "No alert",
"alertDialog": {
"dateKey": "Start",
"expiryKey": "End",
"statusKey": "Colour",
"statusKey": "Alert",
"textKey": "Description",
"typeKey": "Type",
"typeValue_heat": "Heat Health Alert",
Expand All @@ -18,6 +20,7 @@
"alertCta": "Go to alert page"
}
},
"showKeyBtn": "Display Key",
"updated": "Updated {{value, time}} on {{ value, dateShort }}",
"weatherAlert": "{{weatherType}}-health alert for {{regionName}}",
"alertListLabel": "{{type}} health alerts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import useWeatherHealthAlert from '@/app/hooks/queries/useWeatherHealthAlert'
import useWeatherHealthAlertList from '@/app/hooks/queries/useWeatherHealthAlertList'
import { useTranslation } from '@/app/i18n/client'
import { getTagVariantFromStatus } from '@/app/utils/weather-health-alert.utils'
import { getTailwindBackgroundFromColour, getTextColourCssFromColour } from '@/app/utils/weather-health-alert.utils'
import { logger } from '@/lib/logger'

interface AlertProps {
Expand Down Expand Up @@ -100,9 +100,15 @@ export default function AlertBody({ relatedLinks, relatedLinksLayout, weather, r
</SummaryListRow>
<SummaryListRow>
<SummaryListKey>{t('map.alertDialog.statusKey')}</SummaryListKey>
<SummaryListValue>
<div className={clsx(`govuk-tag capitalize`, getTagVariantFromStatus(status))}>{status}</div>
</SummaryListValue>
<div
className={clsx(
`govuk-tag mb-0 px-2 text-center capitalize`,
getTextColourCssFromColour(status),
getTailwindBackgroundFromColour(status)
)}
>
{status == 'Green' ? t('map.no-alert') : t('map.alert', { level: status.toLowerCase() })}
</div>
</SummaryListRow>
<SummaryListRow>
<SummaryListKey>{t('map.alertDialog.dateKey')}</SummaryListKey>
Expand Down
26 changes: 8 additions & 18 deletions src/app/components/ui/ukhsa/List/ListItemStatus.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,15 @@ describe('renders correct tag', () => {
test('renders green tag', () => {
const { getByText } = render(<ListItemStatusTag type="heat" level="Green" region="East of England" />)

expect(getByText('Green')).toHaveClass('govuk-tag--green')
expect(getByText('Green')).toHaveAttribute(
'aria-label',
'There is currently a Green heat alert status for East of England'
)
expect(getByText('No alert')).toHaveClass('bg-green')
expect(getByText('No alert')).toHaveAttribute('aria-label', 'There are currently no alerts for East of England')
})

test('renders yellow tag', () => {
const { getByText } = render(<ListItemStatusTag type="heat" level="Yellow" region="South East" />)

expect(getByText('Yellow')).toHaveClass('govuk-tag--yellow')
expect(getByText('Yellow')).toHaveAttribute(
expect(getByText('yellow alert')).toHaveClass('bg-custard')
expect(getByText('yellow alert')).toHaveAttribute(
'aria-label',
'There is currently a Yellow heat alert status for South East'
)
Expand All @@ -104,8 +101,8 @@ describe('renders correct tag', () => {
test('renders amber tag', () => {
const { getByText } = render(<ListItemStatusTag type="cold" level="Amber" region="West Midlands" />)

expect(getByText('Amber')).toHaveClass('govuk-tag--orange')
expect(getByText('Amber')).toHaveAttribute(
expect(getByText('amber alert')).toHaveClass('bg-orange')
expect(getByText('amber alert')).toHaveAttribute(
'aria-label',
'There is currently an Amber cold alert status for West Midlands'
)
Expand All @@ -114,17 +111,10 @@ describe('renders correct tag', () => {
test('renders red tag', () => {
const { getByText } = render(<ListItemStatusTag type="cold" level="Red" region="East Midlands" />)

expect(getByText('Red')).toHaveClass('govuk-tag--red')
expect(getByText('Red')).toHaveAttribute(
expect(getByText('red alert')).toHaveClass('bg-red')
expect(getByText('red alert')).toHaveAttribute(
'aria-label',
'There is currently a Red cold alert status for East Midlands'
)
})

test('renders no alerts tag', () => {
const { getByText } = render(<ListItemStatusTag type="heat" level="No alerts" region="London" />)

expect(getByText('No alerts')).not.toHaveClass('govuk-tag')
expect(getByText('No alerts')).toHaveAttribute('aria-label', 'There are currently no alerts for London')
})
})
6 changes: 5 additions & 1 deletion src/app/components/ui/ukhsa/List/ListItemStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ interface ListItemStatusProps {
}

export const ListItemStatus = ({ children }: ListItemStatusProps) => {
return <div className="relative grid grid-cols-[1fr_70px] gap-2 sm:grid-cols-[50px_1fr_70px]">{children}</div>
return (
<div className="relative grid grid-cols-[1fr_125px] items-center gap-2 sm:grid-cols-[50px_1fr_125px]">
{children}
</div>
)
}

interface ListItemStatusIconProps {
Expand Down
20 changes: 10 additions & 10 deletions src/app/components/ui/ukhsa/List/ListItemStatusTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@ import clsx from 'clsx'

import { HealthAlertStatus, HealthAlertTypes } from '@/api/models/Alerts'
import { useTranslation } from '@/app/i18n/client'
import { getTailwindBackgroundFromColour, getTextColourCssFromColour } from '@/app/utils/weather-health-alert.utils'

interface ListItemStatusTagProps {
level: HealthAlertStatus | 'No alerts'
level: HealthAlertStatus
region: string
type: HealthAlertTypes
}

const ListItemStatusTag = ({ level, region, type }: ListItemStatusTagProps) => {
const { t } = useTranslation('weatherHealthAlerts')

function getStatusKey(level: HealthAlertStatus | 'No alerts') {
function getStatusKey(level: HealthAlertStatus) {
switch (level) {
case 'Amber':
return 'Amber'
case 'No alerts':
case 'Green':
return 'None'
default:
return 'Initial'
Expand All @@ -27,15 +28,14 @@ const ListItemStatusTag = ({ level, region, type }: ListItemStatusTagProps) => {

return (
<div
className={clsx('govuk-!-margin-right-0 govuk-phase-banner__content__tag m-auto capitalize', {
'govuk-tag govuk-tag--green': level === 'Green',
'govuk-tag govuk-tag--yellow': level === 'Yellow',
'govuk-tag govuk-tag--orange': level === 'Amber',
'govuk-tag govuk-tag--red': level === 'Red',
})}
className={clsx(
`govuk-tag h-6 items-center text-center capitalize`,
getTextColourCssFromColour(level),
getTailwindBackgroundFromColour(level)
)}
aria-label={t('statusLabel', { context: getStatusKey(level), level, type, region })}
>
{level}
{level == 'Green' ? t('map.no-alert') : t('map.alert', { level: level.toLowerCase() })}
</div>
)
}
Expand Down
Loading

1 comment on commit 192237f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests coverage

Lines Statements Branches Functions
Coverage: 93%
92.28% (1771/1919) 82.7% (416/503) 89.76% (263/293)
Tests Skipped Failures Errors Time
476 0 💤 0 ❌ 0 🔥 15.648s ⏱️

Please sign in to comment.