fix(ui): ограничить боковой каталог устройств
This commit is contained in:
1 parent
2bdcc1621f
commit
1cce712833
6 files changed
+141
-10
No files matched your search
@@ -1,8 +1,9 @@
|
||||
import { SCHEDULER_JOB_KEYS } from "../../lib/scheduler-settings"
|
||||
import { test, expect, type Page } from "@playwright/test"
|
||||
import axe from "axe-core"
|
||||
import type { SpeedProbeApiRow } from "../../components/data-grids/probes-speed-probes-data-grid"
|
||||
|
||||
async function setup(page: Page, path: string, count = 12) {
|
||||
async function setup(page: Page, path: string, count = 12, grouped = false) {
|
||||
const probes: SpeedProbeApiRow[] = Array.from({ length: count }, (_, i) => ({
|
||||
id: String(i + 1), srcServerId: String(i + 1), dstServerId: String(count + 1), srcInterface: "ether1",
|
||||
dstInterface: "ether1", protocol: "tcp", direction: "both", durationSec: "10", enabled: true,
|
||||
@@ -17,7 +18,7 @@ async function setup(page: Page, path: string, count = 12) {
|
||||
if (path === "/api/scheduler/status") return route.fulfill({ json: { jobs } })
|
||||
if (path === "/api/scheduler/jobs/alert_engine/run-now") return route.fulfill({ json: { ok: true, result: { status: "ok", error: null, result: { v: 1, job: "alert_engine", sampledAt: "2026-10-03T00:00:00Z", rulesChecked: 0, standaloneFires: 0, groupFires: 0, skippedNoTelegram: false } }, status: { jobs } } })
|
||||
return route.fulfill({ json: path === "/api/uptime/speed-probes" ? { probes }
|
||||
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? Array.from({length:count+1},(_,i)=>({id:i+1,name:i<count?`Источник ${i+1}`:"Цель",host:`192.0.2.${i%250+1}`,type:"exit-node",enabled:true,country:"RU",site:"TEST",asn:"",status:null,latency:null,os:"7",model:"CHR",sessions:0,wanUplinks:[]}))
|
||||
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? Array.from({length:count+1},(_,i)=>({id:i+1,name:i<count?`Источник ${i+1}`:"Цель",host:`192.0.2.${i%250+1}`,type:"exit-node",enabled:true,country:"RU",site:grouped?(i%2?"Площадка B":"Площадка A"):"TEST",asn:"",status:null,latency:null,os:"7",model:"CHR",sessions:0,wanUplinks:[]}))
|
||||
: path === "/api/evobgp/settings" ? { enabled: false, baseUrl: "", secretConfigured: false }
|
||||
: path === "/api/traffic/flow/settings" ? {
|
||||
enabled: false, collectorIp: "10.0.0.1", flowListenPort: 2055, wgListenPort: 51820,
|
||||
@@ -83,7 +84,7 @@ test("Large speed probes: 50 строк, глобальная сортировк
|
||||
console.log(JSON.stringify(sample))
|
||||
await info.attach("large-speed-probes-metrics", { body: JSON.stringify(sample), contentType: "application/json" })
|
||||
expect(sample.scheduleNodes).toBeLessThan(2000)
|
||||
expect(sample.domNodes).toBeLessThan(12000)
|
||||
expect(sample.domNodes).toBeLessThan(2500)
|
||||
await page.getByRole("button", { name: "Следующая страница", exact: true }).click()
|
||||
await expect(rows.first()).toHaveAttribute("data-row-id", "51")
|
||||
await page.getByRole("button", { name: "Обновить пробы скорости", exact: true }).click()
|
||||
@@ -103,3 +104,71 @@ test("Large speed probes: 50 строк, глобальная сортировк
|
||||
await expect(rows).toHaveCount(1)
|
||||
await expect(rows.first()).toHaveAttribute("data-row-id", "1")
|
||||
})
|
||||
|
||||
for (const theme of ["dark", "light"]) test(`Large server rail: URL, страницы, поиск и клавиатура на1001 устройстве/${theme}`, async ({ page }, info) => {
|
||||
await page.addInitScript(value => localStorage.setItem("rl-theme", value), theme)
|
||||
await setup(page, "/probes?server=1000&keep=1", 1000)
|
||||
const rail = page.locator("aside").filter({ has: page.getByRole("listbox", { name: "Серверы", exact: true }) })
|
||||
const list = rail.getByRole("listbox", { name: "Серверы", exact: true })
|
||||
await expect(list.getByRole("option")).toHaveCount(50)
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Источник 1000")
|
||||
await expect(rail.getByText("951–1000 из 1001", { exact: true })).toBeVisible()
|
||||
expect(await rail.locator("*").count()).toBeLessThan(1200)
|
||||
await info.attach("large-rail-metrics", { body: JSON.stringify({ fixtureDevices: 1001, renderedOptions: await list.getByRole("option").count(), railNodes: await rail.locator("*").count(), domNodes: await page.locator("*").count() }), contentType: "application/json" })
|
||||
await list.focus()
|
||||
await page.keyboard.press("End")
|
||||
await expect(page).toHaveURL(url => url.searchParams.get("server") === "1001" && url.searchParams.get("keep") === "1")
|
||||
await expect(list.getByRole("option")).toHaveCount(1)
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Цель")
|
||||
await page.keyboard.press("Home")
|
||||
await expect(page).toHaveURL(url => url.searchParams.get("server") === "1" && url.searchParams.get("keep") === "1")
|
||||
await expect(list.getByRole("option")).toHaveCount(50)
|
||||
await page.keyboard.press("ArrowDown")
|
||||
await expect(page).toHaveURL(url => url.searchParams.get("server") === "2" && url.searchParams.get("keep") === "1")
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Источник 2")
|
||||
await rail.getByRole("button", { name: "Следующие устройства", exact: true }).click()
|
||||
await expect(list.getByRole("option").first()).toContainText("Источник 51")
|
||||
await page.getByRole("button", { name: "Обновить устройства диагностики", exact: true }).click()
|
||||
await expect(page.getByRole("button", { name: "Обновить устройства диагностики", exact: true })).toBeEnabled()
|
||||
await expect(rail.getByText("51–100 из 1001", { exact: true })).toBeVisible()
|
||||
const search = rail.getByRole("textbox", { name: "Поиск сервера", exact: true })
|
||||
await search.fill("Источник 1000")
|
||||
await expect(list.getByRole("option")).toHaveCount(1)
|
||||
await list.getByRole("option").click()
|
||||
await expect(page).toHaveURL(url => url.searchParams.get("server") === "1000" && url.searchParams.get("keep") === "1")
|
||||
await search.fill("")
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Источник 1000")
|
||||
await page.setViewportSize({ width: 320, height: 900 })
|
||||
await page.getByRole("button", { name: "Серверы", exact: true }).click()
|
||||
const sheet = page.getByRole("dialog")
|
||||
await expect(sheet.getByRole("option")).toHaveCount(50)
|
||||
await expect(sheet.getByRole("option", { selected: true })).toContainText("Источник 1000")
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
|
||||
expect(await sheet.getByRole("button", { name: "Следующие устройства", exact: true }).evaluate(el => el.getBoundingClientRect().right <= innerWidth)).toBe(true)
|
||||
expect(await sheet.getByRole("listbox", { name: "Серверы", exact: true }).evaluate(el => { const id = el.getAttribute("aria-activedescendant"); return !!id && el.contains(document.getElementById(id)) })).toBe(true)
|
||||
await page.addScriptTag({ content: axe.source })
|
||||
const audit = await page.evaluate(async () => (window as unknown as { axe: typeof axe }).axe.run(document.querySelector('[role="dialog"]')!, { runOnly: { type: "tag", values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"] } }))
|
||||
await info.attach("large-rail-axe", { body: JSON.stringify(audit), contentType: "application/json" })
|
||||
expect(audit.violations.map(violation => ({ id: violation.id, nodes: violation.nodes.map(node => node.target) }))).toEqual([])
|
||||
await page.screenshot({ path: `test-results/large-server-rail-mobile-${theme}.png`, animations: "disabled" })
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(page.getByRole("button", { name: "Серверы", exact: true })).toBeFocused()
|
||||
})
|
||||
|
||||
test("Large server rail: выбранное устройство и граница площадок", async ({ page }) => {
|
||||
await setup(page, "/probes?server=1000", 1000, true)
|
||||
const rail = page.locator("aside").filter({ has: page.getByRole("listbox", { name: "Серверы", exact: true }) })
|
||||
const list = rail.getByRole("listbox", { name: "Серверы", exact: true })
|
||||
await expect(list.getByRole("option")).toHaveCount(1)
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Источник 1000")
|
||||
await expect(rail.getByText("Площадка B", { exact: true })).toBeVisible()
|
||||
await list.focus()
|
||||
await page.keyboard.press("End")
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Цель")
|
||||
await expect(list.getByRole("option")).toHaveCount(50)
|
||||
await expect(rail.getByText("Площадка A", { exact: true })).toBeVisible()
|
||||
await expect(rail.getByText("Площадка B", { exact: true })).toBeVisible()
|
||||
await page.keyboard.press("Home")
|
||||
await expect(list.getByRole("option", { selected: true })).toContainText("Источник 1")
|
||||
await expect(list.getByRole("option")).toHaveCount(50)
|
||||
})
|
||||
Reference in new issue
Block a user