/** * The test's starting state, as opposed to the app: a balance that is too low to run a test that spends, an account that cannot do what the test needs. * A failure of this kind has the reason "pre-state" (docs/design/protocol.md), so a report and a person can tell it from the app being wrong: * nobody should file a bug against the app because a test account ran out of testnet money. */ export type PreStateVerdict = { ok: true } | { ok: false; reason: "pre-state" | "internal"; message: string; expected?: string; found?: string }; const escape = (s: string): string => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const num = (n: number): string => String(Math.round(n * 1e9) / 1e9); /** Whether the balance the page shows (a number after the label, such as "Balance: 12.5 MALLBUCKS") is at least what the test needs. */ export function judgeBalance(input: { account: string; needed: number; label: string; pageText: string }): PreStateVerdict { if (!Number.isFinite(input.needed) || input.needed < 0) return { ok: false, reason: "internal", message: "balance-at-least needs an amount of zero or more" }; if (input.label.trim() === "") return { ok: false, reason: "internal", message: "balance-at-least needs the label the page shows next to the balance, for example Balance" }; const text = input.pageText.replace(/\s+/g, " "); const found = new RegExp(`(?= input.needed) return { ok: true }; const shown = found[1]!.length > 30 ? `${found[1]!.slice(0, 30)}...` : found[1]!; return { ok: false, reason: "pre-state", message: `${input.account.slice(0, 80)} has ${shown} but this test needs ${num(input.needed)} (short by ${num(input.needed - have)}). This is about the test's starting state, not a failure of the app: refill the account (see docs/runbook-sessions.md) and run again.`, expected: `>= ${num(input.needed)}`, found: shown, }; }