Skip to main content

Harness

Struct Harness 

Source
pub struct Harness<A: App> { /* private fields */ }
Expand description

Runs an App against an in-memory screen.

Every input method renders afterwards, like the real runtime does. Work of Command::perform runs inline, one round per step like one pass of the terminal loop: work that performs again runs at the next step, so a chain of performs takes one Harness::render per link and an endless one never blocks a test.

Implementations§

Source§

impl<A: App> Harness<A>

Source

pub fn new(app: A, width: u16, height: u16) -> Self

A harness with the built-in environment and a width × height screen, already rendered.

The first frame starts the application as the terminal runtime does: the size reaches App::resized, then App::init runs, so the focus it asks for is in place before the first simulated key.

Source

pub fn with_env(app: A, env: Env, width: u16, height: u16) -> Self

A harness with a custom environment.

Source

pub fn render(&mut self) -> &mut Self

Paints the current view.

Source

pub fn send(&mut self, message: A::Msg) -> &mut Self

Delivers message to the application as if a widget had sent it, then renders.

Source

pub fn press(&mut self, chord: &str) -> &mut Self

Presses a key chord such as "ctrl+s", "tab" or "?".

Source

pub fn type_text(&mut self, text: &str) -> &mut Self

Types text one character at a time.

Source

pub fn events(&mut self, events: &[Event]) -> &mut Self

Delivers events in order at the current clock time and renders once afterwards, the way the terminal loop handles every event waiting between two frames. Widgets see the later events with what the earlier ones changed but the rects of the frame before, e.g. a click where a submenu was drawn that a key delivered in the same call already closed.

Source

pub fn paste(&mut self, text: &str) -> &mut Self

Pastes text.

Source

pub fn click(&mut self, x: i32, y: i32) -> &mut Self

Clicks the left button on a cell.

Source

pub fn click_text(&mut self, text: &str) -> &mut Self

Clicks the first cell of the first occurrence of text on screen.

§Panics

Panics when text is not on screen.

Source

pub fn drag(&mut self, from: (i32, i32), to: (i32, i32)) -> &mut Self

Presses the left button on from, drags to to and releases there.

Source

pub fn hover(&mut self, x: i32, y: i32) -> &mut Self

Moves the pointer to a cell.

Source

pub fn mouse(&mut self, kind: MouseKind, x: i32, y: i32) -> &mut Self

Sends a mouse event.

Source

pub fn advance(&mut self, duration: Duration) -> &mut Self

Moves the fake clock forward and renders. Idleness moves with it: what View::idle_for reads grows by duration, and a View::on_idle watch whose silence is reached is told. Every simulated input (a key, the mouse, a paste) starts the silence again; send, resize and theme or language changes do not.

A termination whose Termination::grace is over by then quits, as it does in the runtime.

Source

pub fn terminate(&mut self, cause: Termination) -> &mut Self

Simulates the signal behind cause, the way the terminal runtime hears a SIGTERM or a SIGHUP, then renders. The application hears it through App::terminating exactly as it would in a terminal, so a test can check its answer:

The harness keeps drawing after a hangup, so a test can still read the screen; the runtime stops drawing, since the terminal is gone.

use qframe::prelude::*;
use qframe::runtime::Termination;

struct Editor;

impl App for Editor {
    type Msg = ();
    fn update(&mut self, (): ()) -> Command<()> {
        Command::none()
    }
    fn view(&self, ui: &mut View<'_, ()>) {
        ui.add(Text::new("notes.md"));
    }
}

// An application that implements nothing quits cleanly on either signal.
let mut app = Harness::new(Editor, 20, 3);
app.terminate(Termination::Terminate);
assert!(app.quit_requested());
Source

pub fn key(&mut self, event: KeyEvent) -> &mut Self

Delivers a key event exactly as given, without moving the clock: a KeyKind::Repeat or KeyKind::Release from a terminal with the kitty keyboard protocol, or a press repeated by a held key.

Source

pub fn set_theme(&mut self, id: &str) -> &mut Self

Switches theme, as Command::set_theme would.

Source

pub fn set_locale(&mut self, code: &str) -> &mut Self

Switches language, as Command::set_locale would.

Source

pub fn set_reduced_motion(&mut self, reduced: bool) -> &mut Self

Turns reduced motion on or off.

Source

pub fn set_depth(&mut self, depth: ColorDepth) -> &mut Self

Draws as a terminal with depth colours would. Cells then carry palette indices instead of colours, which Harness::fg and Harness::bg cannot read; compare Harness::buffer cells for those.

Source

pub fn set_glyph_mode(&mut self, mode: GlyphMode) -> &mut Self

Switches the glyph column drawn.

Source

pub fn resize(&mut self, width: u16, height: u16) -> &mut Self

Resizes the screen to width × height and renders, as a terminal resize does in the runtime: the backend hands the engine a fresh, empty buffer of the new size and the next frame is drawn in full. A new size reaches App::resized before that frame is built.

Source

pub fn screen(&self) -> String

The screen as text, one line per row, trailing spaces removed.

Source

pub fn html(&self, caption: &str) -> String

The screen as a self-contained HTML fragment with colours and weights, for looking at renders in a browser. Wrap fragments with html_page to get a document.

Source

pub fn find(&self, text: &str) -> Option<(i32, i32)>

Screen position of the first occurrence of text, in cells.

Source

pub fn fg(&self, x: u16, y: u16) -> Option<Rgb>

Text colour of a cell.

§Panics

Panics when the cell is outside the screen.

Source

pub fn bg(&self, x: u16, y: u16) -> Option<Rgb>

Background colour of a cell.

§Panics

Panics when the cell is outside the screen.

Source

pub fn is_bold(&self, x: u16, y: u16) -> bool

Whether a cell is bold.

§Panics

Panics when the cell is outside the screen.

Source

pub fn buffer(&self) -> &Buffer

The rendered buffer.

Source

pub fn app(&self) -> &A

The application.

Source

pub fn env(&self) -> &Env

The environment.

Source

pub fn copied(&self) -> &[String]

Texts copied to the clipboard so far.

Source

pub fn clipboard(&self) -> Option<&str>

The in-process clipboard: the text copied last, if any.

Source

pub fn set_system_clipboard(&mut self, text: Option<&str>) -> &mut Self

Stands in for the system clipboard that pasting reads first: Some text as if the user had copied it in another program, None for an empty clipboard (the start). A harness never reads the real clipboard or asks a terminal, so without this pasting uses the text the application copied last.

Source

pub fn handoffs(&self) -> &[HandoffRequest]

The handoffs of Command::handoff the application asked for, oldest first. A harness has no terminal to hand over, so it records the request and answers it with the outcome of Harness::set_handoff_outcome instead of running the program.

Source

pub fn set_handoff_outcome(&mut self, outcome: HandoffOutcome) -> &mut Self

The outcome every handoff from now on ends with; Finished { code: Some(0) } without this.

Source

pub fn quit_requested(&self) -> bool

Whether the application asked to quit.

Source

pub fn is_focused(&self, name: &str) -> bool

Whether the widget named name has keyboard focus.

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 Engine<A>: Freeze,

§

impl<A> Unpin for Harness<A>
where Engine<A>: Unpin,

§

impl<A> UnsafeUnpin for Harness<A>
where Engine<A>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.