import { test, expect, type Page } from "@playwright/test" const server = { id: 1, name: "Первый роутер", host: "192.0.2.1", type: "exit-node", enabled: true, country: "RU", status: "online" } const rule = { id: "rule-1", rosId: "*1", serverId: "1", serverName: server.name, family: "ip", table: "filter", chain: "forward", action: "accept", proto: "tcp", src: "", dst: "", port: "443", iface: "", comment: "Первое правило", enabled: true, hits: 1 } const second = { ...rule, id: "rule-2", rosId: "*2", serverId: "2", serverName: "Второй роутер", comment: "Второе правило" } const address = { id: "address-1", rosId: "*A", serverId: "1", serverName: server.name, family: "ip", list: "trusted", address: "192.0.2.10", comment: "Адрес тест", disabled: false } async function setup(page: Page) { const control: { payload: unknown } = { payload: { rules: [rule, second], addressLists: [address] } } 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/auth/config" ? { required: false } : path === "/api/firewall/all" ? control.payload : path === "/api/servers" ? [server, { ...server, id: 2, name: "Второй роутер", host: "192.0.2.2" }] : {} }) }) return control } test("Firewall: сохраняет недоступную таблицу, обновляет другое устройство и восстанавливает пустой срез", async ({ page }) => { const control = await setup(page) await page.goto("/firewall") const rows = page.locator("tr[data-row-id]") await expect(rows).toHaveCount(2) control.payload = { rules: [{ ...second, port: "8443" }], addressLists: [], failures: [{ serverId: "1", serverName: server.name, family: "ip", table: "filter", error: "Таблица недоступна тест" }] } await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.getByRole("alert").filter({ hasText: "Не все срезы Firewall получены" })).toContainText("Таблица недоступна тест") await expect(rows).toHaveCount(2) await expect(page.locator('tr[data-row-id="rule-1"]')).toContainText("443") await expect(page.locator('tr[data-row-id="rule-2"]')).toContainText("8443") await expect(page.getByLabel("Сводка Firewall")).toContainText("—") await page.getByRole("option").filter({ hasText: "Второй роутер" }).click() await expect(rows).toHaveCount(1) await expect(rows.getByRole("switch")).toBeEnabled() await expect(page.getByRole("alert").filter({ hasText: "Не все срезы" })).toHaveCount(0) await page.getByRole("option").filter({ hasText: "Первый роутер" }).click() await expect(rows.getByRole("switch")).toBeDisabled() await expect(page.getByRole("button", { name: "История", exact: true })).toBeDisabled() await expect(page.getByRole("button", { name: "Новое правило", exact: true })).toBeDisabled() control.payload = { rules: [second], addressLists: [] } await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(rows).toHaveCount(0) await expect(page.getByRole("alert").filter({ hasText: "Не все срезы" })).toHaveCount(0) await expect(page.getByLabel("Сводка Firewall")).not.toContainText("—") }) test("Firewall: address-list сохраняется при сбое своего среза", async ({ page }) => { const control = await setup(page) await page.goto("/firewall?server=1") await expect(page.locator("tr[data-row-id]")).toHaveCount(1) control.payload = { rules: [rule, second], addressLists: [], failures: [{ serverId: "1", family: "ip", table: "address-list", error: "Адреса недоступны тест" }] } await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.getByRole("alert").filter({ hasText: "Не все срезы" })).toBeVisible() await page.getByRole("button", { name: /Адр. листы/ }).click() await expect(page.getByText(address.address, { exact: true })).toBeVisible() await expect(page.getByRole("switch")).toBeDisabled() await expect(page.getByRole("button", { name: "Добавить", exact: true })).toBeDisabled() control.payload = { rules: [rule, second], addressLists: [] } await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.getByText(address.address, { exact: true })).toHaveCount(0) await expect(page.getByRole("button", { name: "Добавить", exact: true })).toBeEnabled() }) test("Firewall: первичный сбой устройства не выглядит успешным пустым списком", async ({ page }) => { const control = await setup(page) control.payload = { rules: [], addressLists: [], failures: [{ serverId: "1", error: "Устройство недоступно тест" }] } await page.goto("/firewall?server=1") await expect(page.getByRole("alert").filter({ hasText: "Не все срезы" })).toContainText("Устройство недоступно тест") await expect(page.getByRole("status").filter({ hasText: "Данные Firewall пока недоступны" })).toBeVisible() await expect(page.getByLabel("Сводка Firewall")).toContainText("—") control.payload = { rules: [rule], addressLists: [] } await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.locator("tr[data-row-id]")).toHaveCount(1) await expect(page.getByRole("switch")).toBeEnabled() })