Skip to main content
A plugin is a thin, framework-native layer over the SDK. It connects to this worker’s instance once, reset()s the world between tests, and hands you a Sandbox.

Jest — @prod-break/jest

Jest has no fixture injection, so the plugin is helper functions over beforeEach/afterEach:
import { useSandbox } from "@prod-break/jest";

const sandbox = useSandbox();   // installs the lifecycle on this describe block

test("…", async () => {
  const sb = sandbox();
  await sb.faults.arm("charges", "create", { status: 402, code: "card_declined" });
  const deck = sb.client();
  // …
});

Vitest — @prod-break/vitest

Vitest has real fixture injection (test.extend), so you get an injected sandbox:
import { test } from "@prod-break/vitest";

test("…", async ({ sandbox }) => {
  await sandbox.faults.arm("charges", "create", { status: 402, code: "card_declined" });
  const deck = sandbox.client();
  // …
});

pytest — prod-break-pytest

A real pytest fixture, auto-registered via the plugin entry point:
def test_declined(stripe_sandbox):
    stripe_sandbox.faults.arm("charges", "create", status=402, code="card_declined")
    stripe = stripe_sandbox.client()
    # …  world resets at teardown

Lifecycle, in all three

1

Session: connect once

The plugin connects to this worker’s instance (from PRODBREAK_URL / the worker CSVs) a single time — you pay connection once.
2

Function: reset() each test

Before (and after) each test the world is rewound to t0, keeping tests independent.
3

Sinks are managed for you

Webhook sinks the test stands up are torn down on reset — you don’t manage receiver servers.
Ship order. JS/TS (Jest, then Vitest) lands first — that’s where most integration suites live. pytest is the next plugin on the roadmap; its surface mirrors the TS SDK one-for-one (snake_case), so everything you learn here carries over.