On this pageFunctions
Scene
/** Simulates a blur event on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Simulates a click on the element matching the target.
* When the element has no click handler, the event bubbles up to the
* nearest ancestor with one — mirroring browser event propagation.
* When the element is a submit button (`<button>` with no type or
* `type="submit"`, `<input type="submit">`, `<input type="image">`) with no
* click handler in its ancestor chain, the click falls through to the
* `submit` handler of the nearest ancestor `<form>`.
*/
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Creates a Locator that finds a form control by its current `value`. */
(valueString: string): Locator/**
* Simulates a double-click on the element matching the target.
* When the element has no dblclick handler, the event bubbles up to the
* nearest ancestor with one — mirroring browser event propagation.
*/
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Picks the first match from a LocatorAll, producing a single-match Locator. */
(locatorAll: LocatorAll): Locator/** Simulates a focus event on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Finds all elements with the given `alt` attribute. */
(altValue: string): (html: VNode) => readonly Array<VNode>/** Finds all form controls whose current value matches. */
(displayValueString: string): (html: VNode) => readonly Array<VNode>/**
* Finds every element with the given label text. Applies the same four
* resolution strategies as `getByLabel` (`aria-label`, `<label for="id">`,
* `<label>` nesting, `aria-labelledby`) and returns deduplicated matches.
*/
(labelValue: string): (html: VNode) => readonly Array<VNode>/** Finds all elements with the given placeholder attribute. */
(placeholderValue: string): (html: VNode) => readonly Array<VNode>/** Finds all elements with the given ARIA role and optional matching options. */
(
role: string,
options?: Readonly<{
checked: boolean | "mixed"
disabled: boolean
expanded: boolean
level: number
name: string | RegExp
pressed: boolean | "mixed"
selected: boolean
}>
): (html: VNode) => readonly Array<VNode>/** Finds all elements with the given `data-testid` attribute. */
(testIdValue: string): (html: VNode) => readonly Array<VNode>/**
* Finds all elements matching the given text content.
* Includes nested ancestors — a `<div><p>hi</p></div>` with text "hi" yields both.
*/
(
target: string,
options?: Readonly<{
exact: boolean
}>
): (html: VNode) => readonly Array<VNode>/** Finds all elements with the given `title` attribute. */
(titleValue: string): (html: VNode) => readonly Array<VNode>/** Finds the first element with the given `alt` attribute. */
(altValue: string): (html: VNode) => Option<VNode>/**
* Finds the first form control whose current value matches. Checks the `value`
* attribute on inputs, textareas, and selects.
*/
(displayValue: string): (html: VNode) => Option<VNode>/**
* Finds the first element with the given label text. Checks `aria-label`
* first, then `<label for="id">` association, then `<label>` nesting,
* then `aria-labelledby` reverse lookup.
*/
(labelValue: string): (html: VNode) => Option<VNode>/** Finds the first element with the given placeholder attribute. */
(placeholderValue: string): (html: VNode) => Option<VNode>/**
* Finds the first element with the given ARIA role and optional matching options.
* Supports `name` (accessible name), `level` (heading level), `checked`,
* `selected`, `pressed`, `expanded`, and `disabled` state filters.
*/
(
role: string,
options?: Readonly<{
checked: boolean | "mixed"
disabled: boolean
expanded: boolean
level: number
name: string | RegExp
pressed: boolean | "mixed"
selected: boolean
}>
): (html: VNode) => Option<VNode>/** Finds the first element with the given `data-testid` attribute. */
(testIdValue: string): (html: VNode) => Option<VNode>/**
* Finds the most specific element matching the given text content.
* Skips text VNodes (sel undefined) — only returns actual DOM elements.
*/
(
target: string,
options?: Readonly<{
exact: boolean
}>
): (html: VNode) => Option<VNode>/** Finds the first element with the given `title` attribute. */
(titleValue: string): (html: VNode) => Option<VNode>/**
* Simulates a hover (mouseenter) on the element matching the target.
* Dispatches the `mouseenter` handler, falling back to `mouseover`.
*/
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Scopes a sequence of steps to a parent element. Every Locator referenced by
* child steps — assertions, interactions — resolves within the parent's subtree.
* Use this when several steps share the same scope. For a single scoped query,
* prefer `within(parent, child)` directly. Nested `inside` calls compose scopes
* via `within(outer, inner)`.
*/
<Model, Message, OutMessage = undefined>(
parent: Locator,
steps: readonly Array<NoInfer<SceneStep<Model, Message, OutMessage>>>
): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Picks the last match from a LocatorAll, producing a single-match Locator. */
(locatorAll: LocatorAll): Locator/** Creates a Locator that finds an element by placeholder attribute. */
(placeholderValue: string): Locator/**
* Simulates a pointerdown event on the element matching the target.
* When the element has no pointerdown handler, the event bubbles up to
* the nearest ancestor with one — mirroring browser event propagation.
* Defaults to `pointerType: 'mouse'`, `button: 0`, and `screenX/screenY: 0`.
*/
(
target: string | Locator,
options?: Readonly<{
button: number
clientX: number
clientY: number
pointerType: string
screenX: number
screenY: number
}>
): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Simulates a pointerup event on the element matching the target.
* When the element has no pointerup handler, the event bubbles up to
* the nearest ancestor with one — mirroring browser event propagation.
* Defaults to `pointerType: 'mouse'` and `screenX/screenY: 0`.
*/
(
target: string | Locator,
options?: Readonly<{
pointerType: string
screenX: number
screenY: number
}>
): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Creates a Locator that finds an element by ARIA role. Supports matching on
* `name`, `level`, `checked`, `selected`, `pressed`, `expanded`, and `disabled`.
*/
(
roleValue: string,
options?: Readonly<{
checked: boolean | "mixed"
disabled: boolean
expanded: boolean
level: number
name: string | RegExp
pressed: boolean | "mixed"
selected: boolean
}>
): Locator/**
* Creates a Locator that wraps a CSS selector. Escape hatch for cases
* where no accessible attribute is available.
*/
(css: string): Locator/** Simulates form submission on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Runs a function for side effects (e.g. assertions) without breaking the step chain. */
<Model, Message, OutMessage = undefined>(f: (simulation: SceneSimulation<Model, Message, OutMessage>) => void): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Creates a Locator that finds an element by its `data-testid` attribute. */
(testIdValue: string): Locator/** Creates a Locator that finds the most specific element matching the given text content. */
(
target: string,
options?: Readonly<{
exact: boolean
}>
): Locator/** Creates a Locator that finds an element by its `title` attribute. */
(titleValue: string): Locator/**
* A Command in a test simulation. Carries `name` and optionally the `args`
* the runtime captured at construction. Instance matchers (Command values
* produced by calling a Definition) are matched against this shape; the
* `effect` field on a real Command is irrelevant for matching, so we only
* retain `name + args`.
*/
type AnyCommand = Readonly<{
args: Record<string, unknown>
name: string
}>/**
* A Mount lifecycle event in a test simulation. Carries `name` and
* optionally the `args` used to construct the MountAction. Mirrors
* `AnyCommand` for Mount matchers.
*/
type AnyMount = Readonly<{
args: Record<string, unknown>
name: string
}>/**
* A deferred element query that resolves against a VNode tree. Callable as a
* function (`locator(html)`) so it composes directly in `flow` and `pipe` chains.
* Used by interaction steps (`click`, `type`, `submit`, `keydown`) to
* target elements by accessible attributes instead of CSS selectors.
*/
type Locator = (html: VNode) => Option.Option<VNode> & Readonly<{
description: string
}>/**
* A deferred multi-element query that resolves to all matching VNodes.
* Produced by `all*` locator factories and by `filter(...)`. Convert to a
* single-match `Locator` via `first`, `last`, or `nth(n)`.
*/
type LocatorAll = (html: VNode) => ReadonlyArray<VNode> & Readonly<{
description: string
}>/**
* Pattern for matching a pending Mount in test assertions. A Definition
* matches by name only ("a Mount with this identity is in the rendered
* tree"); an Instance matches by name AND structural-equal args ("a Mount
* with this identity AND these args"). Choose the form per assertion based
* on whether the test cares about the args value.
*
* Two modes only: name-only or name + full args. Partial-args matching is
* intentionally unsupported, mirroring `CommandMatcher`.
*/
type MountMatcher = MountDefinition<string, unknown> | AnyMount/**
* A Mount matcher (Definition or Instance) with the result Message to
* resolve it with. Mirrors `Resolver` for Commands. The optional third
* element lifts a child Mount result into the parent's Message universe
* (mirrors `Mount.mapMessage`).
*/
type MountResolver = readonly [MountMatcher, ResultMessage] | readonly [MountMatcher, ResultMessage, (message: ResultMessage) => unknown]/**
* A pending Mount in a Scene simulation. Identified by `name` and an
* `occurrence` index that disambiguates same-named mounts in the rendered
* tree (e.g. two open popovers each contributing an `AnchorPopover`). The
* occurrence is the 0-based position among same-named markers in
* tree-traversal order. `args` carries the runtime values used to construct
* the MountAction when its definition declared an args record.
*/
type PendingMount = Readonly<{
args: Record<string, unknown>
name: string
occurrence: number
}>/**
* A Command matcher (Definition or Instance) with the result Message to
* resolve a pending Command with. Definition matchers resolve by name; an
* Instance matcher resolves only the pending Command whose name AND args
* match.
*/
type Resolver = readonly [CommandMatcher, ResultMessage] | readonly [CommandMatcher, ResultMessage, (message: ResultMessage) => unknown]/**
* An immutable test simulation that includes the rendered VNode tree.
* The Model and Message are intentionally opaque — Scene tests assert
* through the view, not the model. Use Story for model-level assertions.
*/
type SceneSimulation = Readonly<{
commands: ReadonlyArray<AnyCommand>
html: VNode
mounts: ReadonlyArray<PendingMount>
outMessage: OutMessage
}>/** A single step in a scene — either a `with` step or a scene simulation transform. */
type SceneStep = WithStep<NoInfer<Model>> | (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Steps that operate on the pending Commands of a scene simulation.
* Destructure as `const { Command } = Scene` for concise call sites.
*/
const Command: {
expectExact: (matchers: readonly Array<CommandMatcher>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
expectHas: (matchers: readonly Array<CommandMatcher>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
expectNone: () => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
resolve: (definition: CommandDefinition<Name, ResultMessage>, resultMessage: ResultMessage) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
resolveAll: (resolvers: {
[K in string | number | symbol]: Resolver<R[K]>
}) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
}/**
* Steps that operate on the pending Mounts of a scene simulation.
* Destructure as `const { Mount } = Scene` for concise call sites.
*/
const Mount: {
expectEnded: (matchers: readonly Array<MountMatcher>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
expectExact: (matchers: readonly Array<MountMatcher>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
expectHas: (matchers: readonly Array<MountMatcher>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
expectNone: () => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
resolve: (matcher: Readonly<{
args: Record<string, unknown>
name: string
}> | MountDefinition<Name, ResultMessage>, resultMessage: ResultMessage) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
resolveAll: (resolvers: {
[K in string | number | symbol]: MountResolver<R[K]>
}) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>
}/**
* Multi-match Locator factories. Each returns a `LocatorAll` that resolves
* to every matching VNode. Convert to a single `Locator` via `first`,
* `last`, or `nth(n)`, or narrow via `filter`.
*/
const all: {
altText: (altValue: string) => LocatorAll
displayValue: (valueString: string) => LocatorAll
label: (labelValue: string) => LocatorAll
placeholder: (placeholderValue: string) => LocatorAll
role: (roleValue: string, options?: Readonly<{
checked: boolean | "mixed"
disabled: boolean
expanded: boolean
level: number
name: string | RegExp
pressed: boolean | "mixed"
selected: boolean
}>) => LocatorAll
selector: (css: string) => LocatorAll
testId: (testIdValue: string) => LocatorAll
text: (target: string, options?: Readonly<{
exact: boolean
}>) => LocatorAll
title: (titleValue: string) => LocatorAll
}/** Reads an attribute or prop value from a VNode. */
const attr: (vnode: VNode, name: string) => Option<string>/**
* Simulates a change event on the element matching the target.
* Dual: `change(target, value)` or `change(value)` for data-last piping.
*/
const change: (target: string | Locator, value: string) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Simulates a file input change event on the element matching the target.
* For use with `OnFileChange` attributes. The handler receives a synthetic
* event with `target.files` set to the provided files array.
* Dual: `changeFiles(target, files)` or `changeFiles(files)` for data-last piping.
*/
const changeFiles: (target: string | Locator, files: readonly Array<File>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Simulates a drop event with files on the element matching the target.
* For use with `OnDropFiles` attributes. The handler receives a synthetic
* event with `dataTransfer.files` set to the provided files array and a
* no-op `preventDefault`.
* Dual: `dropFiles(target, files)` or `dropFiles(files)` for data-last piping.
*/
const dropFiles: (target: string | Locator, files: readonly Array<File>) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/**
* Filters a LocatorAll's matches. Supports `has`/`hasNot` to keep entries
* that do/don't contain a matching descendant, and `hasText`/`hasNotText`
* to keep entries whose text content does/doesn't include a substring.
*/
const filter: (locatorAll: LocatorAll, options: FilterOptions) => LocatorAll/** Finds the first VNode matching the CSS selector. */
const find: (html: VNode, selectorString: string) => Option<VNode>/** Finds all VNodes matching the CSS selector. */
const findAll: (html: VNode, selectorString: string) => readonly Array<VNode>/**
* Simulates a keydown event on the element matching the target.
* Dual: `keydown(target, key, modifiers?)` or `keydown(key, modifiers?)` for data-last piping.
*/
const keydown: (target: string | Locator, key: string) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** Picks the nth match (0-indexed) from a LocatorAll, producing a Locator. */
const nth: (locatorAll: LocatorAll, index: number) => Locator/** Executes a scene test. Throws if any Commands remain unresolved. */
const scene: (config: Readonly<{
update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<AnyCommand>, OutMessage]
view: (model: Model) => Html | Document
}>, steps: readonly Array<SceneStep<Model, Message, OutMessage>>) => void/** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
const sceneMatchers: {
toBeAbsent: unknown
toBeChecked: unknown
toBeDisabled: unknown
toBeEmpty: unknown
toBeEnabled: unknown
toBeVisible: unknown
toContainText: unknown
toExist: unknown
toHaveAttr: unknown
toHaveClass: unknown
toHaveHandler: unknown
toHaveHook: unknown
toHaveId: unknown
toHaveStyle: unknown
toHaveText: unknown
toHaveValue: unknown
}/**
* Simulates typing a value into the input matching the target.
* Dual: `type(target, value)` or `type(value)` for data-last piping.
*/
const type: (target: string | Locator, value: string) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>