title: Test utilities with @jeeboard/testkit description: Covers deterministic test helpers and the spatial benchmark from the @jeeboard/testkit package. #
@jeeboard/testkit #
The @jeeboard/testkit package gives you deterministic helpers for tests that use jeeboard. Deterministic means that each run gives the same result. The package also contains a benchmark that measures spatial index query speed.
Use this package in your test code. Do not use it in production code.
Key concepts #
- Manual scheduler: a scheduler that queues tasks and runs them only when you flush a phase.
- Phase: a named stage of work. The phases are
presentation,compilation,raster, andbackground. - Manual clock: a clock that returns a fixed time until you advance it by hand.
- Sequential ID generator: an identifier generator that returns predictable strings such as
test-1andtest-2. - Fixture scene: a generated array of elements with a regular grid layout. A fixture is fixed test data.
- Test editor: a bundle that contains an
EditorCoreand aManualScheduler.
The types Clock, IdGenerator, EditorCore, and EditorElement come from core. The spatial index comes from scene.
Manual scheduler #
createManualScheduler creates a ManualScheduler. The scheduler stores tasks per phase. No task runs until you flush it.
import { createManualScheduler } from "@jeeboard/testkit";
const scheduler = createManualScheduler();
const events: string[] = [];
scheduler.request(() => events.push("background"), "background");
scheduler.request(() => events.push("presentation"), "presentation");
scheduler.request(() => events.push("raster"), "raster");
scheduler.flush("presentation");
// events is ["presentation"]
scheduler.pending("background"); // 1
scheduler.flushAll();
// events is ["presentation", "raster", "background"]
The ManualScheduler methods are:
request(task, phase?)queues a task. The default phase isbackground.flush(phase)runs all queued tasks for one phase.flushAll()runs all phases in the orderpresentation,compilation,raster,background.pending(phase)returns the number of queued tasks for one phase.
Manual clock #
createManualClock creates a Clock with an extra advance method. The clock time does not change until you advance it.
import { createManualClock } from "@jeeboard/testkit";
const clock = createManualClock(100);
clock.advance(25);
clock.now(); // 125
The parameter of createManualClock is the start time. The default start time is 0. The parameter of advance is the number of milliseconds to add.
NOTE: advance throws an error if the value is negative or not finite.
Sequential ID generator #
createSequentialIdGenerator creates an IdGenerator that counts up from one.
import { createSequentialIdGenerator } from "@jeeboard/testkit";
const ids = createSequentialIdGenerator();
ids.next(); // "test-1"
ids.next(); // "test-2"
The optional parameter is the prefix. The default prefix is "test".
Test editor #
createTestEditor creates an EditorCore and a ManualScheduler together. Pass an array of initial elements to populate the core.
import { createTestEditor } from "@jeeboard/testkit";
const { core, scheduler } = createTestEditor();
The returned object has two read-only fields: core and scheduler. Use core for document state. Use scheduler to control when deferred work runs.
Fixture scenes #
createShapeBenchmarkScene creates count shape elements in a grid layout. Each element is 100 units wide and 80 units high. The columns have a spacing of 120 units. The rows have a spacing of 100 units. Each element has the identifier benchmark-shape-<index> and the properties { shape: "rectangle" }.
import { createShapeBenchmarkScene } from "@jeeboard/testkit";
const elements = createShapeBenchmarkScene(100);
The function is deterministic. Two calls with the same count return the same identifiers.
NOTE: createShapeBenchmarkScene throws an error if the count is not a non-negative integer.
Spatial benchmark #
benchmarkSpatialIndex builds a fixture scene, inserts it into a uniform grid index, and runs rectangle queries. It returns a SpatialBenchmarkResult:
elementCount: the requested number of elements.queryCount: the requested number of queries.indexedElements: the number of elements inserted into the index.queriedElements: the total number of elements returned by all queries.elapsedMs: the total query time in milliseconds.averageQueryMs: the query time divided by the query count.
import { benchmarkSpatialIndex } from "@jeeboard/testkit";
const result = benchmarkSpatialIndex(100, 3);
// result.elementCount is 100
// result.indexedElements is 100
The defaults are 100,000 elements and 100 queries. The index cell size is 3,000 units. Each query rectangle is 1,920 by 1,080 units.
NOTE: benchmarkSpatialIndex throws an error if the element count is not a non-negative integer. It also throws if the query count is not a positive integer.
Benchmark script #
The package contains a benchmark script at test/benchmark.mjs. The script prints the result as JSON. Run it from the repository with pnpm:
- Open a terminal in the repository root.
- Run
pnpm --filter @jeeboard/testkit bench. - Read the JSON result on the standard output.
NOTE: The script imports the compiled dist output. The bench script builds the package before it runs the benchmark.
API reference #
See the generated TypeDoc page for @jeeboard/testkit.