import { expect, test, type Page } from "@playwright/test"; async function fixture(page: Page, options: { language?: string; scope?: string; readonly?: boolean; ceiling?: number; reject?: number; hold?: boolean } = {}) { let value: number | null = null; let revision = 1; let reject = options.reject; let release: (() => void) | undefined; let rejectRead = false; const writes: any[] = []; const errors: string[] = []; const inherited = options.ceiling ?? 25; const maximum = options.ceiling ?? 500; page.on("pageerror", (cause) => errors.push(cause.message)); const state = () => ({ scope: options.scope ?? "system", synchronous_send_max_recipients: value, revision: String(revision).padStart(64, "0"), max_configurable_recipients: maximum, effective_max_recipients: value ?? inherited, inherited_max_recipients: inherited, absolute_max_recipients: 500, deployment_ceiling_explicit: Boolean(options.ceiling), deployment_max_recipients: maximum }); await page.route((url) => url.pathname.startsWith("/api/"), async (route) => { if (!route.request().url().includes("/campaigns/settings/delivery-policy/")) return route.fulfill({ status: 404, json: { detail: "Not found" } }); if (route.request().method() === "GET") return route.fulfill(rejectRead ? { status: 503, json: { detail: "Fixture reload unavailable" } } : { json: state() }); expect(route.request().method()).toBe("PUT"); const body = route.request().postDataJSON(); writes.push(body); if (options.hold) await new Promise((resolve) => { release = resolve; }); if (reject) { const status = reject; reject = undefined; return route.fulfill({ status, json: { detail: "Fixture policy save rejected; draft was not saved" } }); } value = body.synchronous_send_max_recipients; revision += 1; return route.fulfill({ json: state() }); }); await page.goto(`/?campaign-delivery-policy&language=${options.language ?? "en"}&scope=${options.scope ?? "system"}${options.readonly ? "&readonly" : ""}`); await expect(page.getByRole("spinbutton")).toHaveValue(String(inherited)); return { writes, errors, release: () => release?.(), failRead: () => { rejectRead = true; } }; } for (const language of ["en", "de"]) { test(`administrator deliberately raises implicit 25 to 200 and reloads saved policy in ${language}`, async ({ page }) => { const f = await fixture(page, { language }); const save = page.getByRole("button", { name: language === "de" ? "Speichern" : "Save", exact: true }); await expect(save).toBeDisabled(); await page.getByRole("checkbox").press("Space"); await page.getByRole("spinbutton").fill("200"); await save.click(); await expect(save).toBeDisabled(); expect(f.writes).toEqual([{ synchronous_send_max_recipients: 200, expected_revision: "1".padStart(64, "0") }]); await page.getByRole("button", { name: language === "de" ? "Gespeicherte Versandrichtlinie neu laden" : "Reload saved delivery policy", exact: true }).click(); await expect(page.getByRole("spinbutton")).toHaveValue("200"); await expect(page.getByRole("checkbox")).not.toBeChecked(); expect(f.errors).toEqual([]); }); } for (const status of [422, 409]) { test(`policy save ${status} retains draft for an explicit retry`, async ({ page }) => { const f = await fixture(page, { reject: status }); await page.getByRole("checkbox").press("Space"); await page.getByRole("spinbutton").fill("200"); await page.getByRole("button", { name: "Save", exact: true }).click(); await expect(page.getByRole("alert").filter({ hasText: "Fixture policy save rejected" })).toBeVisible(); await expect(page.getByRole("spinbutton")).toHaveValue("200"); await page.getByRole("button", { name: "Save", exact: true }).click(); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); expect(f.writes).toHaveLength(2); expect(f.writes[1].synchronous_send_max_recipients).toBe(200); }); } test("explicit ceiling prevents invalid save and clearing override submits inheritance", async ({ page }) => { const f = await fixture(page, { scope: "tenant", ceiling: 40 }); await page.getByRole("checkbox").press("Space"); await page.getByRole("spinbutton").fill("41"); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); expect(f.writes).toHaveLength(0); await page.getByRole("spinbutton").fill("0"); await page.getByRole("button", { name: "Save", exact: true }).click(); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); await page.getByRole("checkbox").press("Space"); await page.getByRole("button", { name: "Save", exact: true }).click(); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); expect(f.writes.map((body) => body.synchronous_send_max_recipients)).toEqual([0, null]); }); test("read-only policy cannot be edited or saved", async ({ page }) => { const f = await fixture(page, { readonly: true }); await expect(page.getByRole("checkbox")).toBeDisabled(); await expect(page.getByRole("spinbutton")).toBeDisabled(); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); expect(f.writes).toHaveLength(0); }); test("pending policy save disables edits and reload; failed refresh preserves acknowledged value", async ({ page }) => { const f = await fixture(page, { hold: true }); await page.getByRole("checkbox").press("Space"); await page.getByRole("spinbutton").fill("200"); await page.getByRole("button", { name: "Save", exact: true }).click(); await expect.poll(() => f.writes.length).toBe(1); await expect(page.getByRole("spinbutton")).toBeDisabled(); await expect(page.getByRole("button", { name: "Reload saved delivery policy", exact: true })).toBeDisabled(); f.release(); await expect(page.getByRole("spinbutton")).toBeEnabled(); f.failRead(); await page.getByRole("button", { name: "Reload saved delivery policy", exact: true }).click(); await expect(page.getByRole("alert").filter({ hasText: "Fixture reload unavailable" })).toBeVisible(); await expect(page.getByRole("spinbutton")).toHaveValue("200"); await expect(page.getByRole("button", { name: "Save", exact: true })).toBeDisabled(); expect(f.writes).toHaveLength(1); });