Test payment failures
Simulate provider outages, timeouts, and rejections with the test rail before real money is involved.
Pre-release · planned API
import { createTollstile, memoryLedger, testRail } from "tollstile";
import { fakeClock } from "tollstile/testing";
const rail = testRail();
const clock = fakeClock();
const toll = createTollstile({ rails: [rail], ledger: memoryLedger({ clock }), clock });
rail.simulate({ settle: "timeout-after-effect" }); // money moved, but the answer was lost
// …call a priced route: the charge ends `unknown`
rail.simulate({});
clock.advance(60_000);
await toll.reconcile({ olderThanMs: 1_000 });
// the charge is `settled`, and rail.effects.settlements is still 1| Simulation | Effect |
|---|---|
verify: "unavailable" | 503, handler not run |
settle: "reject" | Charge failed, SETTLEMENT_REJECTED event |
settle: "timeout-before-effect" | unknown; reconciliation retries or releases |
settle: "timeout-after-effect" | unknown; reconciliation records the settlement once |
refund: "timeout-after-effect" | unknown; reconciliation records the refund once |
lookup: "unavailable" | Reconciliation leaves the charge pending |
rail.effects counts settlements, refunds, and releases so tests can assert nothing happened twice. tollstile/testing also exports httpContext() and mcpContext() to drive gates without a framework.