Plushie.Test.Helpers (Plushie v0.6.0)

Copy Markdown View Source

Test helper functions imported by Plushie.Test.Case.

These functions retrieve the current session from the process dictionary, so they can be called without passing a session explicitly.

Usage

These are automatically imported when using Plushie.Test.Case:

use Plushie.Test.Case, app: MyApp

test "example" do
  click("#my-button")
  assert model().count == 1
  assert_text("#label", "Count: 1")
end

They can also be used with an explicit session by calling through Plushie.Test.Session directly.

Summary

Functions

Advances the renderer animation clock, driving both SDK-side animation frame events and renderer-side transitions.

Asserts that a widget has the expected accessibility attributes.

Asserts that a widget exists in the tree.

Asserts that the current model equals expected.

Asserts that no prop validation diagnostics have been emitted.

Asserts that a widget does NOT exist in the tree.

Asserts that a widget has the expected accessibility role.

Captures a pixel screenshot and asserts it matches the golden file.

Asserts that an existing screenshot matches the golden file.

Asserts that a widget contains the expected text.

Captures a structural tree hash and asserts it matches the golden file.

Asserts that an existing tree hash matches the golden file.

Waits for a tagged async task to complete.

Moves on a canvas to the given coordinates.

Presses on a canvas at the given coordinates.

Releases on a canvas at the given coordinates.

Clicks a widget identified by selector.

Finds an element by selector. Returns nil if not found.

Finds an element by selector. Raises if not found.

Finds an element by its accessibility label. Returns nil if not found.

Finds an element by its accessibility role. Returns nil if not found.

Finds the currently focused element. Returns nil if none is focused.

Returns the current app model.

Moves the cursor to the given coordinates.

Cycles focus in a pane grid.

Pastes text into a widget.

Presses a key (key down). Key string may include modifiers, e.g. "ctrl+s".

Registers an effect stub with the renderer for the current session.

Releases a key (key up). Key string may include modifiers, e.g. "ctrl+s".

Resets the session to initial state.

Save a screenshot as a PNG file to test/screenshots/{name}.png.

Captures a pixel screenshot with the given name.

Scrolls a widget by the given deltas.

Selects a value from a pick_list, combo_box, or radio group.

Returns the current test session from the process dictionary.

Skips all active renderer-side transitions to completion.

Slides a slider to the given value.

Creates and registers a new test session for app.

Submits a text input (simulates pressing enter).

Extracts text content from an element.

Toggles a checkbox or toggler.

Returns the current normalized UI tree.

Captures a structural tree hash with the given name.

Types a key (press + release). Key string may include modifiers, e.g. "enter".

Types text into a widget identified by selector.

Removes a previously registered effect stub.

Functions

advance_frame(timestamp)

@spec advance_frame(timestamp :: non_neg_integer()) :: :ok

Advances the renderer animation clock, driving both SDK-side animation frame events and renderer-side transitions.

In mock mode this is a no-op for renderer-side transitions (they resolve instantly). In headless/windowed mode it advances the animation clock by the given timestamp.

Example

click("#toggle")
advance_frame(150)   # 150ms into the animation

assert_a11y(selector, expected)

(macro)

Asserts that a widget has the expected accessibility attributes.

Finds the widget by selector and checks that its a11y prop map contains all the expected key-value pairs.

assert_a11y("#heading", %{role: :heading, level: 1})

assert_exists(selector)

(macro)

Asserts that a widget exists in the tree.

assert_model(expected)

(macro)

Asserts that the current model equals expected.

Uses strict equality (==). Raises ExUnit.AssertionError with a diff- friendly message on mismatch.

assert_no_diagnostics()

@spec assert_no_diagnostics() :: :ok

Asserts that no prop validation diagnostics have been emitted.

Returns :ok if no diagnostics are pending. Raises ExUnit.AssertionError with the diagnostic details otherwise. Clears the diagnostic list after checking.

assert_not_exists(selector)

(macro)

Asserts that a widget does NOT exist in the tree.

assert_role(selector, expected_role)

(macro)

Asserts that a widget has the expected accessibility role.

Checks the inferred role (from widget type + any a11y override).

assert_role("#save-button", "button")
assert_role("#heading", "heading")

assert_screenshot(name, opts \\ [])

@spec assert_screenshot(name :: String.t(), opts :: keyword()) :: :ok

Captures a pixel screenshot and asserts it matches the golden file.

On first run, creates the golden file. On subsequent runs, compares hashes. Set PLUSHIE_UPDATE_SCREENSHOTS=1 to force-update golden files. No-op on backends that don't support pixel capture (empty hash is silently accepted).

assert_screenshot_match(screenshot, golden_dir)

@spec assert_screenshot_match(
  screenshot :: Plushie.Test.Screenshot.t(),
  golden_dir :: String.t()
) :: :ok

Asserts that an existing screenshot matches the golden file.

Use this when you already have a %Plushie.Automation.Screenshot{} and want the imported helper form instead of calling Plushie.Test.Screenshot.assert_match/2 directly.

assert_text(selector, expected)

(macro)

Asserts that a widget contains the expected text.

Finds the widget by selector and compares its text content.

assert_tree_hash(name)

@spec assert_tree_hash(name :: String.t()) :: :ok

Captures a structural tree hash and asserts it matches the golden file.

On first run, creates the golden file. On subsequent runs, compares hashes. Set PLUSHIE_UPDATE_SNAPSHOTS=1 to force-update golden files.

assert_tree_hash_match(tree_hash, golden_dir)

@spec assert_tree_hash_match(
  tree_hash :: Plushie.Test.TreeHash.t(),
  golden_dir :: String.t()
) :: :ok

Asserts that an existing tree hash matches the golden file.

Use this when you already have a %Plushie.Test.TreeHash{} and want the imported helper form instead of calling Plushie.Test.TreeHash.assert_match/2 directly.

await_async(tag, timeout \\ 5000)

@spec await_async(tag :: atom(), timeout :: non_neg_integer()) :: :ok

Waits for a tagged async task to complete.

canvas_move(selector, x, y, opts \\ [])

@spec canvas_move(
  selector :: Plushie.Test.Session.selector(),
  x :: number(),
  y :: number(),
  opts :: keyword()
) :: :ok

Moves on a canvas to the given coordinates.

Options

  • window: -- target window ID for multi-window apps

canvas_press(selector, x, y, button \\ "left", opts \\ [])

@spec canvas_press(
  selector :: Plushie.Test.Session.selector(),
  x :: number(),
  y :: number(),
  button :: String.t(),
  opts :: keyword()
) :: :ok

Presses on a canvas at the given coordinates.

Options

  • window: -- target window ID for multi-window apps

canvas_release(selector, x, y, button \\ "left", opts \\ [])

@spec canvas_release(
  selector :: Plushie.Test.Session.selector(),
  x :: number(),
  y :: number(),
  button :: String.t(),
  opts :: keyword()
) :: :ok

Releases on a canvas at the given coordinates.

Options

  • window: -- target window ID for multi-window apps

click(selector, opts \\ [])

@spec click(selector :: Plushie.Test.Session.selector(), opts :: keyword()) :: :ok

Clicks a widget identified by selector.

Options

  • window: -- target window ID for multi-window apps

find(selector)

@spec find(selector :: Plushie.Test.Session.selector()) ::
  Plushie.Automation.Element.t() | nil

Finds an element by selector. Returns nil if not found.

find!(selector)

Finds an element by selector. Raises if not found.

find_by_label(label)

@spec find_by_label(label :: String.t()) :: Plushie.Automation.Element.t() | nil

Finds an element by its accessibility label. Returns nil if not found.

find_by_role(role)

@spec find_by_role(role :: atom() | String.t()) ::
  Plushie.Automation.Element.t() | nil

Finds an element by its accessibility role. Returns nil if not found.

find_focused()

@spec find_focused() :: Plushie.Automation.Element.t() | nil

Finds the currently focused element. Returns nil if none is focused.

model()

@spec model() :: term()

Returns the current app model.

move_to(x, y)

@spec move_to(x :: number(), y :: number()) :: :ok

Moves the cursor to the given coordinates.

pane_focus_cycle(selector, opts \\ [])

@spec pane_focus_cycle(selector :: Plushie.Test.Session.selector(), opts :: keyword()) ::
  :ok

Cycles focus in a pane grid.

Options

  • window: -- target window ID for multi-window apps

paste(selector, text, opts \\ [])

@spec paste(
  selector :: Plushie.Test.Session.selector(),
  text :: String.t(),
  opts :: keyword()
) :: :ok

Pastes text into a widget.

Options

  • window: -- target window ID for multi-window apps

press(key)

@spec press(key :: String.t()) :: :ok

Presses a key (key down). Key string may include modifiers, e.g. "ctrl+s".

register_effect_stub(kind, response)

@spec register_effect_stub(kind :: Plushie.Effect.kind(), response :: term()) :: :ok

Registers an effect stub with the renderer for the current session.

The renderer will return response immediately for any effect of the given kind, without executing the real effect. The kind matches the effect function name as an atom (e.g. :file_open, :clipboard_write).

release(key)

@spec release(key :: String.t()) :: :ok

Releases a key (key up). Key string may include modifiers, e.g. "ctrl+s".

reset()

@spec reset() :: :ok

Resets the session to initial state.

save_screenshot(name, opts \\ [])

@spec save_screenshot(name :: String.t(), opts :: keyword()) ::
  Plushie.Test.Screenshot.t()

Save a screenshot as a PNG file to test/screenshots/{name}.png.

Takes a screenshot, saves it, and returns the screenshot struct. Creates the test/screenshots/ directory if it doesn't exist. No-op on backends that don't support pixel capture.

screenshot(name, opts \\ [])

@spec screenshot(name :: String.t(), opts :: keyword()) :: Plushie.Test.Screenshot.t()

Captures a pixel screenshot with the given name.

scroll(selector, delta_x \\ 0, delta_y \\ 0, opts \\ [])

@spec scroll(
  selector :: Plushie.Test.Session.selector(),
  delta_x :: number(),
  delta_y :: number(),
  opts :: keyword()
) :: :ok

Scrolls a widget by the given deltas.

Options

  • window: -- target window ID for multi-window apps

select(selector, value, opts \\ [])

@spec select(
  selector :: Plushie.Test.Session.selector(),
  value :: term(),
  opts :: keyword()
) :: :ok

Selects a value from a pick_list, combo_box, or radio group.

Options

  • window: -- target window ID for multi-window apps

session()

@spec session() :: Plushie.Test.Session.t()

Returns the current test session from the process dictionary.

skip_transitions()

@spec skip_transitions() :: :ok

Skips all active renderer-side transitions to completion.

Advances the animation clock far enough to complete any reasonable animation (10 seconds). Useful in tests that trigger animations but only care about the final state.

Example

click("#toggle")
skip_transitions()
assert find!("#box").props[:opacity] == 0.0

slide(selector, value, opts \\ [])

@spec slide(
  selector :: Plushie.Test.Session.selector(),
  value :: number(),
  opts :: keyword()
) :: :ok

Slides a slider to the given value.

Options

  • window: -- target window ID for multi-window apps

sort(selector, column, direction \\ "asc", opts \\ [])

@spec sort(
  selector :: Plushie.Test.Session.selector(),
  column :: String.t(),
  direction :: String.t(),
  opts :: keyword()
) :: :ok

Sorts a table column.

Options

  • window: -- target window ID for multi-window apps

start(app)

@spec start(app :: module()) :: Plushie.Test.Session.t()

Creates and registers a new test session for app.

Resolves the backend from PLUSHIE_TEST_BACKEND env var, application config, or defaults to :mock. Stores the session in the process dictionary so all helper functions work without explicit session threading.

Call this in a test or setup block when not using Plushie.Test.Case.

submit(selector, opts \\ [])

@spec submit(selector :: Plushie.Test.Session.selector(), opts :: keyword()) :: :ok

Submits a text input (simulates pressing enter).

Options

  • window: -- target window ID for multi-window apps

text(element)

@spec text(element :: Plushie.Automation.Element.t()) :: String.t() | nil

Extracts text content from an element.

toggle(selector, value \\ nil, opts \\ [])

@spec toggle(
  selector :: Plushie.Test.Session.selector(),
  value :: boolean() | nil,
  opts :: keyword()
) ::
  :ok

Toggles a checkbox or toggler.

Without a value, reads the current state and negates it. With an explicit boolean, sets the widget directly without reading state.

toggle("#dark_mode")          # flip current state
toggle("#agree_check", true)  # check
toggle("#agree_check", false) # uncheck

Options

  • window: -- target window ID for multi-window apps

tree()

@spec tree() :: map()

Returns the current normalized UI tree.

tree_hash(name)

@spec tree_hash(name :: String.t()) :: Plushie.Test.TreeHash.t()

Captures a structural tree hash with the given name.

type_key(key)

@spec type_key(key :: String.t()) :: :ok

Types a key (press + release). Key string may include modifiers, e.g. "enter".

type_text(selector, text, opts \\ [])

@spec type_text(
  selector :: Plushie.Test.Session.selector(),
  text :: String.t(),
  opts :: keyword()
) ::
  :ok

Types text into a widget identified by selector.

Options

  • window: -- target window ID for multi-window apps

unregister_effect_stub(kind)

@spec unregister_effect_stub(kind :: Plushie.Effect.kind()) :: :ok

Removes a previously registered effect stub.