fix(ui): открывать выбранный сервер из очереди проблем

This commit is contained in:
Denozordec committed 2026-09-20 16:51:28 +07:00
1 parent 4ec32765df
commit 668c7c6823
5 files changed
+106 -14

No files matched your search

+11 -1
View File
@@ -1,11 +1,15 @@
import { test, expect, type Page } from "@playwright/test"
import { serverReadSchema } from "../../packages/contracts/src/servers"
async function setup(page: Page, initiallyFailed = false, serverCount = 1) {
const control = { failed: initiallyFailed, partial: false, prefixes: 321, hold: false, holdPath: "/api/bgp/sessions", fallback: false, failFallback: false, pending: 0, release: () => {} }
let release!: () => void
const gate = new Promise<void>(resolve => { release = resolve })
control.release = release
const servers = Array.from({ length: serverCount }, (_, index) => ({ id: index + 1, name: serverCount === 1 ? "Узел" : `Узел ${index + 1}`, host: `192.0.2.${index + 1}`, site: "TEST", country: "RU", asn: "64512", type: "exit-node", enabled: true, status: serverCount === 1 ? "online" : "offline", latency: 10, os: "7", model: "CHR" }))
const servers = Array.from({ length: serverCount }, (_, index) => ({ id: index + 1, name: serverCount === 1 ? "Узел" : `Узел ${index + 1}`, host: `192.0.2.${index + 1}`, site: "TEST", country: "RU", asn: "64512", type: "exit-node", enabled: true, status: serverCount === 1 ? "online" : "offline", latency: 10, os: "7", model: "CHR" })).map(row => serverReadSchema.parse({
port: 443, useSsl: true, verifySsl: true, username: "test", password: "fixture-only", comment: "", lanSubnet: "", wanUplinks: [],
createdAt: "2026-09-20T00:00:00Z", updatedAt: "2026-09-20T00:00:00Z", uptime: null, cpuLoad: null, freeMemory: null, totalMemory: null, identityName: null, sessions: 0, polledAt: null, ...row,
}))
const snapshot = { sampledAt: "2026-09-20T00:00:00Z", servers, greTunnels: [], filtersRulesets: [], speedProbes: [], routeLookupByServerId: {}, wanRuntimeByHomeId: {} }
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", async route => {
@@ -62,6 +66,12 @@ test("Дашборд: очередь над измерениями, полный
await page.getByRole("navigation", { name: "Путь страницы" }).scrollIntoViewIfNeeded()
await page.screenshot({ path: "test-results/dashboard-priority-mobile.png", animations: "disabled" })
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
await serverLinks.first().click()
await expect(page).toHaveURL(/\/servers\?server=1$/)
await expect(page.getByRole("status", { name: "Сервер по ссылке" })).toContainText("Выбран сервер: Узел 1")
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
await page.goBack()
await expect(queue).toBeVisible()
})
test("Дашборд: первоначальная ошибка не подменяется нулями и исправным состоянием", async ({ page }) => {
+45 -3
View File
@@ -14,7 +14,7 @@ function server(id: number): ServerRead {
})
}
async function setup(page: Page, intercept?: (route: Route, path: string) => Promise<boolean>, count = 2) {
async function setup(page: Page, intercept?: (route: Route, path: string) => Promise<boolean>, count = 2, url = "/servers") {
const rows = Array.from({ length: count }, (_, i) => server(i + 1))
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", async route => {
@@ -36,8 +36,8 @@ async function setup(page: Page, intercept?: (route: Route, path: string) => Pro
}
await route.fulfill({ json: body })
})
await page.goto("/servers")
await expect(page.getByText("Проверка 1", { exact: true })).toBeVisible()
await page.goto(url)
if (url === "/servers") await expect(page.getByText("Проверка 1", { exact: true })).toBeVisible()
}
async function edit(page: Page, id = 1) {
@@ -45,6 +45,48 @@ async function edit(page: Page, id = 1) {
await page.getByRole("menuitem", { name: "Редактировать", exact: true }).click()
}
test("ссылка на сервер: выбор, опрос одного устройства, сброс и возврат", async ({ page }) => {
const calls: string[] = []
await setup(page, async (route, path) => {
if (!path.endsWith("/poll")) return false
calls.push(path)
await route.fulfill({ json: {} })
return true
}, 2, "/servers?server=2&keep=1")
const context = page.getByRole("status", { name: "Сервер по ссылке" })
await expect(context).toContainText("Выбран сервер: Проверка 2")
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
await page.getByRole("button", { name: "Проверить сервер", exact: true }).click()
await expect(page.getByText("Опрос: успешно 1 из 1", { exact: true })).toBeVisible()
expect(calls).toEqual(["/api/servers/2/poll"])
await context.getByRole("link", { name: "Все серверы", exact: true }).click()
await expect(page).toHaveURL(/\/servers\?keep=1$/)
await expect(page.locator("tr[data-row-id]")).toHaveCount(2)
await page.goBack()
await expect(context).toContainText("Выбран сервер: Проверка 2")
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
await page.reload()
await expect(context).toContainText("Выбран сервер: Проверка 2")
await page.setViewportSize({ width: 390, height: 844 })
await context.scrollIntoViewIfNeeded()
await page.screenshot({ path: "test-results/server-link-mobile.png", animations: "disabled" })
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
})
for (const apiStatus of [200, 403, 500]) {
test(`ссылка на отсутствующий сервер: ответ ${apiStatus} не выбирает другое устройство`, async ({ page }) => {
await setup(page, async (route, path) => {
if (path !== "/api/servers" || apiStatus === 200) return false
await route.fulfill({ status: apiStatus, json: { error: "Список недоступен" } })
return true
}, 2, "/servers?server=999")
const context = page.getByRole("status", { name: "Сервер по ссылке" })
await expect(context).toContainText(apiStatus === 200 ? "Сервер не найден или недоступен" : "Не удалось загрузить сервер")
await expect(page.locator("tr[data-row-id]")).toHaveCount(0)
await expect(page.getByRole("button", { name: "Проверить сервер", exact: true })).toBeDisabled()
})
}
test("таблица v9 сохраняет все строки, сортировку и раскрытие деталей", async ({ page }) => {
await setup(page, undefined, 12)
const rows = page.locator('tr[data-row-id]')