plushie/testing
Test facade for plushie applications.
Provides a unified test API that works on both BEAM and JS targets.
The backend is resolved once at start and carried through the
TestContext, so there are no repeated env lookups or backend construction.
BEAM target
Tests run against the real plushie-renderer binary. Set
PLUSHIE_TEST_BACKEND to choose the backend:
gleam test # default: mock
PLUSHIE_TEST_BACKEND=headless gleam test # software rendering
Default: mock (real binary in --mock mode, sessions pooled).
JavaScript target
Tests run the app’s init/update/view cycle in-memory via the pure session runner. No renderer binary is needed. Widget interactions construct events directly.
Usage
let ctx = testing.start(my_app())
let ctx = testing.click(ctx, "increment")
let assert option.Some(el) = testing.find(ctx, "count")
should.equal(element.text(el), option.Some("Count: 1"))
testing.stop(ctx)
Types
A test context: bundles the session with its backend.
Created by start, threaded through all test operations.
The backend is resolved once at startup, not on every call.
pub opaque type TestContext(model)
Values
pub fn advance_frame(
ctx: TestContext(model),
timestamp: Int,
) -> TestContext(model)
Dispatch an AnimationFrame event to advance frame-based animations.
This works with the mock and session backends. On headless/windowed backends, the renderer generates its own animation frames and this function has no effect.
pub fn assert_a11y(
ctx: TestContext(model),
selector: String,
expected: List(#(String, node.PropValue)),
) -> TestContext(model)
Assert that a widget’s resolved a11y contains all expected keys.
Reads through resolved_a11y so inferred defaults
(placeholder -> description, alt -> label) compose with the
author’s explicit overrides.
pub fn assert_exists(
ctx: TestContext(model),
selector: String,
) -> TestContext(model)
Assert that an element with the given selector exists.
pub fn assert_not_exists(
ctx: TestContext(model),
selector: String,
) -> TestContext(model)
Assert that no element with the given selector exists.
pub fn assert_text(
ctx: TestContext(model),
selector: String,
expected: String,
) -> TestContext(model)
Assert that an element’s text matches the expected value.
pub fn canvas_press(
ctx: TestContext(model),
id: String,
x: Float,
y: Float,
) -> TestContext(model)
Simulate a mouse press on a canvas widget at (x, y) coordinates.
pub fn canvas_touch_move(
ctx: TestContext(model),
id: String,
x: Float,
y: Float,
finger: Int,
) -> TestContext(model)
Simulate a touch move on a canvas widget at (x, y) with a finger index.
pub fn canvas_touch_press(
ctx: TestContext(model),
id: String,
x: Float,
y: Float,
finger: Int,
) -> TestContext(model)
Simulate a touch press on a canvas widget at (x, y) with a finger index.
pub fn canvas_touch_release(
ctx: TestContext(model),
id: String,
x: Float,
y: Float,
finger: Int,
) -> TestContext(model)
Simulate a touch release on a canvas widget at (x, y) with a finger index.
pub fn click(
ctx: TestContext(model),
id: String,
) -> TestContext(model)
Simulate a click on a widget by ID.
pub fn diagnostics(ctx: TestContext(model)) -> List(String)
Get diagnostic events from the test context. This is a placeholder that returns an empty list; it will be expanded when runtime telemetry diagnostic interception is added.
pub fn element_children(
el: element.Element,
) -> List(element.Element)
Get an element’s children.
pub fn element_prop(
el: element.Element,
key: String,
) -> option.Option(node.PropValue)
Get a prop value from an element.
pub fn element_text(el: element.Element) -> option.Option(String)
Extract text content from an element.
pub fn find(
ctx: TestContext(model),
selector: String,
) -> option.Option(element.Element)
Find an element by ID or selector string.
Accepts plain IDs (“save”), scoped IDs (“form/save”), window-qualified IDs (“main#save”), pseudo-selectors (“:focused”), and attribute selectors (“[role=button]”, “[text=Save]”).
Plain IDs delegate to the backend’s find function (which may query the renderer). Semantic selectors search the tree directly.
pub fn find_by(
ctx: TestContext(model),
selector: backend.Selector,
) -> option.Option(element.Element)
Find an element by a typed Selector.
Searches the current tree for text content, a11y role/label,
or focus state. For ID-based lookup, use find(ctx, "id").
testing.find_by(ctx, backend.ByRole("button"))
testing.find_by(ctx, backend.ByText("Save"))
testing.find_by(ctx, backend.Focused)
pub fn paste(
ctx: TestContext(model),
id: String,
text: String,
) -> TestContext(model)
Simulate pasting text into a widget by ID.
pub fn press_key(
ctx: TestContext(model),
key: String,
) -> TestContext(model)
Simulate a key press. Key string uses PascalCase wire format (e.g., “ArrowRight”, “Escape”, “Tab”) with optional modifier prefixes (“ctrl+s”, “shift+Tab”).
pub fn release_key(
ctx: TestContext(model),
key: String,
) -> TestContext(model)
Simulate a key release.
pub fn resolved_a11y(
ctx: TestContext(model),
selector: String,
) -> dict.Dict(String, node.PropValue)
Return the resolved a11y dict for a widget.
Layers render-pipeline inference (placeholder -> description for
text-entry widgets, alt -> label for media widgets) on top of the
normalized a11y prop so tests see what assistive technology will
see. Panics if the selector doesn’t match any widget.
pub fn select(
ctx: TestContext(model),
id: String,
value: String,
) -> TestContext(model)
Simulate selection on a widget by ID.
pub fn send_event(
ctx: TestContext(model),
event: event.Event,
) -> TestContext(model)
Dispatch a raw event through the update cycle.
pub fn slide(
ctx: TestContext(model),
id: String,
value: Float,
) -> TestContext(model)
Simulate a slider change by ID.
pub fn sort(
ctx: TestContext(model),
id: String,
column: String,
) -> TestContext(model)
Trigger sort on a table widget by ID and column name.
pub fn start(
app: app.App(model, event.Event),
) -> TestContext(model)
Start a test session for a simple app (msg = Event).
On BEAM, requires the plushie-renderer binary (panics with setup instructions if not found). On JS, runs in-memory.
pub fn submit(
ctx: TestContext(model),
id: String,
) -> TestContext(model)
Simulate form submission on a widget by ID.
pub fn toggle(
ctx: TestContext(model),
id: String,
) -> TestContext(model)
Simulate a checkbox/toggler toggle by ID.
pub fn type_key(
ctx: TestContext(model),
key: String,
) -> TestContext(model)
Simulate a key press and release.
pub fn type_text(
ctx: TestContext(model),
id: String,
text: String,
) -> TestContext(model)
Simulate text input on a widget by ID.