Files
MikrotikManager/tests/e2e/operational-a11y.spec.ts
T

65 lines
3.9 KiB
TypeScript

import { test, expect } from "@playwright/test"
import axe from "axe-core"
import { emptyAlerts, emptyOutbox } from "./fixtures/alerts"
import { certificateState } from "./fixtures/certificates"
import { state as containerState } from "./fixtures/containers"
import { server } from "./fixtures/users"
for (const theme of ["dark", "light"] as const) for (const width of [1280, 320]) {
for (const path of ["alerts", "certificates", "containers", "filters", "filters-error", "uptime"]) {
test(`Operational accessibility ${path} ${theme} ${width}`, async ({ page }) => {
await page.setViewportSize({ width, height: 1000 })
await page.addInitScript(theme => localStorage.setItem("rl-theme", theme), theme)
const writes: string[] = []
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", route => {
const url = new URL(route.request().url()).pathname
if (route.request().method() !== "GET") writes.push(url)
if (path === "filters-error" && url === "/api/filters/rules") return route.fulfill({ status: 503, json: { error: "Fixture unavailable" } })
const json = url === "/api/auth/config" ? { required: false }
: url === "/api/servers" ? [{ ...server, type: "home-router" }]
: url === "/api/certificates/state" ? certificateState([])
: url === "/api/certificates/renew-settings" ? { enabled: true, intervalSec: 300, renewBeforeDays: 30 }
: url === "/api/containers/state" ? containerState([])
: url === "/api/alerts" ? emptyAlerts
: url === "/api/alerts/outbox" ? emptyOutbox
: url === "/api/uptime/speed-probes" ? { probes: [] }
: url === "/api/uptime/speed-test/runs" ? { runs: [] }
: url === "/api/uptime/probes" ? { probes: [] }
: url === "/api/filters/rules" ? { rulesets: [{ serverId: "1", rules: [] }], greTunnels: [], live: true }
: url === "/api/filters/gre-tunnels" ? { tunnels: [] }
: url === "/api/recursive-routes" ? { routes: [] }
: {}
return route.fulfill({ json })
})
await page.goto("/" + (path === "filters-error" ? "filters" : path))
await expect(page.locator("main").first()).toBeVisible()
if (path === "certificates") await expect(page.getByText("Включено", { exact: true })).toBeVisible()
if (path === "alerts") await expect(page.getByText("Правила не найдены", { exact: true })).toBeVisible()
if (path === "filters-error") await expect(page.getByRole("alert").filter({ hasText: "Не удалось загрузить Filters" })).toBeVisible()
await page.evaluate(() => document.fonts.ready)
// Audit settled colours, after provider hydration and transitions.
await page.waitForTimeout(900)
await page.addScriptTag({ content: axe.source })
const violations = await page.evaluate(async () => (window as unknown as { axe: typeof axe }).axe.run(document, {
runOnly: { type: "tag", values: ["wcag2a", "wcag2aa", "wcag21aa"] },
}))
expect(violations.violations).toEqual([])
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
if (path === "certificates") {
const blocks = page.getByRole("region", { name: /^Команды RouterOS:/ })
await expect(blocks).toHaveCount(3)
for (const block of await blocks.all()) {
await block.focus()
await expect(block).toBeFocused()
if (await block.evaluate(el => el.scrollWidth > el.clientWidth + 1)) {
await block.press("ArrowRight")
await expect.poll(() => block.evaluate(el => el.scrollLeft)).toBeGreaterThan(0)
}
}
}
expect(writes).toEqual([])
})
}
}