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

90 lines
5.4 KiB
TypeScript

import { test, expect, type Page } from "@playwright/test"
import { wgListResponseSchema } from "../../packages/contracts/src/wireguard"
const fixture = wgListResponseSchema.parse({ interfaces: Array.from({ length: 12 }, (_, i) => ({
id: `wg-${i + 1}`, rosId: `*${i + 1}`, name: `wg-test-${i + 1}`, serverId: "1",
serverName: "Тестовый роутер", serverCountry: "RU", listenPort: 13231 + i, mtu: 1420,
comment: "Тест", enabled: true, status: "up",
peers: [{ id: `peer-${i + 1}`, rosId: `*${i + 20}`, publicKey: `fixture-public-key-${i + 1}`,
name: `Пир ${i + 1}`, allowedIps: [`10.0.0.${i + 1}/32`], transferRx: i + 1, transferTx: i + 1 }],
})) })
async function setup(page: Page, empty = false) {
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", route => {
const path = new URL(route.request().url()).pathname
return route.fulfill({ json: path === "/api/wireguard" ? (empty ? { interfaces: [] } : fixture)
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [] : {} })
})
await page.goto("/wireguard")
}
test("WireGuard: 12 интерфейсов, сортировка порта, раскрытие и список пиров", async ({ page }) => {
const errors: string[] = []
page.on("pageerror", e => errors.push(e.message))
await setup(page)
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("button", { name: "Порт", exact: true }).click()
await expect(rows.first()).toContainText("wg-test-12")
await rows.first().click()
await expect(page.getByText("10.0.0.12/32", { exact: true })).toBeVisible()
await rows.first().click()
await expect(page.getByText("10.0.0.12/32", { exact: true })).toBeHidden()
await page.getByRole("tab", { name: /Пиры/ }).click()
await expect(rows).toHaveCount(12)
await expect(rows.last()).toContainText("10.0.0.12/32")
await page.getByRole("button", { name: "Пир", exact: true }).click()
await expect(rows.first()).toContainText("Пир 1")
expect(errors).toEqual([])
})
test("WireGuard: пустые интерфейсы и пиры", async ({ page }) => {
await setup(page, true)
await expect(page.getByText("Нет WireGuard интерфейсов", { exact: true })).toBeVisible()
await page.getByRole("tab", { name: /Пиры/ }).click()
await expect(page.getByText("Нет пиров", { exact: true })).toBeVisible()
})
for (const view of ["details", "peers"] as const) test("WireGuard traffic: observed zero differs from missing/" + view, async ({ page }) => {
await setup(page)
const interfaces = fixture.interfaces.map((row, i) => ({ ...row, peers: row.peers.map(peer => {
const { transferRx, transferTx, ...config } = peer
return i === 0 ? { ...config, transferRx: 0, transferTx: 0 } : i === 1 ? config : { ...config, transferRx, transferTx }
}) }))
await page.route("**/api/wireguard", route => route.fulfill({ json: wgListResponseSchema.parse({ interfaces }) }))
await page.reload()
const rows = page.locator("tr[data-row-id]")
if (view === "peers") await page.getByRole("tab", { name: /Пиры/ }).click()
for (const [index, value] of [[0, "0 Б"], [1, "—"], [2, "3 Б"]] as const) {
const row = rows.nth(index)
if (view === "details") await row.click()
const target = view === "details" ? row.locator("xpath=following-sibling::tr[1]") : row
await expect(target.getByLabel("RX", { exact: true })).toHaveText(value)
await expect(target.getByLabel("TX", { exact: true })).toHaveText(value)
if (view === "details") await row.click()
}
})
test("WireGuard handshake: old observation never proves online, missing remains unknown", async ({ page }, info) => {
await setup(page)
const interfaces = fixture.interfaces.slice(0, 1).map(row => ({ ...row, peers: Array.from({length:4}, (_, i) => ({ ...row.peers[0], id: "h"+i, rosId: "*H"+i, name: "Handshake "+i, latestHandshake: [undefined, "", "1h", "0s"][i] })) }))
await page.route("**/api/wireguard", route => route.fulfill({json:wgListResponseSchema.parse({interfaces})}))
await page.reload()
await expect(page.getByText("Пиров онлайн",{exact:true})).toHaveCount(0)
const label=page.getByText("Данные рукопожатия",{exact:true})
await expect(label.locator("..").locator("..")).toContainText("2/4")
await expect(page.getByText("Доступность пиров не проверена",{exact:true}).filter({visible:true})).toBeVisible()
await page.getByRole("button",{name:"Пиры: wg-test-1",exact:true}).click()
const detail=page.getByRole("region",{name:"Пиры: wg-test-1",exact:true})
await expect(detail.getByText("Нет данных",{exact:true})).toHaveCount(2)
await expect(detail.getByText("1h",{exact:true})).toBeVisible()
await page.getByRole("tab",{name:/Пиры/}).click()
const rows=page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(4)
await expect(rows.nth(0)).toContainText("Нет данных");await expect(rows.nth(1)).toContainText("Нет данных")
await expect(rows.nth(2)).toContainText("1h");await expect(rows.nth(3)).toContainText("0s")
await page.setViewportSize({width:320,height:1000});expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:info.outputPath("wireguard-handshake-320.png"),animations:"disabled"})
})