Testing
Test in three steps, from no account to real gateways in test mode.
1. The test gateway, in your test suite#
No account, no network, no money. Your handler runs exactly as it will in production.
import { test } from "node:test";
import assert from "node:assert/strict";
import { CallCash } from "callcash";
test("a paid order is fulfilled once", async () => {
const cash = new CallCash();
const fulfilled: string[] = [];
const onCash = async (e) => { if (e.type === "payment.paid") fulfilled.push(e.reference); };
const p = await cash.payments.create({ amount: 250, reference: "order_1" });
await cash.test.pay(p.id, onCash);
assert.deepEqual(fulfilled, ["order_1"]);
});Rehearse what goes wrong:
| Call | Your handler gets |
|---|---|
cash.test.pay(id, onCash) | payment.paid |
cash.test.fail(id, onCash, "insufficient funds") | payment.failed with that reason |
cash.test.pay(id, onCash, { amount: 2.5 }) | payment.mismatch, and the payment stays unpaid |
cash.test.pay(id, onCash) twice on a paid payment | payment.mismatch: paid a second time |
| A handler that throws | The event stays owed; cash.events.deliver(onCash) brings it back with redelivery: true |
cash.test.pay and cash.test.fail only work on payments made on the test gateway.
2. Yoco test keys#
Configure Yoco with an sk_test_ key. Payments open a real Yoco checkout and Yoco's test cards work on it. Events arrive at your webhook route with mode: "test". Refunds are not possible on test payments.
Yoco must be able to reach your webhook route, so run your app on a public address (a preview deployment, or a tunnel to your machine).
3. Netcash test mode#
Tick "Make test mode active" in the Netcash dashboard and set test: true. Keep test amounts under R100: a new Pay Now service hides the card option above that limit.
Netcash calls the Notify URL you typed into NetConnector, so that address must be public too.
Testing your own store#
If you write your own Store, test that two update calls at the same moment cannot both win. That atomic step is what stops a payment counting twice.