Skip to content

bun-test-utils

Playwright-style typed fixtures for `bun test`, composed with `test.extend()` — with scopes and LIFO teardown, plus first-class DOM, browser, HTTP, cassette, snapshot, property-based, and BDD testing.

Stable

bun-test-utils extends bun test with a typed fixture model: a fixture is a value built by a setup function, tests ask for the fixtures they need by destructuring, and the engine builds dependencies first and tears everything down in reverse order, even when a test fails.

It is not a replacement for bun:test — it ships no runner of its own, and your tests stay bun test files. It is not a browser-only framework either: fixtures, standard fixtures, HTTP mocking, and cassettes work in any Bun project, and the DOM, browser, property-based, and BDD layers install with their own optional peers when you reach for them.

Choose your path

The core is always available

🧩 Typed fixtures

Compose fixtures with test.extend(); each type flows into the test that requests it. The fixture model

⏱️ Scopes and LIFO teardown

Declare a fixture at session, file, or test scope. Setup and teardown live in one function. Scopes and teardown

📦 Standard fixtures

tmpdir, env, stdio, clock, seed, and networkGuard give every test isolated, deterministic state. Built-in fixture API

🌐 HTTP mocking and test servers

Route fetch with MSW-style handlers, or serve real requests from an ephemeral testServer. HTTP and servers

Add-on capabilities

Each one installs its own optional peer and is requested like any other fixture; nothing is pulled in until a test asks for it.

CapabilityUse it forMaturityRequires
DOM testingComponent and markup assertions in-process, without a browserStablehappy-dom
Browser testingReal layout, focus, and input in headless ChromiumExperimentalplaywright + Chromium
Snapshot testingReviewed baselines for values, files, and callback resultsStable—
Property-based testingGenerated inputs that shrink to a counterexampleStablefast-check
BDD scenariosFluent given / when / then chains on the same fixturesExperimental@aboviq/bun-test-cucumber
HTTP cassettesRecorded request/response pairs that replay deterministicallyStable—

The capability index has the full decision table, the parameterized-test alternative to property tests, and links into every guide.

Quick start

Install the package and wire its preload once per project:

Runnable — complete sample — the docs check runs it against the built package

Terminal window
bun add -d @archont561/bun-test-utils
bunx test-utils init --yes

init adds the package’s preload to bunfig.toml; it installs run-wide teardown hooks and loads no fixtures of its own. Built-in fixtures are then available to any test that requests them:

Runnable — complete sample — the docs check runs it against the built package

greeting.test.ts
import { expect, test } from "@archont561/bun-test-utils";
test("greets through a built-in fixture", async ({ tmpdir }) => {
tmpdir.write("greeting.txt", "hello");
expect(tmpdir.read("greeting.txt")).toBe("hello");
});

Runnable — complete sample — the docs check runs it against the built package

Terminal window
bun test

Expected output:

1 pass
0 fail
1 expect() calls

Install and first passing test shows the same flow with a fixture of your own, complete tsconfig output, and the failure modes.

These docs describe bun-test-utils v0.1.0 (release notes) and the capability tiers above are the same ones in Stability, compatibility, and support: stable surfaces follow semantic versioning, experimental ones may change in a minor release.

Documentation wrong or missing something? Report a docs issue or read Contributing and docs feedback.

Docs for bun-test-utils v0.1.0 Release notes Report a docs issue