plushie/testing/renderer
Test renderer: OTP actor wrapping a Port to the Rust binary.
Provides bidirectional wire communication for renderer-backed test backends (headless and windowed). Handles the Elm loop: dispatches decoded events through update, processes commands, re-renders the view, and sends snapshots back to the renderer.
Request/response lifecycle
External callers send Call* messages (find, interact, tree_hash,
screenshot, reset) which include a reply Subject. The actor
assigns a unique request ID, sends a wire message to the Rust
binary, and stores a PendingEntry keyed by that ID. When the
Rust binary responds, the actor matches the response ID to the
pending map, replies to the caller, and removes the entry.
Pending map invariant: every entry in the pending map
corresponds to exactly one outstanding wire request. If the port
exits, all pending callers receive a ReplyError and the actor
stops. No request ID is ever reused.
Backends
Use headless mode (--headless args) for CI and screenshot tests
with software rendering. Use windowed mode for manual visual
verification. The mock backend does not use this actor at all –
it runs the Elm loop in pure Gleam without a port.
Types
Configuration for starting a renderer actor.
pub type RendererConfig {
RendererConfig(
args: List(String),
format: protocol.Format,
renderer_path: option.Option(String),
send_settings: Bool,
screenshot_size: option.Option(#(Int, Int)),
)
}
Constructors
-
RendererConfig( args: List(String), format: protocol.Format, renderer_path: option.Option(String), send_settings: Bool, screenshot_size: option.Option(#(Int, Int)), )Arguments
- args
-
Port arguments (e.g. [“–headless”] or [“–headless”, “–json”]).
- format
-
Wire format.
- renderer_path
-
Path to the plushie binary. None = auto-resolve.
- send_settings
-
Whether to send settings before the initial snapshot.
- screenshot_size
-
Screenshot dimensions for headless mode (None for windowed).
Messages the renderer actor handles.
pub opaque type RendererMessage
Reply values from the renderer actor.
pub type RendererReply {
ReplyElement(option.Option(element.Element))
ReplyTree(option.Option(dynamic.Dynamic))
ReplyOk
ReplyModel(dynamic.Dynamic)
ReplyTreeHash(tree_hash.TreeHash)
ReplyScreenshot(screenshot.Screenshot)
ReplyError(String)
}
Constructors
-
ReplyElement(option.Option(element.Element)) -
ReplyTree(option.Option(dynamic.Dynamic)) -
ReplyOk -
ReplyModel(dynamic.Dynamic) -
ReplyTreeHash(tree_hash.TreeHash) -
ReplyScreenshot(screenshot.Screenshot) -
ReplyError(String)
Convenience alias for the renderer actor’s Subject.
pub type RendererSubject =
process.Subject(RendererMessage)
Values
pub fn click(
subject: process.Subject(RendererMessage),
selector: String,
) -> Nil
Click on an element identified by selector.
pub fn find(
subject: process.Subject(RendererMessage),
selector: String,
) -> option.Option(element.Element)
Find an element by selector string.
pub fn get_screenshot(
subject: process.Subject(RendererMessage),
name: String,
) -> screenshot.Screenshot
Capture a screenshot from the renderer.
pub fn get_tree(
subject: process.Subject(RendererMessage),
) -> option.Option(dynamic.Dynamic)
Get the raw tree from the renderer.
pub fn get_tree_hash(
subject: process.Subject(RendererMessage),
name: String,
) -> tree_hash.TreeHash
Get a tree hash from the renderer.
pub fn model(
subject: process.Subject(RendererMessage),
) -> dynamic.Dynamic
Get the current model (returned as Dynamic – caller casts).
pub fn move_to(
subject: process.Subject(RendererMessage),
x: Float,
y: Float,
) -> Nil
Move the mouse pointer to absolute coordinates.
pub fn press(
subject: process.Subject(RendererMessage),
key: String,
) -> Nil
Press a key (no selector).
pub fn release(
subject: process.Subject(RendererMessage),
key: String,
) -> Nil
Release a key (no selector).
pub fn reset(subject: process.Subject(RendererMessage)) -> Nil
Reset the session to initial state.
pub fn select(
subject: process.Subject(RendererMessage),
selector: String,
value: String,
) -> Nil
Select a value on a picker/dropdown identified by selector.
pub fn slide(
subject: process.Subject(RendererMessage),
selector: String,
value: Float,
) -> Nil
Slide a slider to a value, identified by selector.
pub fn start(
app: app.App(model, event.Event),
config: RendererConfig,
) -> Result(process.Subject(RendererMessage), actor.StartError)
Start a renderer actor with the given app and config.
pub fn stop(subject: process.Subject(RendererMessage)) -> Nil
Stop a renderer actor by sending a normal exit to its process.
pub fn submit(
subject: process.Subject(RendererMessage),
selector: String,
) -> Nil
Submit a form element identified by selector.
pub fn toggle(
subject: process.Subject(RendererMessage),
selector: String,
) -> Nil
Toggle a checkbox/toggler identified by selector.
pub fn type_key(
subject: process.Subject(RendererMessage),
key: String,
) -> Nil
Press and release a key (no selector).
pub fn type_text(
subject: process.Subject(RendererMessage),
selector: String,
text: String,
) -> Nil
Type text into an element identified by selector.