Skip to content

@aosengine/test-harness ​

Interfaces ​

FrameInputOverrides ​

Fields createFrameInput accepts.

Properties ​

bodies? ​
ts
optional bodies?: Float32Array<ArrayBufferLike>;

Packed body rows, stride 15.

contacts? ​
ts
optional contacts?: readonly Contact[];

Reported contacts.

dt? ​
ts
optional dt?: number;

Fixed timestep in seconds. Default 1 / 60.

elapsed? ​
ts
optional elapsed?: number;

Simulated seconds since init. Defaults to frame * dt.

events? ​
ts
optional events?: readonly GameEvent[];

Host-side events.

frame? ​
ts
optional frame?: number | bigint;

Fixed-step counter. Accepts a number for convenience.

input? ​
ts
optional input?: MutableInputState;

Input state to reuse; a fresh neutral one is built when absent.


LogLine ​

One recorded env.log call.

Properties ​

level ​
ts
level: LogLevel;
msg ​
ts
msg: string;

MockAsset ​

A manifest entry the mock host will resolve.

Properties ​

hasCollider? ​
ts
optional hasCollider?: boolean;

Whether a collider asset is attached. Default false.

kind? ​
ts
optional kind?: AssetKind;

Asset family. Default 'data'.

name ​
ts
name: string;

Manifest string id.

ready? ​
ts
optional ready?: boolean;

Whether the bytes are resident. Default true.

rig? ​
ts
optional rig?: string;

Rig backend for character assets.

tags? ​
ts
optional tags?: readonly string[];

Tags, verbatim.


MockHost ​

A mock host, plus the recordings a test asserts on.

Extends ​

Properties ​

log_ ​
ts
readonly log_: LogLine[];

Every env.log call, in order.

rayCalls ​
ts
readonly rayCalls: object;

How many raycast calls the guest made.

batch ​
ts
batch: number;
overlap ​
ts
overlap: number;
raycast ​
ts
raycast: number;

Methods ​

describe() ​
ts
describe(id): AssetDesc | null | undefined;

Metadata for a handle, or nullish when the handle is unknown.

Parameters ​
ParameterType
idnumber
Returns ​

AssetDesc | null | undefined

Inherited from ​

HostApi.describe

handleOf() ​
ts
handleOf(name): number;

The handle a name resolves to, minting one when needed.

Parameters ​
ParameterType
namestring
Returns ​

number

log() ​
ts
log(level, msg): void;

Route a message to the host logger.

Parameters ​
ParameterType
levelLogLevel
msgstring
Returns ​

void

Inherited from ​

HostApi.log

nowMs() ​
ts
nowMs(): number;

Monotonic milliseconds since engine start. Never feed this to simulation.

Returns ​

number

Inherited from ​

HostApi.nowMs

overlapSphere() ​
ts
overlapSphere(
   center, 
   radius, 
   filter, 
   maxResults
): readonly OverlapHit[];

Bodies overlapping a sphere, nearest first.

Parameters ​
ParameterType
centerVec3
radiusnumber
filterQueryFilter
maxResultsnumber
Returns ​

readonly OverlapHit[]

Inherited from ​

HostApi.overlapSphere

raycast() ​
ts
raycast(
   origin, 
   direction, 
   maxDistance, 
   filter
): RayHit | null | undefined;

Closest hit along a ray, or nullish on a miss.

Parameters ​
ParameterType
originVec3
directionVec3
maxDistancenumber
filterQueryFilter
Returns ​

RayHit | null | undefined

Inherited from ​

HostApi.raycast

raycastBatch() ​
ts
raycastBatch(rays): readonly (RayHit | null | undefined)[];

One round trip for many rays; result index i matches rays[i].

Parameters ​
ParameterType
raysreadonly RayQuery[]
Returns ​

readonly (RayHit | null | undefined)[]

Inherited from ​

HostApi.raycastBatch

reset() ​
ts
reset(): void;

Forget every recording.

Returns ​

void

resolveId() ​
ts
resolveId(name): number | null | undefined;

Manifest string id to handle, or nullish when the manifest has no entry.

Parameters ​
ParameterType
namestring
Returns ​

number | null | undefined

Inherited from ​

HostApi.resolveId

seed() ​
ts
seed(): number;

The deterministic run seed, as a number (already Number()-coerced).

Returns ​

number

Inherited from ​

HostApi.seed

warnings() ​
ts
warnings(): LogLine[];

Lines at 'warn' or 'error'.

Returns ​

LogLine[]


MockHostOptions ​

How to build a mock host.

Properties ​

assets? ​
ts
optional assets?: readonly (string | MockAsset)[];

Manifest entries: the assets this game is allowed to name.

With the default MockHostOptions.strictAssets this is the whole manifest, and a name that is not here resolves to nothing, exactly as a missing entry in assets.json would.

nowMs? ​
ts
optional nowMs?: () => number;

Milliseconds env.nowMs() returns; defaults to a 0.1 ms counter.

Returns ​

number

overlapSphere? ​
ts
optional overlapSphere?: (center, radius, filter, maxResults) => readonly OverlapHit[];

Scripted sphere overlap. Default: no hits.

Parameters ​
ParameterType
centerVec3
radiusnumber
filterQueryFilter
maxResultsnumber
Returns ​

readonly OverlapHit[]

raycast? ​
ts
optional raycast?: (origin, direction, maxDistance, filter) => RayHit | null;

Scripted raycast. Return null for a miss. Default: always a miss.

Parameters ​
ParameterType
originVec3
directionVec3
maxDistancenumber
filterQueryFilter
Returns ​

RayHit | null

seed? ​
ts
optional seed?: number;

The value env.seed() returns. Default 0x5eed1234.

strictAssets? ​
ts
optional strictAssets?: boolean;

Refuse to resolve names that are not in assets. Default true.

Minting a synthetic handle for any name a game asks for hides the most common asset bug there is — a typo, or an id that was never added to assets.json — behind a test that passes. Set it to false for a test that genuinely does not care which assets exist.


MutableInputState ​

A mutable, host-shaped input state.

Extends ​

Properties ​

focused ​
ts
focused: boolean;
Overrides ​

InputState.focused

gamepads ​
ts
gamepads: GamepadState[];
Overrides ​

InputState.gamepads

keys ​
ts
keys: object;
down ​
ts
down: Uint32Array;
pressed ​
ts
pressed: Uint32Array;
released ​
ts
released: Uint32Array;
Overrides ​

InputState.keys

mods ​
ts
mods: InputMods;
Overrides ​

InputState.mods

mouse ​
ts
mouse: MouseState;
Overrides ​

InputState.mouse


SimulateOptions ​

How to run a simulation.

Properties ​

dt? ​
ts
optional dt?: number;

Fixed timestep in seconds. Default 1 / 60.

frames ​
ts
frames: number;

How many frames to run.

keepOutputs? ​
ts
optional keepOutputs?: boolean;

Keep every frame-output. Off by default: outputs are reused objects.

script? ​
ts
optional script?: FrameScript;

Per-frame overrides. Mutate input (the same state object is reused and its edges cleared between frames) or return fields to merge.


SimulateResult ​

What a simulation produced.

Properties ​

commandTags ​
ts
commandTags: string[][];

Commands seen per frame, by tag.

hash ​
ts
hash: number;

Combined hash of every frame.

hashes ​
ts
hashes: number[];

One hashFrameOutput per frame, in order.

hud ​
ts
hud: object[];

Every HUD payload that crossed, with the frame it crossed on.

frame ​
ts
frame: number;
json ​
ts
json: string;
outputs ​
ts
outputs: FrameOutput[];

Outputs, when keepOutputs is set.

transformRows ​
ts
transformRows: number[];

Transform row counts per frame.


Tickable ​

Anything with the guest's per-frame entry point.

Methods ​

tick() ​
ts
tick(input): FrameOutput;
Parameters ​
ParameterType
inputHostFrameInput
Returns ​

FrameOutput

Type Aliases ​

FrameScript ​

ts
type FrameScript = (frame, input) => FrameInputOverrides | void;

A per-frame script. Mutate input in place, and optionally return fields to merge into the frame.

void in the return union is deliberate: a script that only mutates input should not have to write return undefined.

Parameters ​

ParameterType
framenumber
inputMutableInputState

Returns ​

FrameInputOverrides | void

Variables ​

PACKAGE ​

ts
const PACKAGE: "@aosengine/test-harness";

Package identity marker.

Example ​

ts
import { PACKAGE } from '@aosengine/test-harness';

console.log(PACKAGE); // '@aosengine/test-harness'

Functions ​

createFrameInput() ​

ts
function createFrameInput(overrides?): HostFrameInput;

Build one frame-input, in host-side shapes.

Parameters ​

ParameterTypeDescription
overridesFrameInputOverridesAnything to change from the neutral frame.

Returns ​

HostFrameInput

A fresh frame input.

Example ​

ts
import { createFrameInput } from '@aosengine/test-harness';

const input = createFrameInput({ frame: 0 });

createGameConfig() ​

ts
function createGameConfig(overrides?): HostGameConfig;

Build a game-config, in host-side shapes.

Parameters ​

ParameterTypeDescription
overridesPartial<HostGameConfig>Anything to change from the defaults.

Returns ​

HostGameConfig

A fresh config.

Example ​

ts
import { createGameConfig } from '@aosengine/test-harness';

sandbox.init(createGameConfig({ seed: 7n }));

createInputState() ​

ts
function createInputState(): MutableInputState;

Build a neutral input state: nothing held, nothing moving, canvas focused.

Returns ​

MutableInputState

A fresh mutable input state.

Example ​

ts
import { createInputState, press } from '@aosengine/test-harness';

const state = createInputState();
press(state, 'W');

createMockHost() ​

ts
function createMockHost(options?): MockHost;

Create a scripted host.

Parameters ​

ParameterTypeDescription
optionsMockHostOptionsSeed, scripted queries and the manifest.

Returns ​

MockHost

A HostApi with recordings attached.

Example ​

ts
import { createMockHost } from '@aosengine/test-harness';

const host = createMockHost({
  seed: 42,
  assets: ['env.arena'],
  raycast: (origin) => ({
    body: 1,
    entity: 1,
    point: origin,
    normal: { x: 0, y: 1, z: 0 },
    distance: 2,
  }),
});

endFrame() ​

ts
function endFrame(state): void;

Clear the per-frame edges, keeping held keys held.

Call this between frames, exactly as @aosengine/input does.

Parameters ​

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.

Returns ​

void

Nothing.

Example ​

ts
import { endFrame } from '@aosengine/test-harness';

endFrame(state);

hashCommands() ​

ts
function hashCommands(commands): number;

Hash a command list.

Commands are JSON, not floats: their payloads are structural, and a textual difference is exactly what a parity test wants to see.

Parameters ​

ParameterTypeDescription
commandsreadonly Command[]The frame-output.commands list.

Returns ​

number

A 32-bit hash.

Example ​

ts
import { hashCommands } from '@aosengine/test-harness';

expect(hashCommands(out.commands)).toMatchInlineSnapshot();

hashFrameOutput() ​

ts
function hashFrameOutput(out): number;

Hash a whole frame-output: transforms, commands, camera and HUD.

Parameters ​

ParameterTypeDescription
outFrameOutputThe output to hash.

Returns ​

number

A 32-bit hash.

Example ​

ts
import { hashFrameOutput } from '@aosengine/test-harness';

expect(hashFrameOutput(direct)).toBe(hashFrameOutput(wasm));

hashString() ​

ts
function hashString(hash, text): number;

Fold a string into a running FNV-1a hash.

Parameters ​

ParameterTypeDescription
hashnumberThe running hash.
textstringThe string.

Returns ​

number

The new hash.


hashTransforms() ​

ts
function hashTransforms(transforms): number;

Hash a packed transform buffer.

Parameters ​

ParameterTypeDescription
transformsArrayLike<number>The frame-output.transforms list, stride 12.

Returns ​

number

A 32-bit hash.

Example ​

ts
import { hashTransforms } from '@aosengine/test-harness';

expect(hashTransforms(a.transforms)).toBe(hashTransforms(b.transforms));

hashU32() ​

ts
function hashU32(hash, word): number;

Fold a 32-bit word into a running FNV-1a hash, little-endian.

Parameters ​

ParameterTypeDescription
hashnumberThe running hash.
wordnumberThe word.

Returns ​

number

The new hash.


packBodies() ​

ts
function packBodies(rows): Float32Array;

Build a packed bodies row set, stride 15.

Parameters ​

ParameterTypeDescription
rowsreadonly object[]One entry per live body.

Returns ​

Float32Array

A Float32Array sorted ascending by body id.

Example ​

ts
import { packBodies } from '@aosengine/test-harness';

const bodies = packBodies([{ body: 1, position: [0, 1, 0] }]);

press() ​

ts
function press(state, key): void;

Hold a key down and record the press edge.

Parameters ​

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
keystringA key name: 'KeyW', 'W', 'Shift'.

Returns ​

void

Nothing.

Example ​

ts
import { createInputState, press } from '@aosengine/test-harness';

const state = createInputState();
press(state, 'Space');

pressMouse() ​

ts
function pressMouse(state, button): void;

Press a mouse button.

Parameters ​

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
buttonnumberA bit mask; 1 left, 2 right, 4 middle.

Returns ​

void

Nothing.

Example ​

ts
import { pressMouse } from '@aosengine/test-harness';

pressMouse(state, 1);

release() ​

ts
function release(state, key): void;

Release a key and record the release edge.

Parameters ​

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
keystringA key name.

Returns ​

void

Nothing.

Example ​

ts
import { release } from '@aosengine/test-harness';

release(state, 'Space');

releaseMouse() ​

ts
function releaseMouse(state, button): void;

Release a mouse button.

Parameters ​

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
buttonnumberA bit mask.

Returns ​

void

Nothing.

Example ​

ts
import { releaseMouse } from '@aosengine/test-harness';

releaseMouse(state, 1);

simulate() ​

ts
function simulate(guest, options): SimulateResult;

Run a guest for frames fixed steps.

Parameters ​

ParameterTypeDescription
guestTickableAnything with a tick, including a Sandbox.
optionsSimulateOptionsFrame count and the per-frame script.

Returns ​

SimulateResult

Hashes, command tags, HUD payloads and row counts.

Example ​

ts
import { simulate, press } from '@aosengine/test-harness';

const result = simulate(sandbox, {
  frames: 300,
  script: (frame, input) => {
    if (frame === 10) press(input, 'W');
  },
});

stableJson() ​

ts
function stableJson(value): string;

JSON with object keys sorted, so two structurally identical payloads hash the same whatever order their fields were assigned in.

Parameters ​

ParameterTypeDescription
valueunknownAnything JSON-serialisable.

Returns ​

string

The canonical rendering.