@btravstack/testing
@btravstack/testing
Classes
TestRuntimePort
Defined in: testing/src/test-runtime.ts:26
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:15
Returns
Inherited from
RuntimePort<Runtime<never, TestRuntimeInfo>>.constructorProperties
Type Aliases
Boot
type Boot = <X, E, UnitX, UnitNeeds>(module, options?, ...gate) => 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 | Default type |
|---|---|
X | - |
E | - |
UnitX | never |
UnitNeeds | never |
Parameters
| Parameter | Type |
|---|---|
module | Module<X, E, Scope | Env> |
options? | Omit<StartOptions<UnitX, UnitNeeds>, "signals"> |
...gate? | StartGate<X, UnitNeeds> |
Returns
RunningApp<E, RuntimeInfoOf<X>>
BootDefaults
type BootDefaults = Omit<StartOptions, "signals" | "unit">;Defined in: testing/src/boot-fixture.ts:23
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:11
Type Parameters
| Type Parameter |
|---|
T |
E |
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
result | readonly | AsyncResult<T, E> | testing/src/test-runtime.ts:13 |
settle | readonly | (result) => void | testing/src/test-runtime.ts:12 |
signal | readonly | AbortSignal | testing/src/test-runtime.ts:14 |
TestRuntime
type TestRuntime = Runtime<never, TestRuntimeInfo> & object;Defined in: testing/src/test-runtime.ts:28
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. Lets a test observe when the kernel told the runtime to stop accepting, which the drain's ordering invariant turns on. | testing/src/test-runtime.ts:48 |
module | Module<TestRuntimePort, never, never> | A module providing this very runtime on TestRuntimePort — the shape a runtime package ships (@btravstack/http's http()), sized for a test: import it next to the module under test and export the port, and start finds it. It provides this object. A wrapper built by spreading ({ ...runtime, start }) copies the module too, so its module still boots the inner, unwrapped runtime — a wrapper provides itself on TestRuntimePort with a module of its own. | testing/src/test-runtime.ts:39 |
serving() | () => Serving<TestRuntimeInfo> | - | testing/src/test-runtime.ts:49 |
started() | () => boolean | - | testing/src/test-runtime.ts:40 |
submit() | <T, E>() => SubmittedUnit<T, E> | - | testing/src/test-runtime.ts:50 |
untilStarted() | () => AsyncResult<void, never> | Resolves the first time the kernel calls start — start itself stays pending until shutdown. | testing/src/test-runtime.ts:42 |
TestRuntimeInfo
type TestRuntimeInfo = object;Defined in: testing/src/test-runtime.ts:23
What testRuntime publishes on Serving.info — its own name, the one thing an in-memory runtime genuinely knows about itself. A real runtime publishes its own shape (an HTTP one, a bound port); this exists so the mechanism is exercised end to end by the suite.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
name | readonly | string | testing/src/test-runtime.ts:23 |
Functions
bootFixture()
function bootFixture(defaults?): (__namedParameters, use) => Promise<void>;Defined in: testing/src/boot-fixture.ts:53
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, { unit: RequestModule });
…
});The defaults are a test's: signals: false always (process-wide signal handlers would fight across a file), probes: false unless a call asks for a port ({ port: 0 } — an ephemeral one cannot collide), preDrainDelayMs: 0 (a test has no Kubernetes endpoint to wait for) 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 (a shutdown that blew up must not pass green), 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 deadlinetapped()
function tapped<X, E, N, P>(
module,
ports, ...
gate): object;Defined in: testing/src/tapped.ts:32
Read services out of a booted application.
start hands the application context to the runtime alone, so a test that wants the very Logger the use cases write to — not a fresh one — has no ctx.get to reach it with. tapped composes one more provider around module, depending on ports, and remembers what it was built with:
const tap = tapped(OrderApi, [Logger]);
const app = boot(tap.module);
await client.orders.place({ id: "o-1", quantity: 2 });
const [logger] = tap.services();
expect(logger.lines()).toContain(…);The returned module exports exactly what module exports — the kernel still finds the runtime. services() is loud before the graph has been built: reading a tap nobody booted is a bug in the test, not a modeled outcome, so it throws rather than answering an undefined a careless assertion could swallow. The gate refuses a port module does not export, at this call site: an application-scope service is the only thing there is to tap.
Type Parameters
| Type Parameter |
|---|
X |
E |
N |
P extends readonly AnyPort[] |
Parameters
| Parameter | Type |
|---|---|
module | Module<X, E, N> |
ports | P |
...gate | [Exclude<InstanceType<P[number]>, X>] extends [never] ? [] : ["NOT EXPORTED", Exclude<InstanceType<P[number]>, X>] |
Returns
object
| Name | Type | Defined in |
|---|---|---|
module | Module<X, E, N> | testing/src/tapped.ts:38 |
services() | () => ServicesOf<P> | testing/src/tapped.ts:38 |
testRuntime()
function testRuntime(name?): TestRuntime;Defined in: testing/src/test-runtime.ts:53
Parameters
| Parameter | Type | Default value |
|---|---|---|
name | string | "test" |