import { test, expect } from "@playwright/test" for (const kind of ["rule", "address"] as const) { test(`Firewall: новый draft ${kind} при повторном открытии и возврат фокуса`, async ({ page }) => { const rule = { id: "r1", rosId: "*1", serverId: "1", serverName: "Роутер", family: "ip", table: "filter", chain: "forward", action: "accept", proto: "tcp", src: "", dst: "", port: "443", iface: "", comment: "Исходный комментарий", enabled: true, hits: 1 } const entry = { id: "a1", rosId: "*A1", serverId: "1", serverName: "Роутер", family: "ip", list: "trusted", address: "192.0.2.10", comment: "Исходный комментарий", disabled: false } await page.route("**/health", r => r.fulfill({ json: { ok: true } })) await page.route("**/api/**", r => { const p = new URL(r.request().url()).pathname return r.fulfill({ json: p === "/api/auth/config" ? { required: false } : p === "/api/firewall/all" ? { rules: [rule], addressLists: [entry] } : p === "/api/servers" ? [{ id: 1, name: "Роутер", host: "192.0.2.1", type: "exit-node", enabled: true, country: "RU", status: "online" }] : {} }) }) await page.goto("/firewall?server=1"); await expect(page.locator("tr[data-row-id]")).toHaveCount(1) if (kind === "address") await page.getByRole("button", { name: /Адр. листы/ }).click() const action = page.getByRole("button", { name: kind === "rule" ? "Действия: forward accept" : "Действия: 192.0.2.10", exact: true }) const open = async () => { await action.click(); await page.getByRole("menuitem", { name: "Редактировать", exact: true }).click() } await open() const dialog = page.getByRole("dialog") const comment = dialog.locator('[data-slot="field"]').filter({ has: page.getByText("Комментарий", { exact: true }) }).getByRole("textbox") await expect(comment).toHaveValue("Исходный комментарий") await comment.fill("Несохранённый draft"); await page.keyboard.press("Escape") await expect(dialog).toHaveCount(0); await expect(action).toBeFocused() await open(); await expect(comment).toHaveValue("Исходный комментарий") await dialog.getByRole("button", { name: "Отмена", exact: true }).click(); await expect(dialog).toHaveCount(0) await page.getByRole("button", { name: kind === "rule" ? "Новое правило" : "Добавить", exact: true }).click() await expect(comment).toHaveValue("") }) } test("Firewall: удалённый list фильтр сбрасывается и не возвращается после refresh", async ({ page }) => { const entry = { id: "a1", rosId: "*A1", serverId: "1", serverName: "Роутер", family: "ip", list: "trusted", address: "192.0.2.10", comment: "", disabled: false } let entries = [entry] await page.route("**/health", r => r.fulfill({ json: { ok: true } })) await page.route("**/api/**", r => { const p = new URL(r.request().url()).pathname return r.fulfill({ json: p === "/api/auth/config" ? { required: false } : p === "/api/firewall/all" ? { rules: [], addressLists: entries } : p === "/api/servers" ? [{ id: 1, name: "Роутер", host: "192.0.2.1", type: "exit-node", enabled: true, country: "RU", status: "online" }] : {} }) }) await page.goto("/firewall?server=1"); await page.getByRole("button", { name: /Адр. листы/ }).click() await page.getByRole("button", { name: "trusted", exact: true }).click() const other = { ...entry, id: "a2", rosId: "*A2", list: "other", address: "192.0.2.20" } entries = [other]; await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.getByRole("button", { name: "Действия: 192.0.2.20", exact: true })).toBeVisible() entries = [entry, other]; await page.getByRole("button", { name: "Обновить", exact: true }).click() await expect(page.getByRole("button", { name: "Действия: 192.0.2.10", exact: true })).toBeVisible() await expect(page.getByRole("button", { name: "Действия: 192.0.2.20", exact: true })).toBeVisible() })