@roostjs/testing
What the testing package provides, how it connects to Roost's broader testing philosophy, and the specific patterns it enables.
The Testing Package's Scope
@roostjs/testing provides the shared testing infrastructure that other packages
build on. Its two primary exports are TestClient — for making HTTP requests
against a Roost application without a running server — and the test setup utilities that
configure the application environment for tests.
The package intentionally does not try to be a testing framework. Roost applications use
Bun's built-in test runner, and @roostjs/testing extends it rather than
replacing it. Tests use describe, it, and expect
from Bun — the testing package adds Roost-specific assertions on top of those primitives.
TestClient: The Primary Testing Interface
The TestClient is a request builder that calls app.handle()
directly. It supports the common HTTP methods, accepts JSON bodies, allows setting
arbitrary headers, and provides an actingAs(user) method for authenticating
test requests without needing a real session. The response is a TestResponse
with fluent assertion methods: assertStatus(200), assertOk(),
assertJson({ key: value }), assertHeader(name, value).
The TestClient's design reflects the testing philosophy: tests should read like descriptions
of user behavior, not descriptions of implementation details. await client.post('/orders', payload)
reads like what the user is doing. The assertions that follow describe what the application
should have done in response.
Test Application Setup
Tests need an application instance to give to the TestClient. The recommended pattern is to create a test-specific application factory that registers real service providers but replaces infrastructure bindings with fakes — the D1 database is a test D1 (via Wrangler), AI providers are faked, billing is faked, queues are faked. This produces an application that exercises all the real code paths but does not make external calls or require production credentials.
The testing package provides setup utilities that assist with this configuration,
but the application factory is application code — not something the testing package generates
or owns. This keeps the test setup transparent: a new team member can read the test
bootstrap file and understand exactly what is being faked and why.
Connection to the Broader Testing Philosophy
The testing package is the practical expression of the fake-over-mock and integration-first philosophy described in the cross-cutting testing concepts. If you want to understand why the package is designed this way — why fakes, why no mock library, why integration tests are preferred — the testing philosophy page covers that reasoning. This package page focuses on the specific tools the package provides.