Skip to content

zidane/extensions/testing

import { … } from 'zidane/extensions/testing'src/extensions/testing/index.ts

Functions#

createTestHostFunction#

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

TypeScript
function createTestHost(options: TestHostOptions): Promise<TestHost>
Parameters
NameTypeDescription
optionsTestHostOptions

The extensions, port overrides, starting settings and paths.

Promise<TestHost>

The host, once every extension's setup settled.

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

src/extensions/testing/test-host.ts:239

Interfaces#

TestHostInterface#

A loaded test host.

TypeScript
interface TestHost
TestHost properties
NameTypeDescription
commandsreadonly{ list: () => readonly { bind?: readonly string[]; id: string; slash?: string; title: string }[]; run: (id: string, opts?: { args?: string; sessionId?: string }) => Promise<boolean> }

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.

dialogsreadonlyScriptedDialogPort

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.

registryreadonlyExtensionRuntimeOutputs

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.

runtimereadonlyExtensionRuntime

The runtime (load, unload, reload, settings wire).

schedulesreadonly{ 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> }

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.

settingsreadonlyMemorySettingsPort

The in-memory settings port (put, read).

settled() => Promise<void>

Waits until every async extension callback started so far has finished.

storagereadonlyMemoryStoragePort

The in-memory storage port (snapshot, remote).

uireadonly{ readonly client: RecordingUiClientPort; items: <N extends keyof UiWireMap>(token: N) => readonly UiEntry<N>[]; snapshot: () => UiSnapshot }

UI contributions as the hosts see them, and the recorded client calls.

src/extensions/testing/test-host.ts:72

TestHostOptionsInterface#

Options of createTestHost.

TypeScript
interface TestHostOptions
TestHostOptions properties
NameTypeDescription
budget?false | Partial<ErrorBudget>

Guard error budget. Default: the runtime's.

extensionsreadonly 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.

src/extensions/testing/test-host.ts:46

Types#

TestHostExtensionType#

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

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

src/extensions/testing/test-host.ts:41

TestSessionRowType#

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

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

src/extensions/testing/test-host.ts:69

TestSessionSnapshotType#

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

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

src/extensions/testing/test-host.ts:66

Re-exports#

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