Skip to main content
On this pageFunctions

Scene

Functions

altText

functionsource
/** Creates a Locator that finds an element by its `alt` attribute. */
(altValue: string): Locator

blur

functionsource
/** Simulates a blur event on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>

click

functionsource
/**
 * 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>

displayValue

functionsource
/** Creates a Locator that finds a form control by its current `value`. */
(valueString: string): Locator

doubleClick

functionsource
/** Simulates a double-click on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>

expect

functionsource

expectAll

functionsource

first

functionsource
/** Picks the first match from a LocatorAll, producing a single-match Locator. */
(locatorAll: LocatorAll): Locator

focus

functionsource
/** Simulates a focus event on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>

getAllByAltText

functionsource
/** Finds all elements with the given `alt` attribute. */
(altValue: string): (html: VNode) => readonly Array<VNode>

getAllByDisplayValue

functionsource
/** Finds all form controls whose current value matches. */
(displayValueString: string): (html: VNode) => readonly Array<VNode>

getAllByLabel

functionsource
/**
 * 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>

getAllByPlaceholder

functionsource
/** Finds all elements with the given placeholder attribute. */
(placeholderValue: string): (html: VNode) => readonly Array<VNode>

getAllByRole

functionsource
/** 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>

getAllByTestId

functionsource
/** Finds all elements with the given `data-testid` attribute. */
(testIdValue: string): (html: VNode) => readonly Array<VNode>

getAllByText

functionsource
/**
 * 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>

getAllByTitle

functionsource
/** Finds all elements with the given `title` attribute. */
(titleValue: string): (html: VNode) => readonly Array<VNode>

getByAltText

functionsource
/** Finds the first element with the given `alt` attribute. */
(altValue: string): (html: VNode) => Option<VNode>

getByDisplayValue

functionsource
/**
 * Finds the first form control whose current value matches. Checks the `value`
 *  attribute on inputs, textareas, and selects.
 */
(displayValue: string): (html: VNode) => Option<VNode>

getByLabel

functionsource
/**
 * 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>

getByPlaceholder

functionsource
/** Finds the first element with the given placeholder attribute. */
(placeholderValue: string): (html: VNode) => Option<VNode>

getByRole

functionsource
/**
 * 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>

getByTestId

functionsource
/** Finds the first element with the given `data-testid` attribute. */
(testIdValue: string): (html: VNode) => Option<VNode>

getByText

functionsource
/**
 * 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>

getByTitle

functionsource
/** Finds the first element with the given `title` attribute. */
(titleValue: string): (html: VNode) => Option<VNode>

hover

functionsource
/**
 * 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>

inside

functionsource
/**
 * 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>

label

functionsource
/** Creates a Locator that finds an element by aria-label. */
(labelValue: string): Locator

last

functionsource
/** Picks the last match from a LocatorAll, producing a single-match Locator. */
(locatorAll: LocatorAll): Locator

placeholder

functionsource
/** Creates a Locator that finds an element by placeholder attribute. */
(placeholderValue: string): Locator

resolveAll

functionsource
/** Resolves all listed Commands with their result Messages. Handles cascading resolution. */
(pairs: readonly Array<ResolverPair>): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>

role

functionsource
/**
 * 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

selector

functionsource
/**
 * Creates a Locator that wraps a CSS selector. Escape hatch for cases
 *  where no accessible attribute is available.
 */
(css: string): Locator

submit

functionsource
/** Simulates form submission on the element matching the target. */
(target: string | Locator): (simulation: SceneSimulation<Model, Message, OutMessage>) => SceneSimulation<Model, Message, OutMessage>

tap

functionsource
/** 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>

testId

functionsource
/** Creates a Locator that finds an element by its `data-testid` attribute. */
(testIdValue: string): Locator

text

functionsource
/** Creates a Locator that finds the most specific element matching the given text content. */
(
  target: string,
  options?: Readonly<{
    exact: boolean
  }>
): Locator

textContent

functionsource
/** Extracts all text content from a VNode tree, depth-first. */
(vnode: VNode): string

title

functionsource
/** Creates a Locator that finds an element by its `title` attribute. */
(titleValue: string): Locator

with

functionsource
/** Sets the initial Model for a scene test. */
<Model>(model: Model): WithStep<Model>

Types

AnyCommand

typesource
/** A Command in a test simulation, identified by name. */
type AnyCommand = Readonly<{
  name: string
}>

Locator

typesource
/**
 * 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
}>

LocatorAll

typesource
/**
 * 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
}>

ResolverPair

typesource
/** A Command definition paired with the result Message to resolve it with. */
type ResolverPair = readonly [CommandDefinition<Name, ResultMessage>, ResultMessage]

SceneSimulation

typesource
/**
 * 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
}>

SceneStep

typesource
/** 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>

Constants

all

constsource
/**
 * 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
}

attr

constsource
/** Reads an attribute or prop value from a VNode. */
const attr: (vnode: VNode, name: string) => Option<string>

change

constsource
/**
 * 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>

filter

constsource
/**
 * 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

find

constsource
/** Finds the first VNode matching the CSS selector. */
const find: (html: VNode, selectorString: string) => Option<VNode>

findAll

constsource
/** Finds all VNodes matching the CSS selector. */
const findAll: (html: VNode, selectorString: string) => readonly Array<VNode>

keydown

constsource
/**
 * 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>

nth

constsource
/** Picks the nth match (0-indexed) from a LocatorAll, producing a Locator. */
const nth: (locatorAll: LocatorAll, index: number) => Locator

resolve

constsource
/** 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>

scene

constsource
/** 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

sceneMatchers

constsource
/** 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
}

type

constsource
/**
 * 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>

within

constsource
/**
 * Creates a scoped Locator that finds the child within the parent.
 *  Composes via `Option.flatMap` — the parent is resolved first, then
 *  the child is searched within the parent's subtree.
 */
const within: (parent: Locator, child: Locator) => Locator

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson