testing.FakeSessionOptions.profile ​

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.

Property of testing.FakeSessionOptions · stable · since 2.0.0

ts
profile?: {
  unsupported?: readonly Capability[];
  permits?: readonly string[];
  tier?: InfoReport['renderer']['tier'];
  linkedLights?: number;
  maxTextureSize?: number;
  arModes?: InfoReport['ar']['modes'];
  arPending?: boolean;
  arEscapeOnly?: boolean;
  arEnabled?: boolean;
  tryOn?: {
    kinds: readonly TryOnKind[];
    blocked?: 'switched-off' | 'unsupported';
    outcome?: 'launched' | 'camera-denied' | 'needs-tap' | 'error' | 'other';
    durationMs?: number;
  };
  problems?: ReadonlyArray<Omit<Problem, 'at' | 'docs'>>;
  session?: {
    accountId?: number;
    configuratorId?: string | null;
  };
};

The runtime, device and account the fake answers for (spec section 9.4). Unset, it is a full-featured desktop: supports(), has() true for each KnownCapability the fake builds (a member still to come, and an option the runtime takes its fallback for: false, as on the runtime), permits() false, tier 'high', 'ar:modes' answered. supports(), has(), permits(), the gated operations and info() read it alike; info().ar.enabled and info().document follow the applied documents, as in the runtime.

Default: {}

Fields ​

unsupported ​

ts
unsupported?: readonly Capability[];

Ids this runtime lacks: supports() and has() answer false for them.

Default: []

permits ​

ts
permits?: readonly string[];

Gated capabilities this account may use (permits()).

Default: []

tier ​

ts
tier?: InfoReport['renderer']['tier'];

info().renderer.tier.

Default: 'high'

linkedLights ​

ts
linkedLights?: number;

info().renderer.limits.linkedLights.

Default: the runtime's floor for every tier (spec section 5.15)

maxTextureSize ​

ts
maxTextureSize?: number;

info().device.maxTextureSize, px.

Default: 4096

arModes ​

ts
arModes?: InfoReport['ar']['modes'];

The device's AR modes at boot, as the runtime reads them: info().ar.fileModes is its native part, and info().ar.modes lists it without 'scene-viewer' while the committed product is encrypted with no public plain twin, as the runtime's (a call with an http(s) glbUrl opens Scene Viewer where this lists it).

Default: []

arPending ​

ts
arPending?: boolean;

info().ar.pending at boot; setArModes answers it.

Default: false

arEscapeOnly ​

ts
arEscapeOnly?: boolean;

The in-page route is the escape sheet only (an app shell not yet measured, a host's deny row; DL50): info().ar.modes lists 'webxr' as set in arModes, and activateAR() opens the sheet, resolving { launched: false, reason: 'unsupported' } with no 'ar:status' (the sheet is the message), 'webxr' still listed, as on the runtime.

Default: false

arEnabled ​

ts
arEnabled?: boolean;

info().ar.enabled: false is an account (or document) with AR off. info().ar.modes is then empty and activateAR() resolves { launched: false, reason: 'disabled' } with 'ar:status' 'disabled', as in the runtime.

Default: true

tryOn ​

ts
tryOn?: { … }

The account's try-on, so a wearable page tests its Try-on control. Unset, the account offers none: canTryOn() answers { available: false, kind: 'other', modes: [], reason: 'not-enabled' } and tryOn() resolves 'unavailable'. Set, canTryOn() follows the committed product's rig as the runtime does, re-read after each commit: the first enabled ModelNode with a stored tryOn record (a GroupNode's active child, by defaultNodeId) gives kind; a kind kinds lacks answers 'not-enabled', then blocked, then a kind with no tracker in this runtime (every kind but 'face' today) 'unsupported', then a node without a tryOnUrl and an approved rig of a format the runtime reads (tryOn.approved.format 1), or no such node, 'no-rig'; else { available: true, kind, modes: ['here', 'handoff'] } (blocked: 'unsupported' with such a rig lists ['handoff']). tryOn() then resolves as the runtime's: 'unavailable' (mode 'other'; 'unsupported' where canTryOn() says 'unsupported') when it can't open, 'unsupported' for ui: 'headless'; mode: 'handoff' opens where modes lists it and resolves { launched: true, mode: 'handoff', handoffUrl } after durationMs whatever outcome says (no camera opens here), its link returnUrl read against the page's address ('unsupported' with neither, as in Node); else outcome after durationMs; a call while one is open returns its Promise, endAR() closes it at once (durationMs the time it ran; an unlaunched outcome closes as 'other'), and an aborted signal rejects AbortError. No 'xr:start' or 'xr:end' fires (no camera opens). The profile's example runs a Try-on control.

Default: undefined (no try-on)

tryOn.kinds ​

ts
kinds: readonly TryOnKind[];

The kinds the account offers, its consent mode set.

tryOn.blocked ​

ts
blocked?: 'switched-off' | 'unsupported';

'switched-off' (Holostep switched try-on off) or 'unsupported' (this device: no camera, or the page blocks it).

Default: undefined (neither)

tryOn.outcome ​

ts
outcome?: 'launched' | 'camera-denied' | 'needs-tap' | 'error' | 'other';

How a try-on that opens ends: 'launched' (the camera picture showed), else the reason it closed without it.

Default: 'launched'

tryOn.durationMs ​

ts
durationMs?: number;

Fake-clock ms from the call to the close ('needs-tap' answers at once).

Default: 0

problems ​

ts
problems?: ReadonlyArray<Omit<Problem, 'at' | 'docs'>>;

Problems boot would record before it resolves, such as 'tenant-document-unavailable' (spec section 5.1): in problems() and info().problems from the start, and dispatched to no handler, as the runtime's are.

Default: []

session ​

ts
session?: { … }

info().session's ids.

Default: {}

session.accountId ​

ts
accountId?: number;

info().session.accountId.

Default: 0

session.configuratorId ​

ts
configuratorId?: string | null;

info().session.configuratorId.

Default: null

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-FakeSessionOptions.profile.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;
// A glasses page shows its Try-on button only where try-on can open, and tells the
// shopper when the camera was refused.
declare const aviator: IModelNode;  // glbUrl 'glasses.glb', an approved 'face' rig (tryOn, tryOnUrl)
const fake = createFakeSession({
  models: { 'glasses.glb': { nodes: [{ name: 'Frame', mesh: true }] } },
  root: [aviator],
  profile: { tryOn: { kinds: ['face'], outcome: 'camera-denied', durationMs: 400 } },
});
let loaded = false;
void fake.idle().then(() => (loaded = true));
for (let i = 0; i < 100 && !loaded; i++) {
  fake.tick(16);
  await new Promise((resolve) => setTimeout(resolve, 0));
}
export const button = { shown: fake.canTryOn?.().available === true };
const closed = fake.tryOn?.();
fake.tick(400);                                          // the shopper refuses the camera
export const report = await closed;
if (!button.shown || report?.reason !== 'camera-denied') {
  throw new Error('the Try-on control did not follow the account and the product');
}

Generic-API test (spec 3.1) ​

Rule Result
1. Neutral name pass: profile 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)