Files
MikrotikManager/tests/e2e/network-kpi-readability.spec.ts
T

57 lines
4.0 KiB
TypeScript

import { test, expect } from "@playwright/test"
import axe from "axe-core"
for (const path of ["/bgp", "/gre", "/vxlan", "/ospf"]) for (const width of [320, 390]) test(`Network KPI labels remain readable ${path}/${width}`, async ({ page }) => {
await page.setViewportSize({ width, height: 1000 })
await page.route("**/health", r => r.fulfill({ json: { ok: true } }))
await page.route("**/api/**", r => {
const endpoint = new URL(r.request().url()).pathname
return r.fulfill({ json: endpoint === "/api/auth/config" ? { required: false }
: endpoint === "/api/servers" ? [{ id: 1, name: "Роутер", host: "192.0.2.1", enabled: true, country: "RU", status: null }]
: endpoint === "/api/bgp/catalog" ? { sessions: [], failures: [] }
: endpoint === "/api/ospf/catalog" ? { interfaces: [], neighbors: [], instances: [], bfdSessions: [], routes: [], failures: [] }
: endpoint === "/api/gre/tunnels" ? { tunnels: [], failures: [] }
: endpoint === "/api/vxlan" ? { tunnels: [], failures: [] } : {} })
})
await page.goto(path)
const title = path === "/bgp" ? "Сводка BGP" : path === "/gre" ? "Сводка GRE" : path === "/vxlan" ? "Сводка VXLAN" : "Сводка OSPF"
const summary = page.getByLabel(title, { exact: true })
await expect(summary).toBeVisible()
const labels = summary.locator('.text-muted-foreground.truncate')
await expect.poll(() => labels.count()).toBeGreaterThan(0)
// Compare actual rendered text bounds, rather than testing particular grid classes.
await expect.poll(() => labels.evaluateAll(elements => elements.every(el => el.scrollWidth <= el.clientWidth + 1))).toBe(true)
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
})
for (const theme of ["light", "dark"]) test(`ECMP draft: disabled instructions remain readable and enable is local/${theme}`, async ({ page }) => {
await page.addInitScript(value => localStorage.setItem("rl-theme", value), theme)
let writes = 0
await page.route("**/health", r => r.fulfill({ json: { ok: true } }))
await page.route("**/api/**", r => {
const path = new URL(r.request().url()).pathname
if (r.request().method() !== "GET" && !path.endsWith("/preview")) writes++
return r.fulfill({ json: path === "/api/auth/config" ? { required: false }
: path === "/api/servers" ? [{ id: 1, name: "Роутер", host: "192.0.2.1", type: "home-router", country: "RU", enabled: true, status: null }]
: path === "/api/filters/rules" ? { rulesets: [] } : path === "/api/uptime/speed-probes" ? { probes: [] }
: path === "/api/ospf/catalog" ? { interfaces: [], instances: [], neighbors: [], bfdSessions: [], routes: [], failures: [] }
: path.endsWith("/preview") ? { serverId: 1, serverName: "Роутер", pingWeight: 60, interfacesTotal: 0, changedCount: 0, unchangedCount: 0, interfaces: [], changes: [] } : {} })
})
await page.goto("/route-optimizer")
const toggle = page.getByRole("switch", { name: "Черновик ECMP", exact: true })
const group = page.getByRole("group", { name: "Параметры черновика ECMP", exact: true })
await expect(toggle).toHaveAttribute("aria-checked", "false")
const range = group.getByRole("slider", { name: "Максимальное число путей ECMP", exact: true })
await expect(range).toBeDisabled()
await group.scrollIntoViewIfNeeded()
await page.addScriptTag({ content: axe.source })
for (const enabled of [false, true]) {
if (enabled) { await toggle.click(); await expect(range).toBeEnabled(); await range.focus(); await range.press("ArrowRight"); await expect(range).toHaveValue("5") }
const violations = await group.evaluate(async element => (await (window as unknown as { axe: typeof axe }).axe.run(element, {
runOnly: { type: "tag", values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"] },
})).violations.map(v => ({ id: v.id, targets: v.nodes.map(n => n.target) })))
expect(violations).toEqual([])
}
expect(writes).toBe(0)
})