fix(backups): показать отсутствие файлов и защитить удаление записей
This commit is contained in:
1 parent
e452e528e1
commit
6617b776bb
26 files changed
+420
-36
No files matched your search
@@ -0,0 +1,41 @@
|
||||
import { test, expect } from "@playwright/test"
|
||||
import { backup, setupBackups } from "./fixtures/backups"
|
||||
|
||||
for (const width of [1440, 390]) test(`Бэкапы: отсутствующий локальный файл ${width}`, async ({ page }) => {
|
||||
await page.setViewportSize({ width, height: 900 }); await setupBackups(page)
|
||||
await page.route("**/api/backups", r => r.fulfill({ json: [{ ...backup, localFileStatus: "missing" }] }))
|
||||
let operations = 0; page.on("request", r => { if (/\/backups\/[^/]+\/(restore|download)$/.test(new URL(r.url()).pathname)) operations++ })
|
||||
await page.goto("/backups")
|
||||
await expect(page.getByText("Нет файла", { exact: true })).toBeVisible()
|
||||
await expect(page.getByText("Локальный файл отсутствует.", { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole("button", { name: "Скачать " + backup.filename, exact: true })).toBeDisabled()
|
||||
await expect(page.getByRole("button", { name: "Восстановить " + backup.filename, exact: true })).toBeDisabled()
|
||||
await page.getByRole("button", { name: "Удалить " + backup.filename, exact: true }).click()
|
||||
const dialog = page.getByRole("alertdialog"); await expect(dialog).toContainText("Удалить запись о бэкапе?"); await expect(dialog).toContainText("Будет удалена только запись из истории.")
|
||||
await dialog.getByRole("button", { name: "Отмена", exact: true }).click()
|
||||
expect(operations).toBe(0); expect(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1)).toBe(false)
|
||||
})
|
||||
|
||||
test("Бэкапы: потеря local copy сохраняет скачивание из S3", async ({ page }) => {
|
||||
await setupBackups(page); await page.route("**/api/backups", r => r.fulfill({ json: [{ ...backup, storage: "both", localFileStatus: "missing" }] }))
|
||||
await page.route("**/api/backups/backup-1/download", r => r.fulfill({ contentType: "text/plain; charset=utf-8", body: "# S3 fixture\n" }))
|
||||
await page.goto("/backups"); await expect(page.getByText("Локальная копия отсутствует. Файл будет запрошен из S3.", { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole("button", { name: "Восстановить " + backup.filename, exact: true })).toBeEnabled()
|
||||
const download = page.waitForEvent("download"); await page.getByRole("button", { name: "Скачать " + backup.filename, exact: true }).click(); expect((await download).suggestedFilename()).toBe(backup.filename)
|
||||
})
|
||||
|
||||
for (const status of ["unknown", undefined]) test(`Бэкапы: неизвестный или старый receipt ${status}`, async ({ page }) => {
|
||||
await setupBackups(page); await page.route("**/api/backups", r => r.fulfill({ json: [{ ...backup, ...(status ? { localFileStatus: status } : {}) }] }))
|
||||
await page.goto("/backups"); await expect(page.getByText(backup.filename, { exact: true })).toBeVisible()
|
||||
await expect(page.getByText("Нет файла", { exact: true })).toHaveCount(0)
|
||||
await expect(page.getByRole("button", { name: "Скачать " + backup.filename, exact: true })).toBeEnabled()
|
||||
if (status) await expect(page.getByText("Не удалось проверить локальный файл.", { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
test("Бэкапы: исчезновение после первого чтения подтверждается новым receipt", async ({ page }) => {
|
||||
await setupBackups(page); let missing = false
|
||||
await page.route("**/api/backups", r => r.fulfill({ json: [{ ...backup, localFileStatus: missing ? "missing" : "available" }] }))
|
||||
await page.goto("/backups"); const restore = page.getByRole("button", { name: "Восстановить " + backup.filename, exact: true }); await expect(restore).toBeEnabled()
|
||||
missing = true; await page.getByRole("button", { name: "Обновить", exact: true }).click(); await expect(restore).toBeDisabled()
|
||||
await expect(page.getByText("Нет файла", { exact: true })).toBeVisible()
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
import { test, expect } from "@playwright/test"
|
||||
import { backup, setupBackups } from "./fixtures/backups"
|
||||
|
||||
for (const confirmed of [true, false]) test(`Бэкапы: удаление отсутствующего файла требует record-only receipt ${confirmed}`, async ({ page }) => {
|
||||
await setupBackups(page); await page.route("**/api/backups", r => r.fulfill({ json: [{ ...backup, localFileStatus: "missing" }] }))
|
||||
let calls = 0
|
||||
await page.route("**/api/backups/backup-1?recordOnly=true", r => { calls++; return r.fulfill({ status: 204, headers: confirmed ? { "X-Backup-Delete-Mode": "record-only" } : {} }) })
|
||||
await page.goto("/backups"); await page.getByRole("button", { name: "Удалить " + backup.filename, exact: true }).click()
|
||||
const dialog = page.getByRole("alertdialog"); await dialog.getByRole("button", { name: "Удалить", exact: true }).click()
|
||||
if (confirmed) await expect(dialog).toBeHidden()
|
||||
else { await expect(dialog).toBeVisible(); await expect(dialog).toContainText("Не подтверждено удаление только записи истории") }
|
||||
expect(calls).toBe(1)
|
||||
})
|
||||
Reference in new issue
Block a user