Skip to content

Commit

Permalink
Add accessibility tests to the frontend component.
Browse files Browse the repository at this point in the history
Closes #2934.
  • Loading branch information
fniessink committed Jan 27, 2025
1 parent ed39c3d commit 5f4f543
Show file tree
Hide file tree
Showing 61 changed files with 3,065 additions and 1,449 deletions.
2,529 changes: 1,891 additions & 638 deletions components/frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions components/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-simple-import-sort": "^12.1.1",
"globals": "^15.14.0",
"jest": "^27.5.1",
"jest-axe": "^9.0.0",
"prettier": "^3.4.2",
"react-scripts": "5.0.1"
},
Expand Down
45 changes: 29 additions & 16 deletions components/frontend/src/App.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import history from "history/browser"
import * as auth from "./api/auth"
import * as fetch_server_api from "./api/fetch_server_api"
import App from "./App"
import { expectNoAccessibilityViolations } from "./testUtils"
import * as toast from "./widgets/toast"

function set_user_in_local_storage(session_expiration_datetime, email) {
Expand Down Expand Up @@ -32,46 +33,53 @@ afterEach(() => {
})

it("shows spinner", async () => {
render(<App />)
const { container } = render(<App />)
expect(screen.getAllByLabelText(/Loading/).length).toBe(1)
await expectNoAccessibilityViolations(container)
})

it("sets the user from local storage", () => {
it("sets the user from local storage", async () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z")
render(<App />)
const { container } = render(<App />)
expect(screen.getAllByText(/admin/).length).toBe(1)
expect(screen.getAllByAltText(/Avatar for admin/).length).toBe(1)
await expectNoAccessibilityViolations(container)
})

it("does not set invalid email addresses", () => {
it("does not set invalid email addresses", async () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z", "admin at example.org")
render(<App />)
const { container } = render(<App />)
expect(screen.getAllByText(/admin/).length).toBe(1)
expect(screen.queryAllByAltText(/Avatar for admin/).length).toBe(0)
await expectNoAccessibilityViolations(container)
})

it("resets the user when the session is expired on mount", () => {
it("resets the user when the session is expired on mount", async () => {
set_user_in_local_storage("2000-02-23T22:00:50.945Z")
render(<App />)
const { container } = render(<App />)
expect(screen.queryAllByText(/admin/).length).toBe(0)
await expectNoAccessibilityViolations(container)
})

it("resets the user when the user clicks logout", async () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z")
auth.logout = jest.fn().mockResolvedValue({ ok: true })
render(<App />)
const { container } = render(<App />)
await act(async () => {
fireEvent.click(screen.getByText(/admin/))
await expectNoAccessibilityViolations(container)
})
await act(async () => {
fireEvent.click(screen.getByText(/Logout/))
})
expect(screen.queryAllByText(/admin/).length).toBe(0)
await expectNoAccessibilityViolations(container)
})

async function selectDate() {
async function selectDate(container) {
await act(async () => {
fireEvent.click(screen.getByLabelText("Report date"))
await expectNoAccessibilityViolations(container)
})
await act(async () => {
fireEvent.click(screen.getByRole("button", { name: "Previous month" }))
Expand All @@ -82,37 +90,42 @@ async function selectDate() {
}

it("handles a date change", async () => {
render(<App />)
await selectDate()
const { container } = render(<App />)
await selectDate(container)
const expectedDate = dayjs().subtract(1, "month").date(15).toDate().toDateString()
expect(screen.getByLabelText("Report date").textContent).toMatch(expectedDate)
await expectNoAccessibilityViolations(container)
})

it("handles a date change between two dates in the past", async () => {
history.push("/?report_date=2022-03-13")
render(<App />)
await selectDate()
const { container } = render(<App />)
await selectDate(container)
const expectedDate = dayjs().subtract(1, "month").date(15).toDate().toDateString()
expect(screen.getByLabelText("Report date").textContent).toMatch(expectedDate)
await expectNoAccessibilityViolations(container)
})

it("reads the report date query parameter", () => {
it("reads the report date query parameter", async () => {
history.push("/?report_date=2020-03-13")
render(<App />)
const { container } = render(<App />)
const expectedDate = dayjs("2020-03-13").toDate().toDateString()
expect(screen.getByLabelText("Report date").textContent).toMatch(expectedDate)
await expectNoAccessibilityViolations(container)
})

it("handles a date reset", async () => {
history.push("/?report_date=2020-03-13")
render(<App />)
const { container } = render(<App />)
await act(async () => {
fireEvent.click(screen.getByLabelText("Report date"))
await expectNoAccessibilityViolations(container)
})
await act(async () => {
fireEvent.click(screen.getByRole("button", { name: "Today" }))
})
expect(screen.getByLabelText("Report date").textContent).toMatch(/today/)
await expectNoAccessibilityViolations(container)
})

it("handles the nr of measurements event source", async () => {
Expand Down
54 changes: 24 additions & 30 deletions components/frontend/src/AppUI.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ThemeProvider } from "@mui/material/styles"
import { act, fireEvent, render, screen } from "@testing-library/react"
import history from "history/browser"
import { axe } from "jest-axe"

import { dataModel, report } from "./__fixtures__/fixtures"
import * as fetch_server_api from "./api/fetch_server_api"
Expand All @@ -18,33 +19,35 @@ beforeEach(() => {

afterEach(() => jest.restoreAllMocks())

it("shows an error message when there are no reports", async () => {
await act(async () =>
render(
<ThemeProvider theme={theme}>
<AppUI report_uuid="" reports={[]} reports_overview={{}} />
</ThemeProvider>,
),
)
expect(screen.getAllByText(/Sorry, no reports/).length).toBe(1)
})

it("handles sorting", async () => {
await act(async () =>
render(
async function renderAppUI(reports) {
let result
await act(async () => {
result = render(
<ThemeProvider theme={theme}>
<AppUI
dataModel={dataModel}
handleDateChange={jest.fn}
lastUpdate={new Date()}
report_date={null}
report_uuid="report_uuid"
reports={[report]}
report_date={reports ? null : undefined}
report_uuid={reports ? "report_uuid" : ""}
reports={reports ?? []}
reports_overview={{}}
user="xxx"
/>
</ThemeProvider>,
),
)
)
})
return result
}

it("shows an error message when there are no reports", async () => {
const { container } = await renderAppUI()
expect(screen.getAllByText(/Sorry, no reports/).length).toBe(1)
expect(await axe(container)).toHaveNoViolations()
})

it("handles sorting", async () => {
await renderAppUI([report])
fireEvent.click(screen.getAllByText("Comment")[0])
expect(history.location.search).toEqual("?sort_column_report_uuid=comment")
fireEvent.click(screen.getAllByText("Status")[0])
Expand All @@ -60,19 +63,10 @@ it("handles sorting", async () => {
expect(history.location.search).toEqual("")
})

async function renderAppUI() {
return await act(async () =>
render(
<ThemeProvider theme={theme}>
<AppUI handleDateChange={jest.fn} report_uuid="" reports={[]} reports_overview={{}} />
</ThemeProvider>,
),
)
}

it("resets all settings", async () => {
history.push("?date_interval=2")
await act(async () => await renderAppUI())
const { container } = await renderAppUI()
expect(await axe(container)).toHaveNoViolations()
fireEvent.click(screen.getByText("Reset settings"))
expect(history.location.search).toBe("")
})
26 changes: 17 additions & 9 deletions components/frontend/src/PageContent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createTestableSettings } from "./__fixtures__/fixtures"
import * as fetch_server_api from "./api/fetch_server_api"
import { mockGetAnimations } from "./dashboard/MockAnimations"
import { PageContent } from "./PageContent"
import { expectNoAccessibilityViolations } from "./testUtils"

jest.mock("react-toastify")
jest.mock("./api/fetch_server_api")
Expand All @@ -25,8 +26,9 @@ afterEach(() => {

async function renderPageContent({ loading = false, reports = [], report_date = null, report_uuid = "" } = {}) {
const settings = createTestableSettings()
await act(async () =>
render(
let result
await act(async () => {
result = render(
<div id="dashboard">
<PageContent
lastUpdate={new Date()}
Expand All @@ -38,32 +40,37 @@ async function renderPageContent({ loading = false, reports = [], report_date =
settings={settings}
/>
</div>,
),
)
)
})
return result
}

it("shows the reports overview", async () => {
await renderPageContent({ report_date: new Date(2023, 10, 25) })
const { container } = await renderPageContent({ report_date: new Date(2023, 10, 25) })
expect(screen.getAllByText(/Sorry, no reports/).length).toBe(1)
await expectNoAccessibilityViolations(container)
})

it("shows that the report is missing", async () => {
await renderPageContent({ reports: [{}], report_uuid: "uuid" })
const { container } = await renderPageContent({ reports: [{}], report_uuid: "uuid" })
expect(screen.getAllByText(/Sorry, this report doesn't exist/).length).toBe(1)
await expectNoAccessibilityViolations(container)
})

it("shows that the report was missing", async () => {
await renderPageContent({
const { container } = await renderPageContent({
report_date: new Date("2022-03-31"),
reports: [{}],
report_uuid: "uuid",
})
expect(screen.getAllByText(/Sorry, this report didn't exist/).length).toBe(1)
await expectNoAccessibilityViolations(container)
})

it("shows the loading spinner", async () => {
await renderPageContent({ loading: true })
const { container } = await renderPageContent({ loading: true })
expect(screen.getAllByRole("progressbar").length).toBe(1)
await expectNoAccessibilityViolations(container)
})

function expectMeasurementsCall(date, offset = 0) {
Expand All @@ -79,8 +86,9 @@ function expectMeasurementsCall(date, offset = 0) {
it("fetches measurements", async () => {
const mockedDate = new Date("2022-04-27T16:00:05+0000")
jest.setSystemTime(mockedDate)
await renderPageContent({ report_date: null })
const { container } = await renderPageContent({ report_date: null })
expectMeasurementsCall(mockedDate)
await expectNoAccessibilityViolations(container)
})

it("fetches measurements if nr dates > 1", async () => {
Expand Down
10 changes: 7 additions & 3 deletions components/frontend/src/changelog/ChangeLog.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import UpdateIcon from "@mui/icons-material/Update"
import { Button, List, ListItem, ListItemAvatar, ListItemText, Typography } from "@mui/material"
import { Button, List, ListItem, ListItemAvatar, ListItemText, Stack, Typography } from "@mui/material"
import { string } from "prop-types"
import React, { useEffect, useState } from "react"

Expand Down Expand Up @@ -71,8 +71,12 @@ function ChangeLogWithoutMemo({ report_uuid, subject_uuid, metric_uuid, source_u

return (
<>
<Typography variant="subtitle1">{scope}</Typography>
<Typography variant="subtitle2">Most recent first</Typography>
<Stack direction="column">
<Typography>{scope}</Typography>
<Typography component="span" sx={{ fontSize: "80%" }}>
Most recent first
</Typography>
</Stack>
<List dense>
{changes.map((change) => (
<Event
Expand Down
Loading

0 comments on commit 5f4f543

Please sign in to comment.