1use crate::buffer::Buffer;
2use crate::context::Context;
3use crate::event::Event;
4use crate::layout;
5use crate::rect::Rect;
6use crate::style::Theme;
7
8pub struct TestBackend {
9 buffer: Buffer,
10 width: u32,
11 height: u32,
12}
13
14impl TestBackend {
15 pub fn new(width: u32, height: u32) -> Self {
16 let area = Rect::new(0, 0, width, height);
17 Self {
18 buffer: Buffer::empty(area),
19 width,
20 height,
21 }
22 }
23
24 pub fn render(&mut self, f: impl FnOnce(&mut Context)) {
26 let mut ctx = Context::new(
27 Vec::new(),
28 self.width,
29 self.height,
30 0,
31 0,
32 0,
33 Vec::new(),
34 Vec::new(),
35 false,
36 Theme::dark(),
37 None,
38 );
39 f(&mut ctx);
40 let mut tree = layout::build_tree(&ctx.commands);
41 let area = Rect::new(0, 0, self.width, self.height);
42 layout::compute(&mut tree, area);
43 self.buffer.reset();
44 layout::render(&tree, &mut self.buffer);
45 }
46
47 pub fn render_with_events(
49 &mut self,
50 events: Vec<Event>,
51 focus_index: usize,
52 prev_focus_count: usize,
53 f: impl FnOnce(&mut Context),
54 ) {
55 let mut ctx = Context::new(
56 events,
57 self.width,
58 self.height,
59 0,
60 focus_index,
61 prev_focus_count,
62 Vec::new(),
63 Vec::new(),
64 false,
65 Theme::dark(),
66 None,
67 );
68 ctx.process_focus_keys();
69 f(&mut ctx);
70 let mut tree = layout::build_tree(&ctx.commands);
71 let area = Rect::new(0, 0, self.width, self.height);
72 layout::compute(&mut tree, area);
73 self.buffer.reset();
74 layout::render(&tree, &mut self.buffer);
75 }
76
77 pub fn line(&self, y: u32) -> String {
79 let mut s = String::new();
80 for x in 0..self.width {
81 s.push_str(&self.buffer.get(x, y).symbol);
82 }
83 s.trim_end().to_string()
84 }
85
86 pub fn assert_line(&self, y: u32, expected: &str) {
88 let line = self.line(y);
89 assert_eq!(
90 line, expected,
91 "Line {y}: expected {expected:?}, got {line:?}"
92 );
93 }
94
95 pub fn assert_line_contains(&self, y: u32, expected: &str) {
97 let line = self.line(y);
98 assert!(
99 line.contains(expected),
100 "Line {y}: expected to contain {expected:?}, got {line:?}"
101 );
102 }
103
104 pub fn assert_contains(&self, expected: &str) {
106 for y in 0..self.height {
107 if self.line(y).contains(expected) {
108 return;
109 }
110 }
111 let mut all_lines = String::new();
112 for y in 0..self.height {
113 all_lines.push_str(&format!("{}: {}\n", y, self.line(y)));
114 }
115 panic!("Buffer does not contain {expected:?}.\nBuffer:\n{all_lines}");
116 }
117
118 pub fn buffer(&self) -> &Buffer {
119 &self.buffer
120 }
121
122 pub fn width(&self) -> u32 {
123 self.width
124 }
125
126 pub fn height(&self) -> u32 {
127 self.height
128 }
129}