import { test, expect } from "@playwright/test" import { certificateRoutes, issueJob, openIssue } from "./fixtures/certificate-issue" test.beforeEach(async ({ page }) => certificateRoutes(page)) test("Выпуск: успех и отказ последующего каталога разделены", async ({ page }) => { let request: Record = {}; let writes = 0 await page.route("**/api/certificates/issue", r => { writes++; request = r.request().postDataJSON(); return r.fulfill({ json: { jobId: request.requestId } }) }) await page.route("**/api/certificates/issue/*", r => r.fulfill({ json: issueJob(request) })) await page.route("**/api/certificates/state", r => writes ? r.fulfill({ status: 503, json: { error: "Повторное чтение отказало" } }) : r.fallback()) const dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("button", { name: "Задача завершена", exact: true })).toBeDisabled() await expect(page.getByText("API подтвердил завершение задачи выпуска", { exact: true })).toBeVisible() await dialog.getByRole("button", { name: "Закрыть", exact: true }).last().click() await expect(page.getByRole("alert", { name: "Каталог сертификатов", exact: true })).toContainText("Последние данные сохранены") expect(writes).toBe(1) }) test("Выпуск: GET ошибка и reload продолжают ту же задачу без POST", async ({ page }) => { let request: Record = {}, fail = true, writes = 0 await page.route("**/api/certificates/issue", r => { writes++; request = r.request().postDataJSON(); return r.fulfill({ json: { jobId: request.requestId } }) }) await page.route("**/api/certificates/issue/*", r => r.fulfill(fail ? { status: 503, json: { error: "Опрос отказал" } } : { json: issueJob(request) })) let dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("alert", { name: "Выпуск сертификата", exact: true })).toContainText("Продолжите проверку той же задачи") await page.reload(); await page.getByRole("button", { name: "Задача выпуска", exact: true }).click() dialog = page.getByRole("dialog", { name: "Выпуск сертификата", exact: true }); fail = false await dialog.getByRole("button", { name: "Продолжить проверку", exact: true }).click() await expect(dialog.getByRole("button", { name: "Задача завершена", exact: true })).toBeDisabled(); expect(writes).toBe(1) }) for (const accepted of [false, true]) test("Выпуск: потерянное подтверждение POST/accepted=" + accepted, async ({ page }) => { const requests: Record[] = []; let exists = false await page.route("**/api/certificates/issue", r => { const request = r.request().postDataJSON(); requests.push(request); exists = accepted || requests.length > 1; return r.fulfill(requests.length === 1 ? { status: 503, json: { error: "Ответ потерян" } } : { json: { jobId: request.requestId } }) }) await page.route("**/api/certificates/issue/*", r => r.fulfill(exists ? { json: issueJob(requests[0]) } : { status: 404, json: { error: "Задача не найдена" } })) const dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("alert", { name: "Выпуск сертификата", exact: true })).toContainText("Ответ потерян") await dialog.getByRole("button", { name: "Продолжить проверку", exact: true }).click() await expect(dialog.getByRole("button", { name: "Задача завершена", exact: true })).toBeDisabled() expect(requests.length).toBe(accepted ? 1 : 2); for (const request of requests) expect(request.requestId).toBe(requests[0].requestId) }) test("Выпуск: реальный failed и новая форма не повторяют POST автоматически", async ({ page }) => { let request: Record = {}, writes = 0 await page.route("**/api/certificates/issue", r => { writes++; request = r.request().postDataJSON(); return r.fulfill({ json: { jobId: request.requestId } }) }) await page.route("**/api/certificates/issue/*", r => r.fulfill({ json: issueJob(request, { status: "failed", step: "failed", error: "Импорт отказал" }) })) const dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("alert", { name: "Выпуск сертификата", exact: true })).toContainText("Импорт отказал") await expect(dialog.getByRole("button", { name: "Задача завершена", exact: true })).toBeDisabled() await dialog.getByRole("button", { name: "Новый выпуск", exact: true }).click() await expect(dialog.getByRole("textbox", { name: "Имя сертификата", exact: true })).toHaveValue(""); expect(writes).toBe(1) }) test("Выпуск: чужая цель в done не подтверждает успех", async ({ page }) => { let request: Record = {} await page.route("**/api/certificates/issue", r => { request = r.request().postDataJSON(); return r.fulfill({ json: { jobId: request.requestId } }) }) await page.route("**/api/certificates/issue/*", r => r.fulfill({ json: issueJob(request, { serverId: "2" }) })) const dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("alert", { name: "Выпуск сертификата", exact: true })).toContainText("не соответствует") await expect(page.getByText("API подтвердил завершение задачи выпуска", { exact: true })).toHaveCount(0) await expect(dialog.getByRole("button", { name: "Продолжить проверку", exact: true })).toBeEnabled() }) test("Выпуск: отказ записи checkpoint не отправляет запрос", async ({ page }) => { await page.addInitScript(() => { sessionStorage.setItem = () => { throw new Error("storage denied") } }) let writes = 0; await page.route("**/api/certificates/issue", r => { writes++; return r.fulfill({ json: {} }) }) const dialog = await openIssue(page); await dialog.getByRole("button", { name: "Выпустить", exact: true }).click() await expect(dialog.getByRole("alert", { name: "Выпуск сертификата", exact: true })).toContainText("Не удалось сохранить задачу") expect(writes).toBe(0) })