Files
MikrotikManager/tests/e2e/backups-settings.spec.ts
T

66 lines
6.8 KiB
TypeScript

import { test, expect, type Page } from "@playwright/test"
import { setupBackups, schedule, storage } from "./fixtures/backups"
async function open(page: Page) { await page.goto("/backups"); await page.getByRole("tab", { name: "Настройки", exact: true }).click(); await expect(page.getByRole("spinbutton", { name: "Час запуска" })).toBeVisible() }
const save = (page: Page) => page.getByRole("button", { name: "Сохранить расписание", exact: true })
test("Бэкапы: save расписания не сохраняет хранилище", async ({ page }) => {
await setupBackups(page); let puts = 0, storagePuts = 0, body: Record<string, unknown> = {}
await page.route("**/api/backups/storage", r => { if (r.request().method() === "PUT") storagePuts++; return r.fallback() })
await page.route("**/api/backups/schedule", r => { if (r.request().method() !== "PUT") return r.fallback(); puts++; body = r.request().postDataJSON(); return r.fulfill({ json: { ...schedule, ...body } }) })
await open(page); await page.getByRole("spinbutton", { name: "Час запуска" }).fill("7"); await page.getByRole("spinbutton", { name: "Минута запуска" }).fill("7")
await save(page).click(); await expect(page.getByText("Расписание сохранено", { exact: true })).toBeVisible()
expect(puts).toBe(1); expect(storagePuts).toBe(0); expect(body.hour).toBe(7); expect(body.minute).toBe(7); expect(body.format).toBe("rsc")
})
for (const failure of ["API", "mismatch"]) test("Бэкапы: ошибка " + failure + " сохраняет расписание", async ({ page }) => {
await setupBackups(page)
await page.route("**/api/backups/schedule", r => r.request().method() !== "PUT" ? r.fallback() : r.fulfill(failure === "API" ? { status: 503, json: { error: "Расписание отказало" } } : { json: schedule }))
await open(page); await page.getByRole("spinbutton", { name: "Час запуска" }).fill("7"); await save(page).click()
await expect(page.getByText("Расписание сохранено", { exact: true })).toHaveCount(0)
await expect(page.getByRole("spinbutton", { name: "Час запуска" })).toHaveValue("7")
await expect(save(page)).toBeEnabled()
})
test("Бэкапы: неверные числа и пустой явный выбор не отправляются", async ({ page }) => {
await setupBackups(page); let puts = 0
await page.route("**/api/backups/schedule", r => { if (r.request().method() === "PUT") puts++; return r.fallback() })
await open(page)
for (const value of ["", "1.5", "24"]) { await page.getByRole("spinbutton", { name: "Час запуска" }).fill(value); await save(page).click(); await expect(page.getByRole("spinbutton", { name: "Час запуска" })).toHaveValue(value) }
await page.getByRole("spinbutton", { name: "Час запуска" }).fill("0")
await page.getByRole("button", { name: "Сбросить", exact: true }).click(); await save(page).click(); expect(puts).toBe(0)
})
test("Бэкапы: все включённые устройства передаются явно как пустой список", async ({ page }) => {
await setupBackups(page); let body: Record<string, unknown> = {}
await page.route("**/api/backups/schedule", r => { if (r.request().method() !== "PUT") return r.fallback(); body = r.request().postDataJSON(); return r.fulfill({ json: { ...schedule, ...body } }) })
await open(page); await page.getByRole("checkbox", { name: "Все включённые серверы", exact: true }).check(); await save(page).click()
await expect(page.getByText("Расписание сохранено", { exact: true })).toBeVisible(); expect(body.serverIds).toEqual([])
})
test("Бэкапы: общий lock не допускает второй PUT и блокирует поля", async ({ page }) => {
await setupBackups(page); let puts = 0, release!: () => void; const gate = new Promise<void>(r => release = r)
await page.route("**/api/backups/schedule", async r => { if (r.request().method() !== "PUT") return r.fallback(); puts++; await gate; await r.fulfill({ json: { ...schedule, ...r.request().postDataJSON() } }).catch(() => {}) })
await open(page); await save(page).dblclick()
await expect(page.getByRole("spinbutton", { name: "Час запуска" })).toBeDisabled()
await expect(page.getByRole("button", { name: "Сохранить хранилище", exact: true })).toBeDisabled()
release(); await expect(save(page)).toBeEnabled(); expect(puts).toBe(1)
})
test("Бэкапы: отказ расписания не скрывает форму хранилища", async ({ page }) => {
await setupBackups(page); await page.route("**/api/backups/schedule", r => r.fulfill({ status: 503, json: { error: "Schedule unavailable" } }))
await page.goto("/backups"); await page.getByRole("tab", { name: "Настройки", exact: true }).click()
await expect(page.getByRole("button", { name: "Сохранить хранилище", exact: true })).toBeEnabled()
await expect(save(page)).toBeDisabled(); await expect(page.getByRole("spinbutton", { name: "Час запуска" })).toHaveCount(0)
})
test("Бэкапы: проверка S3 не сохраняет черновик незаметно", async ({ page }) => {
await setupBackups(page); let mutations = 0
await page.route("**/api/backups/storage**", r => { if (r.request().method() !== "GET") mutations++; return r.fallback() })
await open(page); await page.getByRole("button", { name: "S3", exact: true }).click()
await page.getByPlaceholder("mikrotik-backups", { exact: true }).fill("draft-bucket")
await page.getByRole("button", { name: "Проверить", exact: true }).click()
await expect(page.getByRole("alert", { name: "Операция резервных копий" })).toContainText("Сначала сохраните хранилище; проверка использует подтверждённые настройки")
expect(mutations).toBe(0)
await expect(page.getByPlaceholder("mikrotik-backups", { exact: true })).toHaveValue("draft-bucket")
})
test("Бэкапы: независимое подтверждение хранилища не отправляет расписание", async ({ page }) => {
await setupBackups(page); let schedulePuts = 0, storagePuts = 0
await page.route("**/api/backups/schedule", r => { if (r.request().method() === "PUT") schedulePuts++; return r.fallback() })
await page.route("**/api/backups/storage", r => { if (r.request().method() !== "PUT") return r.fallback(); storagePuts++; return r.fulfill({ json: { ...storage, ...r.request().postDataJSON() } }) })
await open(page); await page.getByRole("button", { name: "Сохранить хранилище", exact: true }).click()
await expect(page.getByText("Хранилище сохранено", { exact: true })).toBeVisible(); expect(storagePuts).toBe(1); expect(schedulePuts).toBe(0)
})