pub struct TestBackend { /* private fields */ }Expand description
Headless rendering backend for tests.
Renders a UI closure to an in-memory Buffer without a real terminal.
Use render to run one frame, then inspect the
output with line, assert_contains,
or to_string_trimmed.
Session state persists across renders, so multi-frame tests can exercise
hooks, focus, and previous-frame hit testing.
§Example
use slt::TestBackend;
let mut backend = TestBackend::new(40, 10);
backend.render(|ui| {
ui.text("hello");
});
backend.assert_contains("hello");Implementations§
Source§impl TestBackend
impl TestBackend
Sourcepub fn new(width: u32, height: u32) -> Self
pub fn new(width: u32, height: u32) -> Self
Create a test backend with the given terminal dimensions.
Sourcepub fn record_frames(self) -> Self
pub fn record_frames(self) -> Self
Enable frame recording.
After this call, every subsequent render,
render_with_events, and
run_with_events call appends a
FrameRecord to the internal history. Disabled by default so tests
that don’t need history pay zero memory overhead.
Returns self for chaining.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(20, 3).record_frames();
for n in 0..3 {
tb.render(|ui| {
ui.text(format!("frame {n}"));
});
}
assert_eq!(tb.frames().len(), 3);
tb.frames()[0].assert_contains("frame 0");
tb.frames()[2].assert_contains("frame 2");Sourcepub fn frames(&self) -> &[FrameRecord]
pub fn frames(&self) -> &[FrameRecord]
Return all captured frame snapshots in chronological order.
Returns an empty slice if record_frames
was never called on this backend.
Sourcepub fn render(&mut self, f: impl FnOnce(&mut Context))
pub fn render(&mut self, f: impl FnOnce(&mut Context))
Run a UI closure for one frame and render to the internal buffer.
Sourcepub fn render_with_events(
&mut self,
events: Vec<Event>,
focus_index: usize,
prev_focus_count: usize,
f: impl FnOnce(&mut Context),
)
pub fn render_with_events( &mut self, events: Vec<Event>, focus_index: usize, prev_focus_count: usize, f: impl FnOnce(&mut Context), )
Render with injected events and focus state for interaction testing.
Sourcepub fn run_with_events(
&mut self,
events: Vec<Event>,
f: impl FnOnce(&mut Context),
)
pub fn run_with_events( &mut self, events: Vec<Event>, f: impl FnOnce(&mut Context), )
Convenience wrapper: render with events using default focus state.
Sourcepub fn line(&self, y: u32) -> String
pub fn line(&self, y: u32) -> String
Get the rendered text content of row y (trimmed trailing spaces)
Sourcepub fn assert_line(&self, y: u32, expected: &str)
pub fn assert_line(&self, y: u32, expected: &str)
Assert that row y contains expected as a substring
Sourcepub fn assert_line_contains(&self, y: u32, expected: &str)
pub fn assert_line_contains(&self, y: u32, expected: &str)
Assert that row y contains expected as a substring
Sourcepub fn assert_contains(&self, expected: &str)
pub fn assert_contains(&self, expected: &str)
Assert that any line in the buffer contains expected
Sourcepub fn to_string_trimmed(&self) -> String
pub fn to_string_trimmed(&self) -> String
Return the full rendered buffer as a multi-line string.
Each row is trimmed of trailing spaces and joined with newlines.
Useful for snapshot testing with insta::assert_snapshot!.
Sourcepub fn assert_not_contains(&self, expected: &str)
pub fn assert_not_contains(&self, expected: &str)
Assert that no row in the buffer contains expected as a substring.
Panics with the offending row indices and contents on failure.
Sourcepub fn assert_line_not_contains(&self, y: u32, expected: &str)
pub fn assert_line_not_contains(&self, y: u32, expected: &str)
Assert that row y does NOT contain expected as a substring.
Sourcepub fn assert_empty_line(&self, y: u32)
pub fn assert_empty_line(&self, y: u32)
Assert that row y is entirely blank (contains no non-space content).
Useful for verifying that cleared, padded, or overflow-suppressed rows render as empty.
Sourcepub fn assert_style_at(&self, x: u32, y: u32, expected: Style)
pub fn assert_style_at(&self, x: u32, y: u32, expected: Style)
Assert that the cell at (x, y) carries exactly the expected style.
Useful for focused color/modifier regression checks without committing
to a full-buffer snapshot. Panics with (x, y), the actual style, and
the expected style on mismatch.
Sourcepub fn find_text(&self, needle: &str) -> Option<(u32, u32)>
pub fn find_text(&self, needle: &str) -> Option<(u32, u32)>
Find the first buffer position where needle begins in the rendered
text grid, scanning rows top-to-bottom and columns left-to-right.
Each cell contributes its glyph at the cell’s own column; empty cells
(blanks and wide-char trailing cells) count as a single space so the
returned x is the actual buffer column where the match starts. The
search is per-row — a needle that wraps across a row boundary is not
matched. Returns None if needle is empty or absent.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(20, 2);
tb.render(|ui| {
ui.text(" hello");
});
assert_eq!(tb.find_text("hello"), Some((2, 0)));
assert_eq!(tb.find_text("nope"), None);Sourcepub fn assert_region(&self, x: u32, y: u32, w: u32, h: u32, expected: &str)
pub fn assert_region(&self, x: u32, y: u32, w: u32, h: u32, expected: &str)
Assert that the rectangular region anchored at (x, y) with width w
and height h renders exactly expected (rows joined with \n).
Each region row is the slice of buffer columns x..x+w on buffer row
y..y+h, with empty cells rendered as a space and trailing spaces
of each region row preserved (so width is significant). Columns or rows
that fall outside the buffer are treated as blanks. Panics with an
aligned expected-vs-actual diff on mismatch.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(10, 3);
tb.render(|ui| {
let _ = ui.col(|ui| {
ui.text("ab");
ui.text("cd");
});
});
tb.assert_region(0, 0, 2, 2, "ab\ncd");Sourcepub fn region(&self, x: u32, y: u32, w: u32, h: u32) -> String
pub fn region(&self, x: u32, y: u32, w: u32, h: u32) -> String
Render the rectangular region anchored at (x, y) with width w and
height h as a multi-line string (rows joined with \n).
Empty cells render as a single space and trailing spaces are preserved,
so the result is exactly w columns wide per row. Columns or rows
outside the buffer are blank-filled. Useful for scoping a snapshot to a
sub-rectangle without asserting on the full buffer.
Sourcepub fn assert_styled_contains(
&self,
needle: &str,
predicate: impl Fn(&Style) -> bool,
)
pub fn assert_styled_contains( &self, needle: &str, predicate: impl Fn(&Style) -> bool, )
Assert that needle is rendered somewhere in the buffer AND every cell
of the matched run satisfies predicate (applied to each cell’s
Style).
Combines a content check with a per-cell style check, which is more
ergonomic than pairing find_text with
repeated assert_style_at calls. The
run is located with find_text (per-row, left-to-right), then each of
the needle’s char-count cells starting at the match is tested.
Panics if the needle is absent or any covered cell fails the predicate.
§Example
use slt::{Color, TestBackend};
let mut tb = TestBackend::new(20, 1);
tb.render(|ui| {
ui.text("hi").fg(Color::Red).bold();
});
tb.assert_styled_contains("hi", |s| {
s.fg == Some(Color::Red) && s.modifiers.contains(slt::Modifiers::BOLD)
});Sourcepub fn snapshot(&self) -> String
pub fn snapshot(&self) -> String
Produce a stable, plain-text snapshot of the whole buffer.
Every buffer row is rendered exactly width columns wide (empty cells
as spaces, no trailing trim) and joined with \n. Unlike
to_string_trimmed, no trailing blank
rows are dropped and per-row width is fixed, giving a deterministic
snapshot suitable for assert_snapshot_eq
or external snapshot tooling.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(3, 2);
tb.render(|ui| {
ui.text("ab");
});
assert_eq!(tb.snapshot(), "ab \n ");Sourcepub fn assert_snapshot_eq(&self, expected: &str)
pub fn assert_snapshot_eq(&self, expected: &str)
Assert the buffer snapshot equals expected,
panicking with a unified-diff-style report on mismatch.
Trailing whitespace on each line of expected is ignored (the actual
snapshot is right-padded to the buffer width), so callers can write
trimmed expected strings. The panic message lists each differing row
with - (expected) / + (actual) markers.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(5, 2);
tb.render(|ui| {
ui.text("hi");
});
tb.assert_snapshot_eq("hi\n");Sourcepub fn sequence(&mut self) -> TestSequence<'_>
pub fn sequence(&mut self) -> TestSequence<'_>
Begin building a multi-step interaction sequence.
Each tick (or key)
appends an event batch + render closure pair.
run executes them in order, advancing
FrameState naturally between steps so callers don’t need to thread
focus_index / prev_focus_count manually.
§Example
use slt::{KeyCode, TestBackend};
let mut tb = TestBackend::new(20, 3);
tb.sequence()
.tick(|ui| { ui.text("ready"); })
.key(KeyCode::Esc, |ui| { ui.text("after esc"); })
.run();
tb.assert_contains("after esc");Sourcepub fn type_string(&mut self, s: &str, render: impl FnMut(&mut Context))
pub fn type_string(&mut self, s: &str, render: impl FnMut(&mut Context))
Simulate typing s one character at a time, rendering with render
between each character.
Each character produces a KeyCode::Char event with no modifiers.
Focus state is preserved across characters.
§Example
use slt::TestBackend;
let mut tb = TestBackend::new(20, 3);
let mut typed = String::new();
tb.type_string("hi", |ui| {
ui.text(&typed);
});
// 2 characters → 2 frames rendered.
drop(typed);Trait Implementations§
Auto Trait Implementations§
impl Freeze for TestBackend
impl !RefUnwindSafe for TestBackend
impl !Send for TestBackend
impl !Sync for TestBackend
impl Unpin for TestBackend
impl UnsafeUnpin for TestBackend
impl !UnwindSafe for TestBackend
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
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string() Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString. Read more