Files
MikrotikManager/tests/e2e/migrated-tables.spec.ts
T

111 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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/)
})