@btravstack/testing / index
index
Classes
TestRuntimePort
Defined in: testing/src/test-runtime.ts:18
The in-memory runtime's port: what TestRuntime.module provides, and what a test composition exports.
Extends
RuntimePort<Runtime<never,TestRuntimeInfo>>
Constructors
Constructor
new TestRuntimePort(): TestRuntimePort;Defined in: di/dist/index.d.mts:16
Returns
Inherited from
RuntimePort<Runtime<never, TestRuntimeInfo>>.constructorProperties
Type Aliases
Boot
type Boot = <X, E, N>(module, options?) => RunningApp<E, RuntimeInfoOf<X>>;Defined in: testing/src/boot-fixture.ts:16
start, as a test hands it out: the same signature and the same phantom gate, minus signals (always off) — every application it starts is stopped when the test ends.
Type Parameters
| Type Parameter |
|---|
X |
E |
N |
Parameters
| Parameter | Type |
|---|---|
module | Module<X, E, N> & StartGate<X, N> |
options? | Omit<StartOptions, "signals"> |
Returns
RunningApp<E, RuntimeInfoOf<X>>
BootDefaults
type BootDefaults = Omit<StartOptions, "signals">;Defined in: testing/src/boot-fixture.ts:22
What every boot in the fixture starts with; a call's own options win.
FakeClock
type FakeClock = Clock & object;Defined in: testing/src/fake-clock.ts:11
Type Declaration
| Name | Type | Description | Defined in |
|---|---|---|---|
advance() | (ms) => AsyncResult<void, never> | Move the clock forward, resolving every sleep whose deadline has passed. The returned AsyncResult settles once the code under test has had a chance to react — so await clock.advance(5_000) leaves the application where the elapsed time takes it, with no extra flushing at the call site. | testing/src/fake-clock.ts:19 |
ServicesOf
type ServicesOf<P> = { readonly [K in keyof P]: ServiceOf<InstanceType<P[K]>> };Defined in: testing/src/tapped.ts:4
The services behind ports, in order — what tapped(...).services() answers once the graph is built.
Type Parameters
| Type Parameter |
|---|
P extends readonly AnyPort[] |
SubmittedUnit
type SubmittedUnit<T, E> = object;Defined in: testing/src/test-runtime.ts:5
Type Parameters
| Type Parameter |
|---|
T |
E |
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
result | readonly | AsyncResult<T, E> | testing/src/test-runtime.ts:7 |
settle | readonly | (result) => void | testing/src/test-runtime.ts:6 |
signal | readonly | AbortSignal | testing/src/test-runtime.ts:8 |
TestRuntime
type TestRuntime<Unit> = Runtime<never, TestRuntimeInfo> & object;Defined in: testing/src/test-runtime.ts:43
Type Declaration
| Name | Type | Description | Defined in |
|---|---|---|---|
accepting() | () => boolean | Whether the runtime would still take new work — false once drain or stop has been called, so a test can observe WHEN the kernel told it to stop accepting. | testing/src/test-runtime.ts:70 |
host() | () => RuntimeHost<never> | The RuntimeHost the kernel last called start with. Throws if the runtime was never started — the same misuse guard as serving(). | testing/src/test-runtime.ts:74 |
module | Module<TestRuntimePort, never, UnitNeedsOf<Unit>> | A module providing this very runtime on TestRuntimePort: import it next to the module under test, export the port, and start finds it. It provides THIS object, so a wrapper built by spreading copies the module too and that module still boots the inner runtime — a wrapper needs a module of its own. Its Needs channel carries a bound unit module's own unmet needs, though nothing here reads them: the module is forked over the application context per unit, so what it needs is exactly what the test composition must supply — and this is what makes start's UNSATISFIED DEPENDENCIES say so at boot instead of leaving a WiringDefect for the first submit(). | testing/src/test-runtime.ts:61 |
serving() | () => Serving<TestRuntimeInfo> | - | testing/src/test-runtime.ts:71 |
started() | () => boolean | - | testing/src/test-runtime.ts:62 |
submit() | <T, E>() => SubmittedUnit<T, E> | - | testing/src/test-runtime.ts:72 |
untilStarted() | () => AsyncResult<void, never> | Resolves the first time the kernel calls start — start itself stays pending until shutdown. | testing/src/test-runtime.ts:64 |
Type Parameters
| Type Parameter | Default type |
|---|---|
Unit extends AnyUnitModule | undefined | undefined |
TestRuntimeInfo
type TestRuntimeInfo = object;Defined in: testing/src/test-runtime.ts:15
What testRuntime publishes on Serving.info — its own name, the one thing an in-memory runtime genuinely knows about itself.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
name | readonly | string | testing/src/test-runtime.ts:15 |
TestRuntimeOptions
type TestRuntimeOptions<Unit> = object;Defined in: testing/src/test-runtime.ts:38
Type Parameters
| Type Parameter | Default type |
|---|---|
Unit extends AnyUnitModule | undefined | undefined |
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
unit? | readonly | Unit | A module every submitted unit forks, with no seed, before its work runs. | testing/src/test-runtime.ts:40 |
Functions
bootFixture()
function bootFixture(defaults?): (__namedParameters, use) => Promise<void>;Defined in: testing/src/boot-fixture.ts:50
A test.extend fixture that hands the test a Boot and stops every application it started once the test is over — on every exit path, a failing assertion included, which is what test.extend's teardown is for.
export const it = test.extend<{ boot: Boot }>({
boot: bootFixture({ env: { PORT: "0", HOST: "127.0.0.1" } }),
});
it("answers", async ({ boot }) => {
const app = boot(OrderApi);
…
});The defaults are a test's: signals: false always (process-wide handlers would fight across a file), probes: false, preDrainDelayMs: 0, a stopTimeoutMs far out of reach and a silent onEvent — each overridable by defaults and again per call.
Teardown is stop(), then exited is examined: a Defect fails the test even when the test never looked at exited, while a modeled Err passes through, since a startup failure is an outcome a test may be asserting.
Parameters
| Parameter | Type |
|---|---|
defaults | BootDefaults |
Returns
(__namedParameters, use) => Promise<void>
createFakeClock()
function createFakeClock(start?): FakeClock;Defined in: testing/src/fake-clock.ts:44
A Clock whose time only moves when a test says so.
Pass it as StartOptions.clock to drive the drain's pre-drain delay and deadline explicitly, instead of waiting out the real 5s/20s defaults.
Parameters
| Parameter | Type | Default value |
|---|---|---|
start | number | 0 |
Returns
Example
const clock = createFakeClock();
const app = start(AppModule, { runtime, clock });
app.requestDrain();
await clock.advance(5_000); // the pre-drain delay
await clock.advance(20_000); // the drain deadlineoverridden()
function overridden<X, E, N, O>(module, overrides): Module<X, E | ErrorsOf<O>, N>;Defined in: testing/src/overridden.ts:30
The real composition root, with named providers substituted — the testing half of "swapping an adapter is composing a different module", for the seam composition cannot reach: nothing can be layered over a graph that already provides a port, so the alternative was a parallel root that drifted silently.
Each override is an ordinary Provider(Port)(...), so the service type is checked against the port at that call. At run time an override REPLACES the base provider — the base is never constructed — and an override for a port the tree no longer provides is a WiringDefect ("nothing to override"), which is what turns fixture drift into a loud failure.
It replaces ONE provider, never a subsystem: the replaced provider's siblings still construct, so swapping a whole adapter stack remains a different module composed in its place.
An override's own deps deliberately do NOT widen the returned Needs: they resolve from the graph's INTERNALS, and typing them into N would force a root to re-export internals to be overridable. They are checked at build instead, by plan's missing-provider defect.
Type Parameters
| Type Parameter |
|---|
X |
E |
N |
O extends readonly AnyProviderFor[] |
Parameters
| Parameter | Type |
|---|---|
module | Module<X, E, N> |
overrides | O |
Returns
Module<X, E | ErrorsOf<O>, N>
tapped()
function tapped<X, E, N, P>(module, ports): object;Defined in: testing/src/tapped.ts:42
Type Parameters
| Type Parameter |
|---|
X |
E |
N |
P extends readonly AnyPort[] |
Parameters
| Parameter | Type |
|---|---|
module | Module<X, E, N> |
ports | P & TapGate<P, X> |
Returns
object
| Name | Type | Defined in |
|---|---|---|
module | Module<X, E, N> | testing/src/tapped.ts:45 |
services() | () => ServicesOf<P> | testing/src/tapped.ts:45 |
testRuntime()
function testRuntime<Unit>(name?, options?): TestRuntime<Unit>;Defined in: testing/src/test-runtime.ts:77
Type Parameters
| Type Parameter | Default type |
|---|---|
Unit extends AnyUnitModule | undefined | undefined |
Parameters
| Parameter | Type | Default value |
|---|---|---|
name | string | "test" |
options | TestRuntimeOptions<Unit> | {} |
Returns
TestRuntime<Unit>