pub struct Harness<A: App> { /* private fields */ }Expand description
A headless app under test. See the module docs for the model.
Implementations§
Source§impl<A: App> Harness<A>
impl<A: App> Harness<A>
Sourcepub fn new(app: A, theme: Theme, size: (u32, u32)) -> Self
pub fn new(app: A, theme: Theme, size: (u32, u32)) -> Self
Builds the first frame. App::init runs with a collecting
Proxy; proxied messages drain at every rebuild (after each
input, Self::pump, or Self::update).
§Panics
If no compute-capable GPU adapter exists.
Sourcepub fn rebuild(&mut self)
pub fn rebuild(&mut self)
Rebuilds every window from current app state (proxied messages
drain first) and reconciles the declared window set: new keys
open, missing keys close (the active window falls back to main).
Runs automatically after every input; call it yourself only
after mutating via Self::app_mut.
Sourcepub fn set_reduced_motion(&mut self, reduced: bool)
pub fn set_reduced_motion(&mut self, reduced: bool)
Enables or disables real animation. The harness defaults to
reduced motion (everything snaps — deterministic pixels); motion
tests opt into physics and drive it with Self::pump.
Sourcepub fn activate_window(&mut self, key: &str)
pub fn activate_window(&mut self, key: &str)
Switches which window the verbs and queries target. Open windows
come from App::windows; MAIN_WINDOW is always open.
§Panics
If no open window has this key (the message lists the open ones).
Sourcepub fn resize(&mut self, key: &str, width: u32, height: u32)
pub fn resize(&mut self, key: &str, width: u32, height: u32)
Resizes one window: clamps to the renderer’s limits, updates the slot’s
pixel and logical size, and rebuilds its frame via App::view_at at
the new size — the headless analogue of dragging a window edge, and how
view_at window breakpoints and
responsive container queries are driven.
Other windows are untouched.
§Panics
If no open window has this key.
Sourcepub fn window_keys(&self) -> Vec<String>
pub fn window_keys(&self) -> Vec<String>
The keys of every open window, sorted (main first).
Sourcepub fn input(&mut self, event: InputEvent)
pub fn input(&mut self, event: InputEvent)
Dispatches one raw input event against the active window’s current frame, logs and applies the emitted messages, and rebuilds (which also reconciles the window set).
Sourcepub fn hover(&mut self, q: &Query)
pub fn hover(&mut self, q: &Query)
Moves the pointer to the center of the matched node.
§Panics
If the query matches zero or several nodes.
Sourcepub fn click(&mut self, q: &Query)
pub fn click(&mut self, q: &Query)
Clicks (press + release) the center of the matched node.
§Panics
If the query matches zero or several nodes.
Sourcepub fn right_click(&mut self, q: &Query)
pub fn right_click(&mut self, q: &Query)
Sourcepub fn double_click(&mut self, q: &Query)
pub fn double_click(&mut self, q: &Query)
Double-clicks the matched node (two clicks inside the double-click window — the harness clock does not advance).
§Panics
If the query matches zero or several nodes.
Sourcepub fn triple_click(&mut self, q: &Query)
pub fn triple_click(&mut self, q: &Query)
Triple-clicks the matched node (text inputs select the line).
§Panics
If the query matches zero or several nodes.
Sourcepub fn shift_click(&mut self, q: &Query)
pub fn shift_click(&mut self, q: &Query)
Clicks with Shift held (text inputs extend the selection from the caret to the click point).
§Panics
If the query matches zero or several nodes.
Sourcepub fn type_text(&mut self, text: impl Into<String>)
pub fn type_text(&mut self, text: impl Into<String>)
Commits text to the focused element (like typing or IME commit).
Sourcepub fn drag(&mut self, from: &Query, to: &Query)
pub fn drag(&mut self, from: &Query, to: &Query)
Drags from one node to another: press on from, move to to
(recomputed after the press, in case layout shifted), release.
§Panics
If either query matches zero or several nodes.
Sourcepub fn wheel(&mut self, q: &Query, dy: f32)
pub fn wheel(&mut self, q: &Query, dy: f32)
Scrolls the wheel over the matched node (positive dy moves
content down, winit convention).
§Panics
If the query matches zero or several nodes.
Sourcepub fn wheel_xy(&mut self, q: &Query, dx: f32, dy: f32)
pub fn wheel_xy(&mut self, q: &Query, dx: f32, dy: f32)
Scrolls the wheel on both axes over the matched node (positive dx
moves content right, positive dy moves content down).
§Panics
If the query matches zero or several nodes.
Sourcepub fn pump(&mut self, ms: f64)
pub fn pump(&mut self, ms: f64)
Advances the deterministic clock by ms milliseconds and
rebuilds — animations and timers move exactly this far.
Sourcepub fn update(&mut self, msg: A::Msg)
pub fn update(&mut self, msg: A::Msg)
Applies one message directly (as a proxy or window event would)
and rebuilds. Not logged in Self::take_messages.
Sourcepub fn get(&self, q: &Query) -> AccessNode
pub fn get(&self, q: &Query) -> AccessNode
The single matching node; panics (with the accessibility tree in the message) on zero or several matches.
§Panics
If the query matches zero or several nodes.
Sourcepub fn query(&self, q: &Query) -> Option<AccessNode>
pub fn query(&self, q: &Query) -> Option<AccessNode>
The single matching node, or None. Use to assert absence.
§Panics
If the query matches several nodes.
Sourcepub fn get_all(&self, q: &Query) -> Vec<AccessNode>
pub fn get_all(&self, q: &Query) -> Vec<AccessNode>
Every matching node in tree order.
Sourcepub fn take_messages(&mut self) -> Vec<A::Msg>
pub fn take_messages(&mut self) -> Vec<A::Msg>
Messages emitted by handlers since the last call (the Elm-level
assertion: what the UI said, independent of state effects).
Proxied and Self::update messages are inputs, not logged.
Sourcepub fn frame(&self) -> &Frame
pub fn frame(&self) -> &Frame
The active window’s current frame, for direct queries and
access_yaml().
Sourcepub fn app_mut(&mut self) -> &mut A
pub fn app_mut(&mut self) -> &mut A
Mutable access to the app; call Self::rebuild afterwards.
Sourcepub fn render(&mut self) -> RgbaImage
pub fn render(&mut self) -> RgbaImage
Renders the active window to pixels. Mid-test captures are fine — the frame is not consumed.
§Panics
If rendering fails.
Sourcepub fn render_window(&mut self, key: &str) -> RgbaImage
pub fn render_window(&mut self, key: &str) -> RgbaImage
Sourcepub fn film(&mut self, frames: usize, interval_ms: u64) -> Vec<RgbaImage> ⓘ
pub fn film(&mut self, frames: usize, interval_ms: u64) -> Vec<RgbaImage> ⓘ
Captures frames renders of the active window, interval_ms apart on
the deterministic clock: the first frame is the window exactly as it
stands now, then Self::pump and Self::render repeat — so
film(3, 100) returns the states at +0ms, +100ms, +200ms.
Self::new defaults every harness to reduced motion, the same
default every other verification path relies on so single-shot
goldens stay stable — under it every transition snaps to its target
immediately, so a filmstrip captured without changing that is frames
copies of the same pixels. Call
Self::set_reduced_motion(false) first to see real motion play;
determinism still holds, because it comes from the clock (advanced
only by Self::pump), never from suppressing animation.
frames is floored at 1 and clamped to MAX_FILM_FRAMES;
interval_ms is clamped to MAX_FILM_INTERVAL_MS (see their docs).
§Panics
If rendering fails (see Self::render).
Auto Trait Implementations§
impl<A> !RefUnwindSafe for Harness<A>
impl<A> !Send for Harness<A>
impl<A> !Sync for Harness<A>
impl<A> !UnwindSafe for Harness<A>
impl<A> Freeze for Harness<A>where
A: Freeze,
impl<A> Unpin for Harness<A>
impl<A> UnsafeUnpin for Harness<A>where
A: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.