# zidane/extensions/testing

Import: `import { … } from 'zidane/extensions/testing'`. Source: [src/extensions/testing/index.ts](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/index.ts).

## Functions

### `createTestHost`

Function.

Loads `extensions` into an extension runtime wired to in-memory ports.

```ts
function createTestHost(options: TestHostOptions): Promise<TestHost>
```

**Parameters**

- `options` (`TestHostOptions`): The extensions, port overrides, starting settings and paths.

**Returns** `Promise<TestHost>`: The host, once every extension's `setup` settled.

**Example**

```ts
const host = await createTestHost({ extensions: [myExtension] })
await host.fire('turn:after', event)
expect(host.ui.items('slot')).toHaveLength(1)
await host.dispose()
```

Source: [src/extensions/testing/test-host.ts:239](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L239)

## Interfaces

### `TestHost`

Interface.

A loaded test host.

```ts
interface TestHost
```

**Properties**

- `commands` (`{ list: () => readonly { bind?: readonly string[]; id: string; slash?: string; title: string }[]; run: (id: string, opts?: { args?: string; sessionId?: string }) => Promise<boolean> }`, readonly): Runs commands by published id (`<extension>.<id>`).
- `ctx` (`<S extends SettingsSchema = SettingsSchema>(id: string) => ExtensionContext<S>`): The context the extension's `setup` received. Throws for an extension that did not run.
- `dialogs` (`ScriptedDialogPort`, readonly): The scripted dialog client: queue answers with `answer(kind, value)`; `shown` lists what was asked.
- `dispose` (`() => Promise<void>`): Unloads everything.
- `extensions` (`() => ExtensionInfo[]`): Every extension and its status.
- `facets` (`(session: TestSessionSnapshot, trigger?: SessionFacetTrigger) => Promise<Record<string, JsonValue>>`): Computes the facets for one session as a host would: the ones that run on
  `trigger`, or all of them. Fields the session leaves out get defaults
  (title = id, `cwd` = the host's, `status: 'idle'`, times 0, no metadata).
  The result is keyed `<extensionId>.<key>`; a facet that failed has no key.
- `fire` (`<K extends keyof AgentHooks | 'run:settled' | 'session:event'>(event: K, payload: HookEvents[K]) => Promise<void>`): Fires an agent hook or host event at the observers, then waits until they finished.
- `intercept` (`<K extends keyof Interceptors>(name: K, input: Interceptors[K][0], initial: Interceptors[K][1], opts?: { matchKey?: string }) => Promise<Interceptors[K][1]>`): Runs the interceptor chain of `name` and returns the result.
- `registry` (`ExtensionRuntimeOutputs`, readonly): The shared registries: catalogs, interceptors, UI, commands, RPC, contracts, integrations.
- `rpc` (`<C extends RpcContract<Readonly<Record<string, RpcMethodSpec>>, Readonly<Record<string, RpcEventSpec>>>>(contract: C) => RpcClient<C>`): A client for an RPC contract, calling as a separate test extension.
- `runtime` (`ExtensionRuntime`, readonly): The runtime (load, unload, reload, settings wire).
- `schedules` (`{ advance: (ms: number) => Promise<void>; now: () => number; readonly prompts: readonly { scheduleId: string; sessionId: string; text: string }[]; setEnabled: (on: boolean) => void; setTime: (epochMs: number) => Promise<void> }`, readonly): `ctx.schedules` runs on an in-memory scheduler with a clock the test
  moves: `advance(ms)` (or `setTime(epochMs)`) moves it and runs every
  fire that came due, `onFire` handlers included, then resolves. A
  schedule's prompt goes to `prompts` (no session runs). Reminders are on;
  `setEnabled(false)` turns them off.
- `sessions` (`(rows: readonly TestSessionRow[]) => void`): Replaces the sessions `ctx.sessions.list` answers from, so a test can
  check a query (a `Space` query, a filter) the way a host runs it: the
  same evaluator (`querySessions`), the same paging and archive scope.
  Fields a row leaves out get the defaults of `TestHost.facets`, plus
  `worker: false` and `facets: {}`. Until called, the list is empty.
  The rest of `ctx.sessions` (create, send, ...) rejects unless
  `ports.host.sessions` is given, which replaces this.
- `settings` (`MemorySettingsPort`, readonly): The in-memory settings port (`put`, `read`).
- `settled` (`() => Promise<void>`): Waits until every async extension callback started so far has finished.
- `storage` (`MemoryStoragePort`, readonly): The in-memory storage port (`snapshot`, `remote`).
- `ui` (`{ readonly client: RecordingUiClientPort; items: <N extends keyof UiWireMap>(token: N) => readonly UiEntry<N>[]; snapshot: () => UiSnapshot }`, readonly): UI contributions as the hosts see them, and the recorded client calls.

Source: [src/extensions/testing/test-host.ts:72](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L72)

### `TestHostOptions`

Interface.

Options of [`createTestHost`](https://zidane.si/docs/reference/extensions-testing.md#createTestHost).

```ts
interface TestHostOptions
```

**Properties**

- `budget?` (`false | Partial<ErrorBudget>`): Guard error budget. Default: the runtime's.
- `extensions` (`readonly TestHostExtension[]`): The extensions, loaded in dependency order.
- `host?` (`ExtensionHostKind`): The host kind `ctx.app.host` reports. Default `'sdk'`.
- `onLog?` (`(record: { attrs: Readonly<Record<string, unknown>>; level: string; message: string }) => void`): Receives every log record (warnings, attributed errors).
- `paths?` (`Partial<ExtensionPaths>`): Paths handed to the extensions. Default: under the OS temp folder.
- `ports?` (`RuntimePorts`): Ports that replace the in-memory ones (storage, settings, dialogs and UI client stay reachable only when not replaced).
- `settings?` (`Readonly<Record<string, Readonly<Record<string, unknown>>>>`): Starting settings values in the `user` layer: `{ [extensionId]: { [key]: value } }`.
- `setupTimeoutMs?` (`number`): Bound of `setup`, in ms.

Source: [src/extensions/testing/test-host.ts:46](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L46)

## Types

### `TestHostExtension`

Type.

One extension to load: a definition, or a definition with where it came from.

```ts
type TestHostExtension =
  | ExtensionDefinition<any>
  | { definition: unknown; dir?: string; enabled?: boolean; source?: ExtensionSource }
```

Source: [src/extensions/testing/test-host.ts:41](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L41)

### `TestSessionRow`

Type.

A session for `TestHost.sessions`: an id, and any list-row fields the queries read.

```ts
type TestSessionRow = Partial<SessionListRow> & { id: string }
```

Source: [src/extensions/testing/test-host.ts:69](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L69)

### `TestSessionSnapshot`

Type.

A session for `TestHost.facets`: an id, and any snapshot fields the facets read.

```ts
type TestSessionSnapshot = Partial<SessionSnapshot> & { id: string }
```

Source: [src/extensions/testing/test-host.ts:66](https://github.com/Tahul/zidane/blob/main/src/extensions/testing/test-host.ts#L66)

## Re-exports

These names are documented on the entry point that owns them.

- [zidane/extensions](https://zidane.si/docs/reference/extensions.md): [`createMemorySettingsPort`](https://zidane.si/docs/reference/extensions.md#createMemorySettingsPort), [`createMemoryStoragePort`](https://zidane.si/docs/reference/extensions.md#createMemoryStoragePort), [`createRecordingUiClientPort`](https://zidane.si/docs/reference/extensions.md#createRecordingUiClientPort), [`createScriptedDialogPort`](https://zidane.si/docs/reference/extensions.md#createScriptedDialogPort), [`DialogAnswer`](https://zidane.si/docs/reference/extensions.md#DialogAnswer), [`MemorySettingsPort`](https://zidane.si/docs/reference/extensions.md#MemorySettingsPort), [`MemoryStoragePort`](https://zidane.si/docs/reference/extensions.md#MemoryStoragePort), [`RecordingUiClientPort`](https://zidane.si/docs/reference/extensions.md#RecordingUiClientPort), [`ScriptedDialogPort`](https://zidane.si/docs/reference/extensions.md#ScriptedDialogPort), [`UiClientCall`](https://zidane.si/docs/reference/extensions.md#UiClientCall)
