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 is a submit button (`<button>` with no type or
* `type="submit"`, `<input type="submit">`, `<input type="image">`) with no
* click handler of its own, the click falls through to the `submit` handler
* of the nearest ancestor `<form>` — mirroring browser behavior.
*/
(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. */
(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
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
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/** Resolves all listed Commands with their result Messages. Handles cascading resolution. */
(pairs: readonly Array<ResolverPair>): (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
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, identified by name. */
type AnyCommand = Readonly<{
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
}>/** A Command definition paired with the result Message to resolve it with. */
type ResolverPair = readonly [CommandDefinition<Name, ResultMessage>, ResultMessage]/**
* 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
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>/**
* 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
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>/**
* 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/** Resolves a specific pending Command with the given result Message. */
const resolve: (definition: CommandDefinition<Name, ResultMessage>, resultMessage: ResultMessage) => (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>/** 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
}>, 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>