testing family
Deterministic clocks and schedulers, test asset loaders, debug inspection, scenarios and traces.
Import these from gamekit/src/testing (a few are also re-exported by the package root, as noted on each).
8 symbols, 3 of them also in the package root.
| Symbol | Summary |
|---|---|
ClockScheduler | class. Schedules deterministic one-shot and periodic callbacks against explicitly advanced seconds. |
DebugScenario | class. Builds a detached input sequence, reproduces its first deterministic failure, and deletion-minimizes it. |
DebugTools | class. Produces detached, stable descriptions of GameKit ownership and ordering for headless diagnostics. |
DebugTrace | class. Bounded opt-in diagnostic ring that detaches and optionally redacts each event. |
PresentationClock | class. Independently pausable, scalable clock for presentation-domain timers. |
ScheduledWork | class. Stable control handle for one scheduler entry. |
ScheduleOwner | class. Generation token that prevents scheduled callbacks from surviving disposal or object-pool reuse. |
SimulationClock | class. Fixed-step simulation time domain with a scheduler advanced before each user tick callback. |
ClockScheduler
ts
import { ClockScheduler } from "gamekit/src/testing";
class ClockSchedulerSchedules deterministic one-shot and periodic callbacks against explicitly advanced seconds. Each advance snapshots eligible work, orders equal due times by stable ID, and defers work created by callbacks until the next advance.
Members
ts
constructor(catchUpCap: int = DEFAULT_SCHEDULER_CATCH_UP_CAP)Creates an empty scheduler at time zero.
catchUpCap: Positive limit on periodic catch-up callbacks per advance.- Throws: Error if the cap is not positive.
ts
get time(): floatElapsed scheduler time in explicitly supplied seconds.
ts
get catchUpCap(): intMaximum periodic catch-up callbacks attempted in one advance.
ts
get advancing(): booleanIs true while the due-work snapshot is executing.
ts
get activeCount(): intNumber of retained active entries, including future and backlogged periodic work.
ts
schedule(delay: float, callback: Function, owner: ScheduleOwner | null = null): ScheduledWorkEnqueues a one-shot callback relative to current scheduler time.
delay: Non-negative seconds before eligibility.callback: Synchronous work invoked at most once.owner: Optional generation-checked lifetime owner.- Returns: Stable handle for cancellation or rescheduling.
- Throws: Error if delay is negative.
ts
scheduleEvery(period: float, callback: Function, owner: ScheduleOwner | null = null): ScheduledWorkEnqueues periodic work whose first due time is one period from now.
period: Positive seconds between due times.callback: Synchronous work that may run repeatedly during catch-up.owner: Optional generation-checked lifetime owner.- Returns: Stable handle retaining one identity across repetitions.
- Throws: Error if period is not positive.
ts
advance(elapsed: float): intAdvances time, snapshots due entries, and invokes them by due time then ID. Cancellation inside a callback does not remove another callback already in the snapshot; newly scheduled work waits for a later call.
elapsed: Non-negative seconds to add, including zero for draining eligible deferred work.- Returns: Number of callbacks invoked.
- Throws: Error for negative elapsed time, recursive advancement, or a callback failure.
ts
cancelEntry(entry: ScheduledEntry): voidInvalidates an active internal entry; inactive entries are ignored.
entry: Entry owned by aScheduledWorkhandle.
ts
rescheduleEntry(entry: ScheduledEntry, delay: float): voidReplaces an active entry's due time without changing its ID or creating a second callback.
entry: Entry owned by aScheduledWorkhandle.delay: Non-negative seconds relative to current scheduler time.- Throws: Error if delay is negative.
DebugScenario
ts
import { DebugScenario } from "gamekit";
class DebugScenarioBuilds a detached input sequence, reproduces its first deterministic failure, and deletion-minimizes it. Transitions and assertions run synchronously from copied state and inputs.
Members
ts
constructor(seed: int)Creates an empty scenario carrying the seed reported to every transition and result.
seed: Game-selected reproduction seed; the scenario does not interpret it.
ts
step(label: string, input: any): DebugScenarioAppends a detached input with a diagnostic label.
label: Non-empty human-readable step name.input: Value copied now for later replay.- Returns: This scenario for chaining.
- Throws: Error if
labelis empty.
ts
steps(): any[]Returns detached {label, input} records in execution order.
ts
run(initial: any, apply: Function, assertFailure: Function | null = null): anyApplies steps until the assertion returns a reason, capturing the failing boundary and canonical diff.
initial: State copied before the first transition.apply: Synchronous(state, input, seed, index)transition returning next state.assertFailure: Optional(state, seed, index, input)callback returning a reason ornull.- Returns: Failure details at the first reason, otherwise final state and a complete transcript.
ts
minimize(stillFails: Function): DebugScenarioRemoves contiguous chunks while the supplied clean-run predicate still reproduces failure.
stillFails: Synchronous predicate receiving each candidate scenario.- Returns: New scenario with retained step order and the same seed; the original is unchanged.
DebugTools
ts
import { DebugTools } from "gamekit";
class DebugToolsProduces detached, stable descriptions of GameKit ownership and ordering for headless diagnostics. Object keys are sorted, functions are omitted, and cycles become the literal [circular].
Members
ts
static inspect(value: any): anyRecursively copies data into sorted debug-safe objects without live references.
value: Value to detach; repeated references on one traversal are rendered as[circular].
ts
static inspectWorld(world: any): anyDescribes entities, stores, components, effects, deferred commands, guard depths, and teardown state without mutation.
world: World whose public and diagnostic state is copied.- Returns: Detached snapshot ordered by the world's current entity and registration order.
ts
static inspectQuery(query: any): anyReads required component labels from a Query or Query2 without executing iteration.
query: Query whose one or two keys are inspected.
ts
static inspectPhases(schedule: any): anyCopies declared phase order, dependencies, system counts, flush flags, and current running state.
schedule: Phase schedule inspected without resolving or running it.
ts
static inspectClock(clock: any): anyNormalizes a simulation clock, presentation clock, or bare scheduler into one timing snapshot.
clock: Clock or scheduler to inspect without advancing it.
ts
static inspectInputRouter(router: any): anyCopies context precedence, action captures, and queued-release count without routing a frame.
router: Input router whose current ownership is inspected.
ts
static inspectScenes(scenes: any): anyCopies bottom-to-top scene names, count, and transition activity without invoking hooks.
scenes: Sole scene stack to inspect.
ts
static inspectEffects(effects: any): anyCopies effect IDs, keys, order, state, and values without exposing handles.
effects: Collection whose lifecycle entries are inspected.
ts
static inspectAssets(manager: any): anyCopies asset keys, states, reference counts, generations, and errors without exposing loaded assets.
manager: Asset manager inspected without changing loads or scopes.
ts
static inspectSaves(manager: any): anyReports slot extension, autosave limit, shutdown flag, and per-slot queue count without storage I/O.
manager: Save-slot manager whose configuration is inspected.
ts
static canonicalSnapshot(value: any): stringDetaches a value and serializes it with canonical object-key ordering.
value: Debug state to snapshot.
ts
static diff(before: any, after: any): anyCompares detached canonical values and lists changed top-level keys in sorted order.
before: Earlier diagnostic state.after: Later diagnostic state.- Returns:
{changed, before, after}; scalar differences use the synthetic keyvalue.
ts
static assertTranscript(actual: any, expected: any): voidCompares canonical detached transcripts and includes both serialized forms on mismatch.
actual: Produced transcript.expected: Expected transcript.- Throws: Error when canonical transcripts differ.
DebugTrace
ts
import { DebugTrace } from "gamekit";
class DebugTraceBounded opt-in diagnostic ring that detaches and optionally redacts each event. Disabled recording returns before allocation, redaction, or observer callbacks.
Members
ts
constructor(enabled: boolean = false, maxEntries: int = 128, redactor: Function | null = null, callback: Function | null = null)Configures trace retention and enabled-only hooks.
enabled: Initial recording state.maxEntries: Positive capacity; the oldest entry is evicted on overflow.redactor: Optional transform applied before detaching a recorded value.callback: Optional observer receiving a detached entry after retention.- Throws: Error if capacity is not positive.
ts
get enabled(): booleanIs true when record will retain data and invoke hooks.
ts
get count(): intNumber of retained entries, never greater than configured capacity.
ts
setEnabled(enabled: boolean): voidChanges recording state without clearing existing entries.
enabled: Whether later calls may retain and observe events.
ts
record(kind: string, value: any): voidRedacts, detaches, retains, and observes one event when enabled.
kind: Non-empty stable event category.value: Live game value; neither retention nor observer receives this reference.- Throws: Error for an empty kind when enabled.
ts
entries(): any[]Returns detached entries from oldest retained to newest.
ts
clear(): voidClears retained entries without changing enabled state or hooks.
PresentationClock
ts
import { PresentationClock } from "gamekit/src/testing";
class PresentationClockIndependently pausable, scalable clock for presentation-domain timers. It advances only from supplied elapsed seconds and owns a scheduler in the same scaled time domain.
Members
ts
constructor(schedulerCatchUpCap: int = DEFAULT_SCHEDULER_CATCH_UP_CAP)Creates a time-zero presentation domain.
schedulerCatchUpCap: Positive periodic callback cap for the owned scheduler.- Throws: Error if the scheduler cap is not positive.
ts
get scheduler(): ClockSchedulerScheduler sharing this clock's scaled seconds and pause behavior.
ts
get time(): floatTotal scaled seconds accepted while unpaused.
ts
get timeScale(): floatMultiplier applied to later elapsed-time advances.
ts
get paused(): booleanIs true when advances discard elapsed time and run no callbacks.
ts
setTimeScale(scale: float): voidChanges the multiplier for future advances without altering accumulated time.
scale: Non-negative elapsed-time multiplier; zero freezes progression without settingpaused.- Throws: Error if scale is negative.
ts
pause(): voidStarts discarding subsequent elapsed-time advances.
ts
resume(): voidAccepts later advances again without replaying time discarded while paused.
ts
advance(elapsed: float): intAdds scaled elapsed seconds and runs scheduler work due in the new interval.
elapsed: Non-negative unscaled seconds from the presentation loop.- Returns: Callback count, or zero while paused.
- Throws: Error for negative elapsed time or scheduler callback failures.
ScheduledWork
ts
import { ScheduledWork } from "gamekit/src/testing";
class ScheduledWorkStable control handle for one scheduler entry. Its ID survives rescheduling; completed, cancelled, or stale-owner work becomes inactive permanently.
Members
ts
constructor(scheduler: any, entry: ScheduledEntry)Binds an internal entry to the scheduler that created it.
scheduler: Scheduler receiving handle operations.entry: Internal entry whose identity and state are exposed.
ts
get id(): intScheduler-local monotonic identity used to order equal due times.
ts
get active(): booleanIs true while the entry remains eligible for future invocation.
ts
cancel(): voidPrevents future invocations; repeated cancellation has no effect.
ts
reschedule(delay: float): voidMoves active work relative to current scheduler time while preserving its ID.
delay: Non-negative seconds from now; inactive work remains inactive.- Throws: Error if delay is negative.
ScheduleOwner
ts
import { ScheduleOwner } from "gamekit/src/testing";
class ScheduleOwnerGeneration token that prevents scheduled callbacks from surviving disposal or object-pool reuse. Schedulers capture the generation at scheduling time and retire work when it no longer matches.
Members
ts
get generation(): intRevision number incremented on each dispose and revive boundary.
ts
get disposed(): booleanIs true while no callbacks may target this owner.
ts
dispose(): voidInvalidates all work scheduled against the current generation; repeated calls are inert.
ts
revive(): voidBegins a fresh live generation without reviving stale work.
- Throws: Error when the owner is already live.
SimulationClock
ts
import { SimulationClock } from "gamekit/src/testing";
class SimulationClockFixed-step simulation time domain with a scheduler advanced before each user tick callback. Pausing discards supplied time, while manual stepping still executes exactly one tick.
Members
ts
constructor(tickDuration: float, catchUpCap: int, tickWork: Function, schedulerCatchUpCap: int = DEFAULT_SCHEDULER_CATCH_UP_CAP)Creates a time-zero fixed-step domain and its timer scheduler.
tickDuration: Positive simulated seconds per tick.catchUpCap: Positive tick limit per advance.tickWork: Callback receiving(tickDuration, zeroBasedTickNumber)after due timers.schedulerCatchUpCap: Positive periodic callback cap per scheduler advance.- Throws: Error if either duration or cap is invalid.
ts
get scheduler(): ClockSchedulerTimer scheduler sharing fixed-step simulated seconds.
ts
get time(): floatTotal seconds in successfully started fixed ticks; fractional remainder is excluded.
ts
get timeScale(): floatMultiplier applied to later elapsed-time advances.
ts
get paused(): booleanIs true when advance discards time; manual steps remain available.
ts
get tickCount(): intCount of successfully completed fixed ticks, starting at zero.
ts
get interpolation(): floatBuffered fraction of the next fixed tick, clamped to [0, 1].
ts
setTimeScale(scale: float): voidChanges the multiplier for future automatic advances.
scale: Non-negative multiplier; zero freezes automatic ticks.- Throws: Error if scale is negative.
ts
pause(): voidMakes later automatic advances discard time without clearing an existing fractional remainder.
ts
resume(): voidRe-enables automatic advancement without replaying discarded time.
ts
advance(elapsed: float): intScales elapsed seconds and runs as many complete ticks as the catch-up cap permits.
elapsed: Non-negative unscaled seconds since the previous call.- Returns: Completed tick count, or zero while paused.
- Throws: Error for negative elapsed time, recursive stepping, or callback failures.
ts
step(): voidRuns one fixed tick immediately, including due timers, without consuming the stepper remainder.
ts
singleStep(): voidAlias for step, emphasizing its use while automatic advancement is paused.