# `testing.createFakeSession`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `testing.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Function · `import { createFakeSession } from '@holostep-configurators/runtime-client/testing';` · stable · since 2.0.0 · section 24. /testing

A fake session: the runtime's own implementation of the spec's section 6 tables, without a
renderer. Use it in unit tests and to run the examples in this file. `root` loads on the fake
clock, as the page's first [`setSceneModel`](Writer.setSceneModel.md) does: until it commits, a rule matches nothing yet
(`pending`, `matched` 0), and [`idle()`](Session.idle.md) settles only as `tick` moves the clock, so a test pumps
`tick(16)` with an `await` between ticks until [`idle()`](Session.idle.md) settles, then writes.
Errors: the options are checked at the call, nested ones included (`profile`, each `models`
entry with its nodes, clips and load, each `assets` entry): a field the declaration doesn't
have throws HoloInputError 'unknown-field' with `didYouMean`, a malformed value (a node
without a string `name`, a `parent` naming no entry or a name two entries share, a `tier` or AR mode the profile doesn't
know) 'invalid-input'.

## Declaration

```ts
export function createFakeSession(options?: FakeSessionOptions): FakeSession;
```

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/24-createFakeSession.ts`):

```ts
import { createFakeSession } from '@holostep-configurators/runtime-client/testing';
import type { IModelNode, Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const chair: IModelNode;                           // glbUrl 'chair.glb'
const fake = createFakeSession({
  models: {
    'chair.glb': {
      nodes: [{ name: 'Chair' }, { name: 'Seat', parent: 'Chair', mesh: true, slot: 'fabric' }],
    },
  },
  root: [chair],
});
let loaded = false;
void fake.idle().then(() => (loaded = true));
for (let i = 0; i < 100 && !loaded; i++) {
  fake.tick(16);                                           // the load, then the frame
  await new Promise((resolve) => setTimeout(resolve, 0));  // continuations run
}
const r = await fake.find({ node: chair.nodeId, slot: 'fabric' }).set({ visible: false });
fake.frame();                                              // present and dispatch
if (r.matched !== 1 || fake.problems().length > 0) {
  throw new Error('the seat rule did not apply cleanly');
}
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `createFakeSession` names no product |
| 2. A precedent | not recorded: no ledger row (coverage.json) names this member or its owner |
| 3. Two apps, or labs | not recorded: no ledger row names this member or its owner |
| 4. The cheaper fix first | not recorded per member (Appendix B decides it per need) |
