mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-29 08:00:38 +00:00
2cfe82a47e
- Simplify `assert_buffer_eq!` logic. - Deprecate `assert_buffer_eq!`. - Introduce `TestBackend::assert_buffer_lines`. Also simplify many tests involving buffer comparisons. For the deprecation, just use `assert_eq` instead of `assert_buffer_eq`: ```diff -assert_buffer_eq!(actual, expected); +assert_eq!(actual, expected); ``` --- I noticed `assert_buffer_eq!` creating no test coverage reports and looked into this macro. First I simplified it. Then I noticed a bunch of `assert_eq!(buffer, …)` and other indirect usages of this macro (like `TestBackend::assert_buffer`). The good thing here is that it's mainly used in tests so not many changes to the library code.
850 lines
32 KiB
Rust
Executable file
850 lines
32 KiB
Rust
Executable file
#![allow(deprecated)]
|
|
|
|
use ratatui::{
|
|
backend::TestBackend,
|
|
buffer::Buffer,
|
|
layout::Constraint,
|
|
style::{Color, Modifier, Style},
|
|
text::{Line, Span},
|
|
widgets::{Block, Borders, Cell, HighlightSpacing, Row, Table, TableState},
|
|
Terminal,
|
|
};
|
|
use rstest::rstest;
|
|
|
|
#[rstest]
|
|
#[case::no_space_between_columns(0, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1Head2Head3 │",
|
|
"│ │",
|
|
"│Row11Row12Row13 │",
|
|
"│Row21Row22Row23 │",
|
|
"│Row31Row32Row33 │",
|
|
"│Row41Row42Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::one_space_between_columns(1, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::large_width_just_before_pushing_a_column_off(6, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::large_width_pushes_part_of_third_column_off(7, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head Head3│",
|
|
"│ │",
|
|
"│Row11 Row1 Row13│",
|
|
"│Row21 Row2 Row23│",
|
|
"│Row31 Row3 Row33│",
|
|
"│Row41 Row4 Row43│",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_column_spacing_can_be_changed<'line, Lines>(
|
|
#[case] column_spacing: u16,
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let backend = TestBackend::new(30, 10);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
],
|
|
[
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.column_spacing(column_spacing);
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::zero_width_shows_nothing( &[
|
|
Constraint::Length(0),
|
|
Constraint::Length(0),
|
|
Constraint::Length(0),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::slim_columns_trim_data(&[
|
|
Constraint::Length(1),
|
|
Constraint::Length(1),
|
|
Constraint::Length(1),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│H H H │",
|
|
"│ │",
|
|
"│R R R │",
|
|
"│R R R │",
|
|
"│R R R │",
|
|
"│R R R │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::large_width_just_before_pushing_a_column_off(&[
|
|
Constraint::Length(8),
|
|
Constraint::Length(8),
|
|
Constraint::Length(8),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_columns_widths_can_use_fixed_length_constraints<'line, Lines>(
|
|
#[case] widths: &[Constraint],
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let backend = TestBackend::new(30, 10);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
],
|
|
widths,
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered());
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::zero_width_shows_nothing(&[
|
|
Constraint::Percentage(0),
|
|
Constraint::Percentage(0),
|
|
Constraint::Percentage(0),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::slim_columns_trim_data(&[
|
|
Constraint::Percentage(11),
|
|
Constraint::Percentage(11),
|
|
Constraint::Percentage(11),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│HeaHeaHea │",
|
|
"│ │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::large_width_just_before_pushing_a_column_off(&[
|
|
Constraint::Percentage(33),
|
|
Constraint::Percentage(33),
|
|
Constraint::Percentage(33),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::sum_100_equal_widths(&[Constraint::Percentage(50), Constraint::Percentage(50)], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 │",
|
|
"│ │",
|
|
"│Row11 Row12 │",
|
|
"│Row21 Row22 │",
|
|
"│Row31 Row32 │",
|
|
"│Row41 Row42 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_columns_widths_can_use_percentage_constraints<'line, Lines>(
|
|
#[case] widths: &[Constraint],
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let backend = TestBackend::new(30, 10);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
],
|
|
widths,
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.column_spacing(0);
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::zero_width_shows_nothing(&[
|
|
Constraint::Percentage(0),
|
|
Constraint::Length(0),
|
|
Constraint::Percentage(0),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::slim_columns_trim_data(&[
|
|
Constraint::Percentage(11),
|
|
Constraint::Length(20),
|
|
Constraint::Percentage(11),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│Hea Head2 Hea│",
|
|
"│ │",
|
|
"│Row Row12 Row│",
|
|
"│Row Row22 Row│",
|
|
"│Row Row32 Row│",
|
|
"│Row Row42 Row│",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::large_width_just_before_pushing_a_column_off(&[
|
|
Constraint::Percentage(33),
|
|
Constraint::Length(10),
|
|
Constraint::Percentage(33),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::more_than_100(&[
|
|
Constraint::Percentage(60),
|
|
Constraint::Length(10),
|
|
Constraint::Percentage(60),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_columns_widths_can_use_mixed_constraints<'line, Lines>(
|
|
#[case] widths: &[Constraint],
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let backend = TestBackend::new(30, 10);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
],
|
|
widths,
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered());
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::zero_shows_nothing(&[
|
|
Constraint::Ratio(0, 1),
|
|
Constraint::Ratio(0, 1),
|
|
Constraint::Ratio(0, 1),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::slim_trims_data(&[
|
|
Constraint::Ratio(1, 9),
|
|
Constraint::Ratio(1, 9),
|
|
Constraint::Ratio(1, 9),
|
|
], [
|
|
"┌────────────────────────────┐",
|
|
"│HeaHeaHea │",
|
|
"│ │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│RowRowRow │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::three(&[Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3)], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::two(&[Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)], [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 │",
|
|
"│ │",
|
|
"│Row11 Row12 │",
|
|
"│Row21 Row22 │",
|
|
"│Row31 Row32 │",
|
|
"│Row41 Row42 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_columns_widths_can_use_ratio_constraints<'line, Lines>(
|
|
#[case] widths: &[Constraint],
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let backend = TestBackend::new(30, 10);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
],
|
|
widths,
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.column_spacing(0);
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::none(
|
|
None,
|
|
[
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
],
|
|
)]
|
|
#[case::first(
|
|
Some(0),
|
|
[
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│>> Row11 Row12 Row13 │",
|
|
"│ Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
],
|
|
)]
|
|
#[case::second_no_partially_fourth(
|
|
Some(1),
|
|
[
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│ Row11 Row12 Row13 │",
|
|
"│>> Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
],
|
|
)]
|
|
#[case::fourth_no_partially_first(
|
|
Some(3),
|
|
[
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"│>> Row41 Row42 Row43 │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
],
|
|
)]
|
|
fn widgets_table_can_have_rows_with_multi_lines<'line, Lines>(
|
|
#[case] selected: Option<usize>,
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let mut state = TableState::new().with_selected(selected);
|
|
let backend = TestBackend::new(30, 8);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]).height(2),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]).height(2),
|
|
],
|
|
[
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.highlight_symbol(">> ")
|
|
.column_spacing(1);
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case::none_when_selected(None, HighlightSpacing::WhenSelected, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::none_always(
|
|
None, HighlightSpacing::Always, [
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│ Row11 Row12 Row13 │",
|
|
"│ Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::none_never(None, HighlightSpacing::Never, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::first_when_selected(Some(0), HighlightSpacing::WhenSelected, [
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│>> Row11 Row12 Row13 │",
|
|
"│ Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::first_always(Some(0), HighlightSpacing::Always, [
|
|
"┌────────────────────────────┐",
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│>> Row11 Row12 Row13 │",
|
|
"│ Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│ Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
#[case::first_never(Some(0), HighlightSpacing::Never, [
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row11 Row12 Row13 │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│ │",
|
|
"│Row31 Row32 Row33 │",
|
|
"└────────────────────────────┘",
|
|
])]
|
|
fn widgets_table_enable_always_highlight_spacing<'line, Lines>(
|
|
#[case] selected: Option<usize>,
|
|
#[case] space: HighlightSpacing,
|
|
#[case] expected: Lines,
|
|
) where
|
|
Lines: IntoIterator,
|
|
Lines::Item: Into<Line<'line>>,
|
|
{
|
|
let mut state = TableState::new().with_selected(selected);
|
|
let backend = TestBackend::new(30, 8);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]).height(2),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]).height(2),
|
|
],
|
|
[
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.highlight_symbol(">> ")
|
|
.highlight_spacing(space)
|
|
.column_spacing(1);
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines(expected);
|
|
}
|
|
|
|
#[test]
|
|
fn widgets_table_can_have_elements_styled_individually() {
|
|
let backend = TestBackend::new(30, 4);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
let mut state = TableState::default();
|
|
state.select(Some(0));
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row11", "Row12", "Row13"])
|
|
.style(Style::default().fg(Color::Green)),
|
|
Row::new(vec![
|
|
Cell::from("Row21"),
|
|
Cell::from("Row22").style(Style::default().fg(Color::Yellow)),
|
|
Cell::from(Line::from(vec![
|
|
Span::raw("Row"),
|
|
Span::styled("23", Style::default().fg(Color::Blue)),
|
|
]))
|
|
.style(Style::default().fg(Color::Red)),
|
|
])
|
|
.style(Style::default().fg(Color::LightGreen)),
|
|
],
|
|
[
|
|
Constraint::Length(6),
|
|
Constraint::Length(6),
|
|
Constraint::Length(6),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::new().borders(Borders::LEFT | Borders::RIGHT))
|
|
.highlight_symbol(">> ")
|
|
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
|
|
.column_spacing(1);
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
|
|
let mut expected = Buffer::with_lines([
|
|
"│ Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│>> Row11 Row12 Row13 │",
|
|
"│ Row21 Row22 Row23 │",
|
|
]);
|
|
// First row = row color + highlight style
|
|
for col in 1..=28 {
|
|
expected.get_mut(col, 2).set_style(
|
|
Style::default()
|
|
.fg(Color::Green)
|
|
.add_modifier(Modifier::BOLD),
|
|
);
|
|
}
|
|
// Second row:
|
|
// 1. row color
|
|
for col in 1..=28 {
|
|
expected
|
|
.get_mut(col, 3)
|
|
.set_style(Style::default().fg(Color::LightGreen));
|
|
}
|
|
// 2. cell color
|
|
for col in 11..=16 {
|
|
expected
|
|
.get_mut(col, 3)
|
|
.set_style(Style::default().fg(Color::Yellow));
|
|
}
|
|
for col in 18..=23 {
|
|
expected
|
|
.get_mut(col, 3)
|
|
.set_style(Style::default().fg(Color::Red));
|
|
}
|
|
// 3. text color
|
|
for col in 21..=22 {
|
|
expected
|
|
.get_mut(col, 3)
|
|
.set_style(Style::default().fg(Color::Blue));
|
|
}
|
|
terminal.backend().assert_buffer(&expected);
|
|
}
|
|
|
|
#[test]
|
|
fn widgets_table_should_render_even_if_empty() {
|
|
let backend = TestBackend::new(30, 4);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
Vec::<Row>::new(),
|
|
[
|
|
Constraint::Length(6),
|
|
Constraint::Length(6),
|
|
Constraint::Length(6),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]))
|
|
.block(Block::new().borders(Borders::LEFT | Borders::RIGHT))
|
|
.column_spacing(1);
|
|
f.render_widget(table, size);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines([
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
]);
|
|
}
|
|
|
|
// based on https://github.com/fdehau/tui-rs/issues/470#issuecomment-852562848
|
|
#[test]
|
|
fn widgets_table_columns_dont_panic() {
|
|
let table_width = 98;
|
|
let table = Table::new(
|
|
vec![Row::new(vec!["r1", "r2", "r3", "r4"])],
|
|
[
|
|
Constraint::Percentage(15),
|
|
Constraint::Percentage(15),
|
|
Constraint::Percentage(25),
|
|
Constraint::Percentage(45),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["h1", "h2", "h3", "h4"]))
|
|
.block(Block::bordered())
|
|
.highlight_symbol(">> ")
|
|
.column_spacing(1);
|
|
|
|
let mut state = TableState::default();
|
|
|
|
// select first, which would cause a panic before fix
|
|
state.select(Some(0));
|
|
|
|
let backend = TestBackend::new(table_width, 8);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn widgets_table_should_clamp_offset_if_rows_are_removed() {
|
|
let backend = TestBackend::new(30, 8);
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
let mut state = TableState::default();
|
|
|
|
// render with 6 items => offset will be at 2
|
|
state.select(Some(5));
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![
|
|
Row::new(vec!["Row01", "Row02", "Row03"]),
|
|
Row::new(vec!["Row11", "Row12", "Row13"]),
|
|
Row::new(vec!["Row21", "Row22", "Row23"]),
|
|
Row::new(vec!["Row31", "Row32", "Row33"]),
|
|
Row::new(vec!["Row41", "Row42", "Row43"]),
|
|
Row::new(vec!["Row51", "Row52", "Row53"]),
|
|
],
|
|
[
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.column_spacing(1);
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines([
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row21 Row22 Row23 │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│Row41 Row42 Row43 │",
|
|
"│Row51 Row52 Row53 │",
|
|
"└────────────────────────────┘",
|
|
]);
|
|
|
|
// render with 1 item => offset will be at 1
|
|
state.select(Some(1));
|
|
terminal
|
|
.draw(|f| {
|
|
let size = f.size();
|
|
let table = Table::new(
|
|
vec![Row::new(vec!["Row31", "Row32", "Row33"])],
|
|
[
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
Constraint::Length(5),
|
|
],
|
|
)
|
|
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
|
.block(Block::bordered())
|
|
.column_spacing(1);
|
|
f.render_stateful_widget(table, size, &mut state);
|
|
})
|
|
.unwrap();
|
|
terminal.backend().assert_buffer_lines([
|
|
"┌────────────────────────────┐",
|
|
"│Head1 Head2 Head3 │",
|
|
"│ │",
|
|
"│Row31 Row32 Row33 │",
|
|
"│ │",
|
|
"│ │",
|
|
"│ │",
|
|
"└────────────────────────────┘",
|
|
]);
|
|
}
|