@suaveplan/testing - Universal test utilities (FakeClock, Factory, FixtureManager, MemoryStore, builders, helpers, observability) — runner-agnostic, no DOM dependencies
Summary
Shared test infrastructure for Suaveplan. Provides runner primitives (Vitest or bun-test via conditional exports), structured builders, a deterministic FakeClock, Factory and FixtureManager, an in-memory store, async helpers, and a WSL2-aware createTestConfig() factory. Every other @suaveplan/* package imports from here when writing tests.
This package is Layer 0 in the dependency graph: it has zero @suaveplan/* workspace dependencies. External catalog deps only. Version 0.1.0 .
Documentation tree
- request — (no submodules)
- request — (no submodules)
- response — (no submodules)
- response — (no submodules)
- fake-clock — (no submodules)
- fake-clock — (no submodules)
- config — (no submodules)
- create-test-config — (no submodules)
- clock-constants —
clock-constantscentralises the default configuration values and safety limits forFakeClock, the controllable time… - fixture-constants —
fixture-constantsdefines the safety limits governingFixtureManager, the lifecycle-aware test fixture coordinator… - helpers-constants —
helpers-constantsprovides the default polling configuration forwaitFor, the async condition helper in `@suaveplan… - http-constants —
http-constantsprovides the default HTTP configuration values used byResponseBuilder, the fluent HTTP response fix… - store-constants —
store-constantsdefines the default configuration and hard upper bounds forMemoryStore, the in-process key-value s… - context — (no submodules)
- context — (no submodules)
- codes —
TESTING_ERROR_CODESis the frozen registry of every failure code@suaveplan/testingemits. All codes share the `TES… - testing-error — Every error thrown from
@suaveplan/testingis aTestingErroror a domain-specific subclass (ClockError, `Fixtures… - factory — (no submodules)
- factory — (no submodules)
- fixture-manager — (no submodules)
- fixture-manager-internals — Houses the internal algorithmic helpers for
FixtureManagerso that the public-facing class file stays under the 300-l… - fixture-manager — (no submodules)
- fixture-manager-internals — Houses the internal algorithmic helpers for
- helpers — (no submodules)
- test-helpers — (no submodules)
- observability — (no submodules)
- with-observability — (no submodules)
- runner — (no submodules) - vitest — The
runner/vitestmodule re-exports vite…- bun-test — The
runner/bun-testmodule re-exports bun-test's primitives (describe,it,test,expect,beforeAll, `before… - mocks — The
runner/mocksmodule offers a small set of dependency-injection friendly mock helpers that work identically under… - runner — (no submodules) - vitest — The
runner/vitestmodule re-exports vite… - vitest — The
runner/vitestmodule re-exports vitest'sdescribe,it,test,expect,beforeAll,beforeEach, `afterAll…
- bun-test — The
- memory-store — (no submodules)
- memory-store — (no submodules)
- types — (no submodules)
- http — (no submodules)
- fixture-constants —
fixture-constantsdefines the safety limits governingFixtureManager, the lifecycle-aware test fixture coordinator… - helpers-constants —
helpers-constantsprovides the default polling configuration forwaitFor, the async condition helper in `@suaveplan… - http-constants —
http-constantsprovides the default HTTP configuration values used byResponseBuilder, the fluent HTTP response fix… - store-constants —
store-constantsdefines the default configuration and hard upper bounds forMemoryStore, the in-process key-value s… - context — (no submodules)- context — (no submodules)- codes —
TESTING_ERROR_CODESis the frozen registry of every failure code@suaveplan/testingemits. All codes share the `TES… - testing-error — Every error thrown from
@suaveplan/testingis aTestingErroror a domain-specific subclass (ClockError, `Fixtures… - factory — (no submodules)- factory — (no submodules)- fixture-manager — (no submodules)- fixture-manager-internals — Houses the internal algorithmic helpers for
FixtureManagerso that the public-facing class file stays under the 300-l…- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - bun-test — The
runner/bun-testmodule re-exports bun-test's primitives (describe,it,test,expect,beforeAll, `before… - mocks — The
runner/mocksmodule offers a small set of dependency-injection friendly mock helpers that work identically under… - runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - vitest — The
runner/vitestmodule re-exports vitest'sdescribe,it,test,expect,beforeAll,beforeEach, `afterAll…
- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
- memory-store — (no submodules)- memory-store — (no submodules)- types — (no submodules)- http — (no submodules)- request — (no submodules)- response — (no submodules)- response — (no submodules)- fake-clock — (no submodules)- fake-clock — (no submodules)- config — (no submodules)- create-test-config — (no submodules)- clock-constants —
clock-constantscentralises the default configuration values and safety limits forFakeClock, the controllable time… - fixture-constants —
fixture-constantsdefines the safety limits governingFixtureManager, the lifecycle-aware test fixture coordinator… - helpers-constants —
helpers-constantsprovides the default polling configuration forwaitFor, the async condition helper in `@suaveplan… - http-constants —
http-constantsprovides the default HTTP configuration values used byResponseBuilder, the fluent HTTP response fix… - store-constants —
store-constantsdefines the default configuration and hard upper bounds forMemoryStore, the in-process key-value s… - context — (no submodules)- context — (no submodules)- codes —
TESTING_ERROR_CODESis the frozen registry of every failure code@suaveplan/testingemits. All codes share the `TES… - testing-error — Every error thrown from
@suaveplan/testingis aTestingErroror a domain-specific subclass (ClockError, `Fixtures… - factory — (no submodules)- factory — (no submodules)- fixture-manager — (no submodules)- fixture-manager-internals — Houses the internal algorithmic helpers for
FixtureManagerso that the public-facing class file stays under the 300-l…- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - bun-test — The
runner/bun-testmodule re-exports bun-test's primitives (describe,it,test,expect,beforeAll, `before… - mocks — The
runner/mocksmodule offers a small set of dependency-injection friendly mock helpers that work identically under… - runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - vitest — The
runner/vitestmodule re-exports vitest'sdescribe,it,test,expect,beforeAll,beforeEach, `afterAll…
- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
- memory-store — (no submodules)- memory-store — (no submodules)- types — (no submodules)- http — (no submodules)- request — (no submodules)- response — (no submodules)- response — (no submodules)- fake-clock — (no submodules)- fake-clock — (no submodules)- config — (no submodules)- create-test-config — (no submodules)- clock-constants —
clock-constantscentralises the default configuration values and safety limits forFakeClock, the controllable time… - fixture-constants —
fixture-constantsdefines the safety limits governingFixtureManager, the lifecycle-aware test fixture coordinator… - helpers-constants —
helpers-constantsprovides the default polling configuration forwaitFor, the async condition helper in `@suaveplan… - http-constants —
http-constantsprovides the default HTTP configuration values used byResponseBuilder, the fluent HTTP response fix… - store-constants —
store-constantsdefines the default configuration and hard upper bounds forMemoryStore, the in-process key-value s… - context — (no submodules)- context — (no submodules)- codes —
TESTING_ERROR_CODESis the frozen registry of every failure code@suaveplan/testingemits. All codes share the `TES… - testing-error — Every error thrown from
@suaveplan/testingis aTestingErroror a domain-specific subclass (ClockError, `Fixtures… - factory — (no submodules)- factory — (no submodules)- fixture-manager — (no submodules)- fixture-manager-internals — Houses the internal algorithmic helpers for
FixtureManagerso that the public-facing class file stays under the 300-l…- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - bun-test — The
runner/bun-testmodule re-exports bun-test's primitives (describe,it,test,expect,beforeAll, `before… - mocks — The
runner/mocksmodule offers a small set of dependency-injection friendly mock helpers that work identically under… - runner — (no submodules)- vitest — The
runner/vitestmodule re-exports vite… - vitest — The
runner/vitestmodule re-exports vitest'sdescribe,it,test,expect,beforeAll,beforeEach, `afterAll…
- fixture-manager — (no submodules)- helpers — (no submodules)- test-helpers — (no submodules)- observability — (no submodules)- with-observability — (no submodules)- runner — (no submodules)- vitest — The
- memory-store — (no submodules)- memory-store — (no submodules)- types — (no submodules)- http — (no submodules)- request — (no submodules)- response — (no submodules) - response — (no submodules)- fake-clock — (no submodules) - fake-clock — (no submodules)- config — (no submodules) - create-test-config — (no submodules)- clock-constants —
clock-constantscentralises the default configuration values and safety limits forFakeClock, the controllable time… - fixture-constants —
fixture-constantsdefines the safety limits governingFixtureManager, the lifecycle-aware test fixture coordinator… - helpers-constants —
helpers-constantsprovides the default polling configuration forwaitFor, the async condition helper in `@suaveplan… - http-constants —
http-constantsprovides the default HTTP configuration values used byResponseBuilder, the fluent HTTP response fix… - store-constants —
store-constantsdefines the default configuration and hard upper bounds forMemoryStore, the in-process key-value s… - context — (no submodules) - context — (no submodules)- codes —
TESTING_ERROR_CODESis the frozen registry of every failure code@suaveplan/testingemits. All codes share the `TES… - testing-error — Every error thrown from
@suaveplan/testingis aTestingErroror a domain-specific subclass (ClockError, `Fixtures… - factory — (no submodules) - factory — (no submodules)- fixture-manager — (no submodules) - fixture-manager-internals — Houses the internal algorithmic helpers for
FixtureManagerso that the public-facing class file stays under the 300-l…- fixture-manager — (no submodules)- helpers — (no submodules) - test-helpers — (no submodules)- observability — (no submodules) - with-observability — (no submodules)- runner — (no submodules) - bun-test — The
runner/bun-testmodule re-exports bun-test's primitives (describe,it,test,expect,beforeAll, `before… - mocks — The
runner/mocksmodule offers a small set of dependency-injection friendly mock helpers that work identically under… - runner — (no submodules) - vitest — The
runner/vitestmodule re-exports vitest'sdescribe,it,test,expect,beforeAll,beforeEach, `afterAll…
- fixture-manager — (no submodules)- helpers — (no submodules) - test-helpers — (no submodules)- observability — (no submodules) - with-observability — (no submodules)- runner — (no submodules) - bun-test — The
- memory-store — (no submodules) - memory-store — (no submodules)- types — (no submodules) - http — (no submodules)
Install
bun add -D @suaveplan/testing
Quick usage
Vitest config
// vitest.config.ts
import { createTestConfig } from "@suaveplan/testing/config";
export default await createTestConfig({
environment: "happy-dom",
});
In a test file
import {
describe,
it,
expect,
FakeClock,
defineFactory,
waitFor,
} from "@suaveplan/testing";
describe("user flow", () => {
const userFactory = defineFactory({
defaults: {
id: (i) => `u-${i}`,
name: "Anonymous",
},
traits: {
admin: { name: "Admin" },
},
});
it("builds deterministic users", { timeout: 5000 }, () => {
const user = userFactory.build();
expect(user.id).toBe("u-0");
});
});
Deterministic clock
import { FakeClock } from "@suaveplan/testing";
const clock = new FakeClock({ startTime: 0 });
let fired = false;
clock.setTimeout(() => { fired = true; }, 1000);
clock.advance(1000);
// fired === true
Public surface
Every export is documented in its co-located .md file. High-level map:
- Runner —
describe,it,test,expect,vi,fn,spy,stub,mock,fakeClock,restoreMocks,restoreTimers - Builders —
RequestBuilder,ResponseBuilder, presets (get,post,put,patch,del,ok,created,noContent,badRequest,unauthorized,notFound,serverError) - Clock —
FakeClock(implementsClockinterface) - Factories —
defineFactory,Factory(supports traits, per-factory plugins, deterministic output under seeded RNG) - Fixtures —
FixtureManager(supports lifecycle plugins, AbortSignal) - Storage —
MemoryStore(TTL expiry via injected clock, capacity-bounded) - Helpers —
assertThrows,assertThrowsAsync,createCollector,deferred,measureTime,sleep,uniqueTestId,waitFor,resetTestIdCounter - Constants —
DEFAULT_*,MAX_* - Types —
HttpMethod,HttpHeaders,QueryParams,TestRequest,TestResponse, and the feature-local*State/*Options/*Snapshotinterfaces - Subpaths —
./config(createTestConfig,TestConfigOptions),./utils(barrel re-export for single-import convenience),./polyfills(side-effect module forsetupFiles)
Design
- Every public function accepts an optional
{ clock?, rng?, signal? }options parameter. Zero-config callers are unaffected; callers who need determinism pass their ownClock/Rng/AbortSignal. - Every thrown error is a
TestingErrorsubclass with a stableTESTING.<DOMAIN>.<REASON>code and{ cause?, context? }fields. - Public inputs and outputs have Zod schemas in sibling
*.schemas.tsfiles. Schemas are NOT imported by functional entry points — tree-shake test proves this. - Every public entrypoint is wrapped with OpenTelemetry counters, histograms, and (for iterative ops) spans via
@opentelemetry/api. No-op when no SDK is registered. - fast-check property tests and mitata benchmarks in
src/__tests__/andsrc/__benchmarks__/respectively.
See the design document for the full design and the per-module decisions.
Error codes
Every error thrown from @suaveplan/testing has a stable code. Callers should branch on err.code rather than parsing err.message.
| Code | Thrown by |
|---|---|
TESTING.CLOCK.MAX_TIMERS_EXCEEDED |
FakeClock.setTimeout / setInterval |
TESTING.CLOCK.NEGATIVE_ADVANCE |
FakeClock.advance |
TESTING.FIXTURES.SETUP_FAILED |
FixtureManager.setupAll |
TESTING.FIXTURES.TEARDOWN_FAILED |
FixtureManager.teardownAll |
TESTING.FIXTURES.MAX_FIXTURES_EXCEEDED |
FixtureManager.register |
TESTING.FACTORY.BUILD_FAILED |
Factory.build / buildBatch |
TESTING.FACTORY.TRAIT_NOT_FOUND |
Factory.build with unknown trait |
TESTING.STORE.CAPACITY_EXCEEDED |
MemoryStore.set |
TESTING.STORE.KEY_NOT_FOUND |
MemoryStore.get (strict mode) |
TESTING.HELPERS.WAIT_TIMEOUT |
waitFor |
TESTING.HELPERS.ASSERTION_FAILED |
assertThrows / assertThrowsAsync |
TESTING.BUILDER.INVALID_STATE |
RequestBuilder / ResponseBuilder |
TESTING.CONFIG.UNKNOWN_RUNNER |
createTestConfig |
TESTING.ABORTED |
any iterative helper when its signal fires |
License
MIT