Skip to main content

tui/testing/
helpers.rs

1use std::fmt::Write;
2
3use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
4
5use crate::rendering::frame::Cursor;
6use crate::rendering::frame::Frame;
7use crate::rendering::renderer::Renderer;
8use crate::{SelectOption, ViewContext};
9
10use super::TestTerminal;
11
12fn frame_from_lines(lines: &[crate::line::Line], _width: u16, _rows: u16) -> Frame {
13    Frame::new(lines.to_vec())
14        .with_cursor(Cursor { row: lines.len().saturating_sub(1), col: 0, is_visible: true })
15        .clamp_cursor()
16}
17
18pub fn render_component(mut render: impl FnMut(&ViewContext) -> Frame, width: u16, rows: u16) -> TestTerminal {
19    let ctx = ViewContext::new((width, rows));
20    let frame = render(&ctx);
21    let terminal = TestTerminal::new(width, rows);
22    let mut renderer = Renderer::new(terminal, crate::theme::Theme::default(), (width, rows));
23    renderer.render_frame(|_| frame).unwrap();
24    renderer.writer().clone()
25}
26
27pub fn render_component_with_renderer(
28    mut render: impl FnMut(&ViewContext) -> Frame,
29    renderer: &mut Renderer<TestTerminal>,
30    width: u16,
31    rows: u16,
32) {
33    let ctx = ViewContext::new((width, rows));
34    let frame = render(&ctx);
35    renderer.render_frame(|_| frame).unwrap();
36}
37
38pub fn render_lines(lines: &[crate::line::Line], width: u16, rows: u16) -> TestTerminal {
39    render_component(|_| frame_from_lines(lines, width, rows), width, rows)
40}
41
42pub fn key(code: KeyCode) -> KeyEvent {
43    KeyEvent::new(code, KeyModifiers::NONE)
44}
45
46pub fn pad(text: &str, width: usize) -> String {
47    format!("{text:<width$}")
48}
49
50pub fn cols(parts: &[(&str, usize)]) -> String {
51    let mut out = String::new();
52    for (text, width) in parts {
53        let _ = write!(out, "{text:<width$}");
54    }
55    out.trim_end().to_string()
56}
57
58pub fn sample_options() -> Vec<SelectOption> {
59    vec![
60        SelectOption { value: "a".into(), title: "Alpha".into(), description: None },
61        SelectOption { value: "b".into(), title: "Beta".into(), description: None },
62        SelectOption { value: "c".into(), title: "Gamma".into(), description: None },
63    ]
64}