# 2D physics test harness

```ts
import { createPhysicsTestHarness2D } from "@pibbl/core/physics/2d/testing";
import type {
  PibblPhysicsTestHarness2D,
  PibblPhysicsTestHarness2DOptions,
} from "@pibbl/core/physics/2d/testing";
```

`createPhysicsTestHarness2D` mounts a public Pibbl root with a deterministic
manual host-frame driver. It lets tests and coding agents observe public handles
and state without importing private world storage.

```text
function createPhysicsTestHarness2D<Observation>(
  options: PibblPhysicsTestHarness2DOptions<Observation>,
): PibblPhysicsTestHarness2D<Observation>;
```

### `PibblPhysicsTestHarness2DOptions`

```text
interface PibblPhysicsTestHarness2DOptions<Observation> {
  readonly canvas: HTMLCanvasElement;
  readonly root: () => PibblNode;
  readonly observe: () => Observation;
}
```

The caller owns the canvas; disposal never removes it. `root()` creates the
initial and reset composition. `observe()` should read public application
state. External fixtures are not reset automatically.

### `PibblPhysicsTestHarness2D`

```text
interface PibblPhysicsTestHarness2D<Observation> {
  readonly pendingFrames: number;
  flush(): boolean;
  advanceFrames(count: number, milliseconds?: number): number;
  act<Result>(callback: () => Result): Result;
  observe(): Observation;
  reset(): void;
  dispose(): void;
}
```

`flush()` delivers one requested host frame at current host time. `advanceFrames`
uses `1000 / 60` milliseconds by default and returns the host callbacks it ran;
it does not promise an equal number of physics ticks because fixed-step worlds
may take zero, one, or several ticks per host frame. `act()` runs a state action
then flushes one frame without moving host time. `reset()` remounts while time
remains monotonic; `dispose()` is idempotent and restores the previous driver.

The harness requires an isolated Pibbl realm and rejects creation while another
Pibbl root is mounted, because Pibbl has one realm scheduler. See the
[2D physics guide](/guides/physics-2d/) for the public world and handle
API under test.

## API details from source

<span id="api-createPhysicsTestHarness2D"></span>

Creates an isolated manual-clock test mount for one Pibbl 2D physics composition.

It refuses a realm with an existing root because a Pibbl realm deliberately has
one scheduler. Use ordinary browser tests when a test needs multiple roots.

```ts
createPhysicsTestHarness2D: <Observation>(options: PibblPhysicsTestHarness2DOptions<Observation>) => PibblPhysicsTestHarness2D<Observation>
```

Related API: [createPhysicsTestHarness2D](/reference/functions/physics-2d-testing/), [PibblPhysicsTestHarness2DOptions](/reference/types/physics-2d-testing/#pibblphysicstestharness2doptions), [PibblPhysicsTestHarness2D](/reference/types/physics-2d-testing/#pibblphysicstestharness2d).

### Parameters

- **`options`** — Caller-owned canvas, root factory, and semantic state observer. See
[PibblPhysicsTestHarness2DOptions](/reference/types/physics-2d-testing/#pibblphysicstestharness2doptions) .

### Returns

A harness owning the test mount and scheduler lifetime; dispose it after use. See
[PibblPhysicsTestHarness2D](/reference/types/physics-2d-testing/#pibblphysicstestharness2d) .

### See also

[PibblPhysicsTestHarness2DOptions](/reference/types/physics-2d-testing/#pibblphysicstestharness2doptions)

[PibblPhysicsTestHarness2D](/reference/types/physics-2d-testing/#pibblphysicstestharness2d)

[View source — packages/core/src/features/physics/2d-testing.ts:90](/source/packages/core/src/features/physics/2d-testing-ts/#L90)

## Implementation guidance for agents

Read the [Physics and geometry companion](/agents/topics/physics/) for ownership, adaptation, failure modes, and verification. [Agent start](/agents/) provides the version-selection workflow.

## Complete minimal examples

- [Deterministic physics test](/minimal-examples/physics/testing-harness/): Advance a public physics scene through controlled host frames. [Plain source](/minimal/physics/testing-harness.tsx)
## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
