Expand description
A headless driver for an App: clicks, keys, typed text and drags
through the real view and on_event, with no window and no GPU.
Drive owns (or borrows) a Core and a viewport. A test frames the
app, finds nodes by the label they were keyed under, sends gestures and
reads back what the frame drew. It runs under plain cargo test.
use kui_native::testing::Drive;
use kui_native::widgets;
use kui_native::{App, Core, Message, NodeSpec, TextStyle, Ui, UiEvent};
#[derive(Message, Clone, Debug, PartialEq)]
enum Msg {
Add,
}
#[derive(Default)]
struct Counter {
count: u32,
}
impl App for Counter {
fn view(&mut self, ui: &mut Ui<'_>) {
ui.with(NodeSpec::column().fill().gap(8.0), |ui| {
widgets::button(ui, "Add", Msg::Add);
ui.text_in_keyed(
"summary",
NodeSpec::row(),
&format!("{} added", self.count),
TextStyle::new(12.0),
);
});
}
fn on_event(&mut self, ev: UiEvent) {
if ev.message::<Msg>() == Some(Msg::Add) {
self.count += 1;
}
}
}
let mut app = Counter::default();
// `framing` builds a frame after every gesture, so the view has caught
// up before the next assert.
let mut d = Drive::new(Core::new(), 320.0, 200.0).framing();
d.frame(&mut app);
// Click by label, the way a screen reader presses: no geometry needed.
let add = d.key_of("Add").expect("an Add button");
d.click_key(&mut app, add);
assert_eq!(app.count, 1);
assert_eq!(d.texts_under("summary"), ["1 added"]);
// Nothing the core saw was misdeclared.
assert!(d.warnings().is_empty());Without Drive::framing, a gesture sends its inputs and stops, and
the test calls Drive::frame when it wants the view to catch up.
Events reach the app as the windowed runner sends them: an extension’s
to the extension, the rest to on_event, each one logged
(Drive::log).
Structs§
- Drive
- The headless driver; see the module docs for an example.