1 use tui::{
2     backend::TestBackend,
3     buffer::Buffer,
4     layout::{Constraint, Direction, Layout, Rect},
5     style::{Color, Modifier, Style},
6     symbols,
7     text::Span,
8     widgets::{Block, Borders, Gauge, LineGauge},
9     Terminal,
10 };
11 
12 #[test]
widgets_gauge_renders()13 fn widgets_gauge_renders() {
14     let backend = TestBackend::new(40, 10);
15     let mut terminal = Terminal::new(backend).unwrap();
16     terminal
17         .draw(|f| {
18             let chunks = Layout::default()
19                 .direction(Direction::Vertical)
20                 .margin(2)
21                 .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
22                 .split(f.size());
23 
24             let gauge = Gauge::default()
25                 .block(Block::default().title("Percentage").borders(Borders::ALL))
26                 .gauge_style(Style::default().bg(Color::Blue).fg(Color::Red))
27                 .use_unicode(true)
28                 .percent(43);
29             f.render_widget(gauge, chunks[0]);
30             let gauge = Gauge::default()
31                 .block(Block::default().title("Ratio").borders(Borders::ALL))
32                 .gauge_style(Style::default().bg(Color::Blue).fg(Color::Red))
33                 .use_unicode(true)
34                 .ratio(0.511_313_934_313_1);
35             f.render_widget(gauge, chunks[1]);
36         })
37         .unwrap();
38     let mut expected = Buffer::with_lines(vec![
39         "                                        ",
40         "                                        ",
41         "  ┌Percentage────────────────────────┐  ",
42         "  │              ▋43%                │  ",
43         "  └──────────────────────────────────┘  ",
44         "  ┌Ratio─────────────────────────────┐  ",
45         "  │               51%                │  ",
46         "  └──────────────────────────────────┘  ",
47         "                                        ",
48         "                                        ",
49     ]);
50 
51     for i in 3..17 {
52         expected
53             .get_mut(i, 3)
54             .set_bg(Color::Red)
55             .set_fg(Color::Blue);
56     }
57     for i in 17..37 {
58         expected
59             .get_mut(i, 3)
60             .set_bg(Color::Blue)
61             .set_fg(Color::Red);
62     }
63 
64     for i in 3..20 {
65         expected
66             .get_mut(i, 6)
67             .set_bg(Color::Red)
68             .set_fg(Color::Blue);
69     }
70     for i in 20..37 {
71         expected
72             .get_mut(i, 6)
73             .set_bg(Color::Blue)
74             .set_fg(Color::Red);
75     }
76 
77     terminal.backend().assert_buffer(&expected);
78 }
79 
80 #[test]
widgets_gauge_renders_no_unicode()81 fn widgets_gauge_renders_no_unicode() {
82     let backend = TestBackend::new(40, 10);
83     let mut terminal = Terminal::new(backend).unwrap();
84 
85     terminal
86         .draw(|f| {
87             let chunks = Layout::default()
88                 .direction(Direction::Vertical)
89                 .margin(2)
90                 .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
91                 .split(f.size());
92 
93             let gauge = Gauge::default()
94                 .block(Block::default().title("Percentage").borders(Borders::ALL))
95                 .percent(43)
96                 .use_unicode(false);
97             f.render_widget(gauge, chunks[0]);
98             let gauge = Gauge::default()
99                 .block(Block::default().title("Ratio").borders(Borders::ALL))
100                 .ratio(0.211_313_934_313_1)
101                 .use_unicode(false);
102             f.render_widget(gauge, chunks[1]);
103         })
104         .unwrap();
105     let expected = Buffer::with_lines(vec![
106         "                                        ",
107         "                                        ",
108         "  ┌Percentage────────────────────────┐  ",
109         "  │               43%                │  ",
110         "  └──────────────────────────────────┘  ",
111         "  ┌Ratio─────────────────────────────┐  ",
112         "  │               21%                │  ",
113         "  └──────────────────────────────────┘  ",
114         "                                        ",
115         "                                        ",
116     ]);
117     terminal.backend().assert_buffer(&expected);
118 }
119 
120 #[test]
widgets_gauge_applies_styles()121 fn widgets_gauge_applies_styles() {
122     let backend = TestBackend::new(12, 5);
123     let mut terminal = Terminal::new(backend).unwrap();
124 
125     terminal
126         .draw(|f| {
127             let gauge = Gauge::default()
128                 .block(
129                     Block::default()
130                         .title(Span::styled("Test", Style::default().fg(Color::Red)))
131                         .borders(Borders::ALL),
132                 )
133                 .gauge_style(Style::default().fg(Color::Blue).bg(Color::Red))
134                 .percent(43)
135                 .label(Span::styled(
136                     "43%",
137                     Style::default()
138                         .fg(Color::Green)
139                         .add_modifier(Modifier::BOLD),
140                 ));
141             f.render_widget(gauge, f.size());
142         })
143         .unwrap();
144     let mut expected = Buffer::with_lines(vec![
145         "┌Test──────┐",
146         "│          │",
147         "│   43%    │",
148         "│          │",
149         "└──────────┘",
150     ]);
151     // title
152     expected.set_style(Rect::new(1, 0, 4, 1), Style::default().fg(Color::Red));
153     // gauge area
154     expected.set_style(
155         Rect::new(1, 1, 10, 3),
156         Style::default().fg(Color::Blue).bg(Color::Red),
157     );
158     // filled area
159     for y in 1..4 {
160         expected.set_style(
161             Rect::new(1, y, 4, 1),
162             // filled style is invert of gauge_style
163             Style::default().fg(Color::Red).bg(Color::Blue),
164         );
165     }
166     // label (foreground and modifier from label style)
167     expected.set_style(
168         Rect::new(4, 2, 1, 1),
169         Style::default()
170             .fg(Color::Green)
171             // "4" is in the filled area so background is gauge_style foreground
172             .bg(Color::Blue)
173             .add_modifier(Modifier::BOLD),
174     );
175     expected.set_style(
176         Rect::new(5, 2, 2, 1),
177         Style::default()
178             .fg(Color::Green)
179             // "3%" is not in the filled area so background is gauge_style background
180             .bg(Color::Red)
181             .add_modifier(Modifier::BOLD),
182     );
183     terminal.backend().assert_buffer(&expected);
184 }
185 
186 #[test]
widgets_gauge_supports_large_labels()187 fn widgets_gauge_supports_large_labels() {
188     let backend = TestBackend::new(10, 1);
189     let mut terminal = Terminal::new(backend).unwrap();
190 
191     terminal
192         .draw(|f| {
193             let gauge = Gauge::default()
194                 .percent(43)
195                 .label("43333333333333333333333333333%");
196             f.render_widget(gauge, f.size());
197         })
198         .unwrap();
199     let expected = Buffer::with_lines(vec!["4333333333"]);
200     terminal.backend().assert_buffer(&expected);
201 }
202 
203 #[test]
widgets_line_gauge_renders()204 fn widgets_line_gauge_renders() {
205     let backend = TestBackend::new(20, 4);
206     let mut terminal = Terminal::new(backend).unwrap();
207     terminal
208         .draw(|f| {
209             let gauge = LineGauge::default()
210                 .gauge_style(Style::default().fg(Color::Green).bg(Color::White))
211                 .ratio(0.43);
212             f.render_widget(
213                 gauge,
214                 Rect {
215                     x: 0,
216                     y: 0,
217                     width: 20,
218                     height: 1,
219                 },
220             );
221             let gauge = LineGauge::default()
222                 .block(Block::default().title("Gauge 2").borders(Borders::ALL))
223                 .gauge_style(Style::default().fg(Color::Green))
224                 .line_set(symbols::line::THICK)
225                 .ratio(0.211_313_934_313_1);
226             f.render_widget(
227                 gauge,
228                 Rect {
229                     x: 0,
230                     y: 1,
231                     width: 20,
232                     height: 3,
233                 },
234             );
235         })
236         .unwrap();
237     let mut expected = Buffer::with_lines(vec![
238         "43% ────────────────",
239         "┌Gauge 2───────────┐",
240         "│21% ━━━━━━━━━━━━━━│",
241         "└──────────────────┘",
242     ]);
243     for col in 4..10 {
244         expected.get_mut(col, 0).set_fg(Color::Green);
245     }
246     for col in 10..20 {
247         expected.get_mut(col, 0).set_fg(Color::White);
248     }
249     for col in 5..7 {
250         expected.get_mut(col, 2).set_fg(Color::Green);
251     }
252     terminal.backend().assert_buffer(&expected);
253 }
254