fix(ui): перенести основные таблицы на ReUI v9

This commit is contained in:
Denozordec committed 2026-09-13 21:01:23 +07:00
1 parent 3d3c45e4d2
commit e66762ca2e
14 files changed
+287 -110

No files matched your search

+110
View File
@@ -0,0 +1,110 @@
import { test, expect, type Page } from "@playwright/test"
import type { EvoBgpCatalogSnapshot } from "../../lib/evobgp-context"
import { statisticsDtoSchema } from "../../packages/contracts/src/statistics"
const catalog: EvoBgpCatalogSnapshot = {
fetchedAt: "2026-09-13T00:00:00Z", modules: [],
asns: Array.from({ length: 12 }, (_, i) => ({
id: String(i + 1), asn: `AS${65001 + i}`, org: `Организация ${i + 1}`,
country: "RU", prefixes: i + 1, filter: "", updated: "2026-09-13", enabled: true,
})),
domains: Array.from({ length: 12 }, (_, i) => ({
id: String(i + 1), domain: `test${i + 1}.example`, resolvedIp: `192.0.2.${i + 1}`,
asn: "AS65001", purpose: "Тест", filter: "", updated: "2026-09-13", enabled: true,
})),
ipRanges: Array.from({ length: 12 }, (_, i) => ({
id: String(i + 1), cidr: `192.0.${i + 1}.0/24`, asn: "AS65001", country: "RU",
purpose: "Тест", filter: "", updated: "2026-09-13", enabled: true,
})),
communities: Array.from({ length: 12 }, (_, i) => ({
id: String(i + 1), value: `65001:${i + 1}`, name: `Community ${i + 1}`,
description: `Описание ${i + 1}`, type: "standard", filterIds: [],
serverCount: i + 1, prefixCount: i + 1, action: "permit", enabled: true,
})),
}
async function setup(page: Page, path: string) {
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", route => {
const path = new URL(route.request().url()).pathname
const json = path === "/api/auth/config" ? { required: false }
: path === "/api/evobgp/settings" ? { enabled: true, baseUrl: "", secretConfigured: true }
: path === "/api/evobgp/catalog" ? catalog
: path === "/api/servers" ? [] : {}
return route.fulfill({ json })
})
await page.goto(path)
}
for (const [path, placeholder, last] of [
["/asns", "Поиск по ASN, имени, префиксам…", "AS65012"],
["/domains", "Поиск по домену…", "test12.example"],
["/ip-ranges", "Поиск по CIDR, ASN…", "192.0.12.0/24"],
]) {
test(`${path}: страницы и поиск с последней страницы`, async ({ page }) => {
const errors: string[] = []
page.on("pageerror", e => errors.push(e.message))
await setup(page, path)
const rows = page.locator("tr[data-row-id]")
await expect(page.getByText("1–10 из 12", { exact: true })).toBeVisible()
await expect(rows).toHaveCount(10)
await page.getByRole("button", { name: "Следующая страница", exact: true }).click()
await expect(rows).toHaveCount(2)
await expect(rows.last()).toContainText(last)
await page.getByPlaceholder(placeholder).fill(last)
await expect(rows).toHaveCount(1)
await expect(rows.first()).toContainText(last)
await expect(page.getByText("1–1 из 1", { exact: true })).toBeVisible()
await page.getByPlaceholder(placeholder).fill("несуществующее значение")
await expect(rows).toHaveCount(0)
await page.getByPlaceholder(placeholder).fill("")
await expect(rows).toHaveCount(10)
expect(errors).toEqual([])
})
}
test("ASN: числовая сортировка охватывает обе страницы", async ({ page }) => {
await setup(page, "/asns")
await expect(page.getByText("1–10 из 12", { exact: true })).toBeVisible()
await page.getByRole("button", { name: "Префиксов", exact: true }).click()
await expect(page.locator("tr[data-row-id]").first()).toContainText("AS65012")
await page.getByRole("button", { name: "Следующая страница", exact: true }).click()
await expect(page.locator("tr[data-row-id]").last()).toContainText("AS65001")
})
test("Communities: все 12 строк и выбор деталей", async ({ page }) => {
await setup(page, "/communities")
await expect(page.locator("tr[data-row-id]")).toHaveCount(12)
await page.locator('tr[data-row-id="12"]').click()
await expect(page.locator('tr[data-row-id="12"]')).toHaveAttribute("data-state", "selected")
await expect(page.getByText("Описание 12", { exact: true })).toHaveCount(2)
await expect(page.getByText("Описание 12", { exact: true }).last()).toBeVisible()
await page.screenshot({ path: "test-results/communities-migrated.png", fullPage: true })
})
test("Статистика: CompactDataGrid сохраняет 12 строк, сортировку и переход в срез", async ({ page }) => {
const dto = statisticsDtoSchema.parse({
from: "2026-09-01", to: "2026-09-13", grain: "day",
kpis: { bytes: 7800, packets: 78, avgBps: 100, users: 12, servers: 1, ifaces: 1, topCountry: "RU", topService: "https" },
series: [], servers: [], interfaces: [], countries: [], services: [], asns: [],
users: Array.from({ length: 12 }, (_, i) => ({
id: `user-${i + 1}`, label: `Пользователь ${i + 1}`, bytes: (i + 1) * 100,
packets: i + 1, bps: i + 1, percent: i + 1,
})),
})
await page.route("**/api/statistics?**", route => route.fulfill({ json: dto }))
// The general API handler falls back to the previously registered statistics route.
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", route => {
const path = new URL(route.request().url()).pathname
if (path === "/api/statistics") return route.fallback()
return route.fulfill({ json: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [] : {} })
})
await page.goto("/statistics?from=2026-09-01&to=2026-09-13&dim=users")
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("button", { name: "Байты", exact: true }).first().click()
await expect(rows.first()).toContainText("Пользователь 12")
await rows.first().click()
await expect(page).toHaveURL(/userId=user-12/)
})