Skip to content

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.

SymbolSummary
ClockSchedulerclass. Schedules deterministic one-shot and periodic callbacks against explicitly advanced seconds.
DebugScenarioclass. Builds a detached input sequence, reproduces its first deterministic failure, and deletion-minimizes it.
DebugToolsclass. Produces detached, stable descriptions of GameKit ownership and ordering for headless diagnostics.
DebugTraceclass. Bounded opt-in diagnostic ring that detaches and optionally redacts each event.
PresentationClockclass. Independently pausable, scalable clock for presentation-domain timers.
ScheduledWorkclass. Stable control handle for one scheduler entry.
ScheduleOwnerclass. Generation token that prevents scheduled callbacks from surviving disposal or object-pool reuse.
SimulationClockclass. Fixed-step simulation time domain with a scheduler advanced before each user tick callback.

ClockScheduler ​

ts
import { ClockScheduler } from "gamekit/src/testing";
class ClockScheduler

Schedules 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(): float

Elapsed scheduler time in explicitly supplied seconds.

ts
get catchUpCap(): int

Maximum periodic catch-up callbacks attempted in one advance.

ts
get advancing(): boolean

Is true while the due-work snapshot is executing.

ts
get activeCount(): int

Number of retained active entries, including future and backlogged periodic work.

ts
schedule(delay: float, callback: Function, owner: ScheduleOwner | null = null): ScheduledWork

Enqueues 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): ScheduledWork

Enqueues 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): int

Advances 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): void

Invalidates an active internal entry; inactive entries are ignored.

  • entry: Entry owned by a ScheduledWork handle.
ts
rescheduleEntry(entry: ScheduledEntry, delay: float): void

Replaces an active entry's due time without changing its ID or creating a second callback.

  • entry: Entry owned by a ScheduledWork handle.
  • delay: Non-negative seconds relative to current scheduler time.
  • Throws: Error if delay is negative.

DebugScenario ​

ts
import { DebugScenario } from "gamekit";
class DebugScenario

Builds 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): DebugScenario

Appends 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 label is empty.
ts
steps(): any[]

Returns detached {label, input} records in execution order.

ts
run(initial: any, apply: Function, assertFailure: Function | null = null): any

Applies 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 or null.
  • Returns: Failure details at the first reason, otherwise final state and a complete transcript.
ts
minimize(stillFails: Function): DebugScenario

Removes 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 DebugTools

Produces 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): any

Recursively 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): any

Describes 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): any

Reads 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): any

Copies 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): any

Normalizes 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): any

Copies 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): any

Copies bottom-to-top scene names, count, and transition activity without invoking hooks.

  • scenes: Sole scene stack to inspect.
ts
static inspectEffects(effects: any): any

Copies effect IDs, keys, order, state, and values without exposing handles.

  • effects: Collection whose lifecycle entries are inspected.
ts
static inspectAssets(manager: any): any

Copies 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): any

Reports 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): string

Detaches a value and serializes it with canonical object-key ordering.

  • value: Debug state to snapshot.
ts
static diff(before: any, after: any): any

Compares 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 key value.
ts
static assertTranscript(actual: any, expected: any): void

Compares 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 DebugTrace

Bounded 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(): boolean

Is true when record will retain data and invoke hooks.

ts
get count(): int

Number of retained entries, never greater than configured capacity.

ts
setEnabled(enabled: boolean): void

Changes recording state without clearing existing entries.

  • enabled: Whether later calls may retain and observe events.
ts
record(kind: string, value: any): void

Redacts, 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(): void

Clears retained entries without changing enabled state or hooks.

PresentationClock ​

ts
import { PresentationClock } from "gamekit/src/testing";
class PresentationClock

Independently 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(): ClockScheduler

Scheduler sharing this clock's scaled seconds and pause behavior.

ts
get time(): float

Total scaled seconds accepted while unpaused.

ts
get timeScale(): float

Multiplier applied to later elapsed-time advances.

ts
get paused(): boolean

Is true when advances discard elapsed time and run no callbacks.

ts
setTimeScale(scale: float): void

Changes the multiplier for future advances without altering accumulated time.

  • scale: Non-negative elapsed-time multiplier; zero freezes progression without setting paused.
  • Throws: Error if scale is negative.
ts
pause(): void

Starts discarding subsequent elapsed-time advances.

ts
resume(): void

Accepts later advances again without replaying time discarded while paused.

ts
advance(elapsed: float): int

Adds 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 ScheduledWork

Stable 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(): int

Scheduler-local monotonic identity used to order equal due times.

ts
get active(): boolean

Is true while the entry remains eligible for future invocation.

ts
cancel(): void

Prevents future invocations; repeated cancellation has no effect.

ts
reschedule(delay: float): void

Moves 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 ScheduleOwner

Generation 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(): int

Revision number incremented on each dispose and revive boundary.

ts
get disposed(): boolean

Is true while no callbacks may target this owner.

ts
dispose(): void

Invalidates all work scheduled against the current generation; repeated calls are inert.

ts
revive(): void

Begins 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 SimulationClock

Fixed-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(): ClockScheduler

Timer scheduler sharing fixed-step simulated seconds.

ts
get time(): float

Total seconds in successfully started fixed ticks; fractional remainder is excluded.

ts
get timeScale(): float

Multiplier applied to later elapsed-time advances.

ts
get paused(): boolean

Is true when advance discards time; manual steps remain available.

ts
get tickCount(): int

Count of successfully completed fixed ticks, starting at zero.

ts
get interpolation(): float

Buffered fraction of the next fixed tick, clamped to [0, 1].

ts
setTimeScale(scale: float): void

Changes the multiplier for future automatic advances.

  • scale: Non-negative multiplier; zero freezes automatic ticks.
  • Throws: Error if scale is negative.
ts
pause(): void

Makes later automatic advances discard time without clearing an existing fractional remainder.

ts
resume(): void

Re-enables automatic advancement without replaying discarded time.

ts
advance(elapsed: float): int

Scales 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(): void

Runs one fixed tick immediately, including due timers, without consuming the stepper remainder.

ts
singleStep(): void

Alias for step, emphasizing its use while automatic advancement is paused.