Files
MikrotikManager/tests/e2e/firewall-delete.spec.ts

73 lines
4.7 KiB
TypeScript

import { test, expect } from "@playwright/test"
for (const kind of ["rule", "address"] as const) {
for (const family of ["ip", "ip6"] as const) {
test(`Firewall: удаление ${kind}/${family} требует подтверждения`, async ({ page }) => {
let attempts = 0
let deleted = false
let release: (() => void) | undefined
const gate = new Promise<void>(resolve => { release = resolve })
const rule = { id: "rule-1", rosId: "*R/1", serverId: "1", serverName: "Роутер", family, table: "filter", chain: "forward", action: "accept", proto: "tcp", src: "", dst: "", port: "443", iface: "", comment: "Правило тест", enabled: true, hits: 1 }
const entry = { id: "address-1", rosId: "*A/1", serverId: "1", serverName: "Роутер", family, list: "trusted", address: family === "ip" ? "192.0.2.10" : "2001:db8::10", comment: "Адрес тест", disabled: false }
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", async route => {
const path = new URL(route.request().url()).pathname
if (route.request().method() === "DELETE") {
attempts++
expect(path).toBe(kind === "rule" ? "/api/firewall/rules" : "/api/firewall/address-lists")
expect(route.request().postDataJSON()).toEqual(kind === "rule"
? { serverId: "1", family, table: "filter", rosId: "*R/1" }
: { serverId: "1", family, rosId: "*A/1" })
if (attempts === 1) { await gate; return route.fulfill({ status: 403, json: { error: "Удаление запрещено тест" } }) }
if (attempts === 2) return route.fulfill({ json: {} })
if (attempts === 3) return route.fulfill({ json: { ok: false } })
deleted = true
return route.fulfill({ json: { ok: true } })
}
return route.fulfill({ json: path === "/api/auth/config" ? { required: false }
: path === "/api/firewall/all" ? { rules: kind === "rule" && !deleted ? [rule] : [], addressLists: kind === "address" && !deleted ? [entry] : [] }
: path === "/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")
if (family === "ip6") await page.getByRole("button", { name: "IPv6", exact: true }).click()
if (kind === "address") await page.getByRole("button", { name: /Адр. листы/ }).click()
const open = async () => {
await page.getByRole("button", { name: kind === "rule" ? "Действия: forward accept" : "Действия: " + entry.address, exact: true }).click()
await page.getByRole("menuitem", { name: kind === "rule" ? "Удалить правило" : "Удалить", exact: true }).click()
}
await open()
const dialog = page.getByRole("alertdialog")
await expect(dialog).toContainText("Роутер")
await expect(dialog).toContainText(kind === "rule" ? rule.comment : entry.address)
await dialog.getByRole("button", { name: "Отмена" }).click()
await expect(dialog).toHaveCount(0)
expect(attempts).toBe(0)
await open()
const remove = dialog.getByRole("button", { name: "Удалить", exact: true })
await remove.evaluate(button => { (button as HTMLButtonElement).click(); (button as HTMLButtonElement).click() })
await expect.poll(() => attempts).toBe(1)
await expect(remove).toBeDisabled()
await expect(dialog.getByRole("button", { name: "Отмена" })).toBeDisabled()
await expect(dialog.getByRole("status")).toContainText("Ожидание результата")
await page.keyboard.press("Escape")
await expect(dialog).toBeVisible()
release!()
await expect(dialog.getByRole("alert")).toContainText("Удаление запрещено тест")
await dialog.getByRole("button", { name: "Отмена" }).click()
await expect(dialog).toHaveCount(0)
await open()
await expect(dialog.getByRole("alert")).toHaveCount(0)
for (let i = 2; i <= 3; i++) {
await remove.click()
await expect.poll(() => attempts).toBe(i)
await expect(dialog.getByRole("alert")).toContainText("Сервер не подтвердил удаление")
await expect(page.getByText(kind === "rule" ? "Правило удалено" : "Запись удалена", { exact: true })).toHaveCount(0)
}
await remove.click()
await expect(dialog).toHaveCount(0)
expect(attempts).toBe(4)
await expect(page.getByRole("button", { name: kind === "rule" ? "Действия: forward accept" : "Действия: " + entry.address, exact: true })).toHaveCount(0)
})
}
}