Better Payment

Chaos Testing

Inject declines, lost responses and delays to test how your application handles them.

Not released yet

Payment code usually breaks on the paths nobody tests: a provider that doesn't answer, a response lost after the bank charged the card, a decline in the middle of a flow. Provider sandboxes rarely let you trigger these on demand. The chaos plugin injects them into your own setup, so you can check your error handling, retries and handling of NETWORK_ERROR results (error codes).

Setup

import { betterPayment, iyzico } from 'better-payment';
import { chaos } from 'better-payment/plugins';

const payment = betterPayment({
  mode: 'sandbox',
  providers: { iyzico: iyzico({ /* ... */ }) },
  plugins: [
    chaos({
      enabled: process.env.CHAOS === '1',
      seed: 42,
      rules: [
        { operation: 'createPayment', probability: 0.2, fail: 'NETWORK_ERROR' },
        { operation: 'refund', delay: '3s' },
        { provider: 'iyzico', probability: 0.1, fail: 'PROVIDER_ERROR' },
      ],
    }),
  ],
});

A failure is returned as a normal result and the provider is not called. NETWORK_ERROR returns a pending result, the way a lost response does; every other code returns a failure. After hooks and payment events run for injected results too, so localizedErrors translates them and your payment.failed listeners see them.

Options

OptionDefaultDescription
rules—The rules, checked in order. The first matching rule that fires is applied.
enabledtrueTurn the plugin on or off, for example from an environment variable
seed—Makes runs reproducible: the same seed fires the same rules on the same calls
allowProductionfalseAllow the plugin in production mode

Rules

FieldDefaultDescription
operationallOne operation or a list: 'createPayment', 'refund', 'initThreeDSPayment'...
providerallOne provider id or a list
probability1Chance that the rule fires on a matching call, from 0 to 1
fail—Return a failure with this error code
delay—Wait before the call: milliseconds, or '500ms', '3s', '1m'
message—The errorMessage of the injected failure

A rule with only delay slows the call down and then runs it on the provider. A rule with delay and fail waits, then fails.

Turn it on and off in tests

payment.chaos.disable(); // operations run normally
payment.chaos.enable();
payment.chaos.enabled;   // true

Production

The plugin throws a ConfigurationError in production mode, on the first operation or on payment.chaos.enable(), so a test setup can't break real payments by accident. A disabled plugin (enabled: false) is allowed. Set allowProduction: true only if you know you want failures in production, for example in a game day exercise.

On this page