refactor(buffer): deprecate assert_buffer_eq! in favor of assert_eq! (#1007)

- 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.
This commit is contained in:
EdJoPaTo 2024-05-14 03:13:46 +02:00 committed by GitHub
parent 1a4bb1cbb8
commit 2cfe82a47e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 2969 additions and 3841 deletions

View file

@ -30,16 +30,15 @@ cassowary = "0.3"
compact_str = "0.7.1" compact_str = "0.7.1"
crossterm = { version = "0.27", optional = true } crossterm = { version = "0.27", optional = true }
document-features = { version = "0.2.7", optional = true } document-features = { version = "0.2.7", optional = true }
indoc = "2.0"
itertools = "0.12" itertools = "0.12"
lru = "0.12.0" lru = "0.12.0"
paste = "1.0.2" paste = "1.0.2"
serde = { version = "1", optional = true, features = ["derive"] } serde = { version = "1", optional = true, features = ["derive"] }
stability = "0.2.0" stability = "0.2.0"
strum = { version = "0.26", features = ["derive"] } strum = { version = "0.26", features = ["derive"] }
time = { version = "0.3.11", optional = true, features = ["local-offset"] }
termion = { version = "3.0", optional = true } termion = { version = "3.0", optional = true }
termwiz = { version = "0.22.0", optional = true } termwiz = { version = "0.22.0", optional = true }
time = { version = "0.3.11", optional = true, features = ["local-offset"] }
unicode-segmentation = "1.10" unicode-segmentation = "1.10"
unicode-truncate = "1" unicode-truncate = "1"
unicode-width = "0.1" unicode-width = "0.1"
@ -56,6 +55,7 @@ criterion = { version = "0.5.1", features = ["html_reports"] }
derive_builder = "0.20.0" derive_builder = "0.20.0"
fakeit = "1.1" fakeit = "1.1"
font8x8 = "0.3.1" font8x8 = "0.3.1"
indoc = "2"
palette = "0.7.3" palette = "0.7.3"
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
rand = "0.8.5" rand = "0.8.5"

View file

@ -286,10 +286,10 @@ fn draw_legend(f: &mut Frame, area: Rect) {
"- Company B", "- Company B",
Style::default().fg(Color::Yellow), Style::default().fg(Color::Yellow),
)), )),
Line::from(vec![Span::styled( Line::from(Span::styled(
"- Company C", "- Company C",
Style::default().fg(Color::White), Style::default().fg(Color::White),
)]), )),
]; ];
let block = Block::bordered().style(Style::default().fg(Color::White)); let block = Block::bordered().style(Style::default().fg(Color::White));

View file

@ -276,8 +276,6 @@ fn render_glyph(glyph: [u8; 8], area: Rect, buf: &mut Buffer, pixel_size: PixelS
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ratatui::assert_buffer_eq;
use super::*; use super::*;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
@ -308,7 +306,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 80, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 80, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" ████ ██ ███ ████ ██ ", " ████ ██ ███ ████ ██ ",
"██ ██ ██ ██ ", "██ ██ ██ ██ ",
"███ ███ █████ ███ ██ ██ ████ ██ ███ █████ ████ ", "███ ███ █████ ███ ██ ██ ████ ██ ███ █████ ████ ",
@ -318,7 +316,7 @@ mod tests {
" ████ ████ ██ ██ ██ ████ ████ ███████ ████ ██ ██ ████ ", " ████ ████ ██ ██ ██ ████ ████ ███████ ████ ██ ██ ████ ",
" █████ ", " █████ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -329,7 +327,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 70, 6)); let mut buf = Buffer::empty(Rect::new(0, 0, 70, 6));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"██████ █ ███", "██████ █ ███",
"█ ██ █ ██ ██", "█ ██ █ ██ ██",
" ██ ██ ███ ██ ██ █████ ████ ████ █████ ████ ██", " ██ ██ ███ ██ ██ █████ ████ ████ █████ ████ ██",
@ -337,7 +335,7 @@ mod tests {
" ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██████ ██ ██", " ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██████ ██ ██",
" ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █ ██ ██ ██", " ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █ ██ ██ ██",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -348,7 +346,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 16)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 16));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"██ ██ ███ █ ██ ", "██ ██ ███ █ ██ ",
"███ ███ ██ ██ ", "███ ███ ██ ██ ",
"███████ ██ ██ ██ █████ ███ ", "███████ ██ ██ ██ █████ ███ ",
@ -366,7 +364,7 @@ mod tests {
"███████ ████ ██ ██ ████ █████ ", "███████ ████ ██ ██ ████ █████ ",
" ", " ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -378,18 +376,17 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 48, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 48, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" ████ █ ███ ███ ", " ████ █ ███ ███ ".bold(),
"██ ██ ██ ██ ██ ", "██ ██ ██ ██ ██ ".bold(),
"███ █████ ██ ██ ██ ████ ██ ", "███ █████ ██ ██ ██ ████ ██ ".bold(),
" ███ ██ ██ ██ ██ ██ ██ █████ ", " ███ ██ ██ ██ ██ ██ ██ █████ ".bold(),
" ███ ██ ██ ██ ██ ██████ ██ ██ ", " ███ ██ ██ ██ ██ ██████ ██ ██ ".bold(),
"██ ██ ██ █ █████ ██ ██ ██ ██ ", "██ ██ ██ █ █████ ██ ██ ██ ██ ".bold(),
" ████ ██ ██ ████ ████ ███ ██ ", " ████ ██ ██ ████ ████ ███ ██ ".bold(),
" █████ ", " █████ ".bold(),
]); ]);
expected.set_style(Rect::new(0, 0, 48, 8), Style::new().bold()); assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -404,7 +401,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 24)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 24));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"██████ ███ ", "██████ ███ ",
" ██ ██ ██ ", " ██ ██ ██ ",
" ██ ██ ████ ██ ", " ██ ██ ████ ██ ",
@ -433,7 +430,7 @@ mod tests {
expected.set_style(Rect::new(0, 0, 24, 8), Style::new().red()); expected.set_style(Rect::new(0, 0, 24, 8), Style::new().red());
expected.set_style(Rect::new(0, 8, 40, 8), Style::new().green()); expected.set_style(Rect::new(0, 8, 40, 8), Style::new().green());
expected.set_style(Rect::new(0, 16, 32, 8), Style::new().blue()); expected.set_style(Rect::new(0, 16, 32, 8), Style::new().blue());
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -445,13 +442,13 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 80, 4)); let mut buf = Buffer::empty(Rect::new(0, 0, 80, 4));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▄█▀▀█▄ ▀▀ ▀██ ▀██▀ ▀▀ ", "▄█▀▀█▄ ▀▀ ▀██ ▀██▀ ▀▀ ",
"▀██▄ ▀██ ██▀▀█▄ ▄█▀▀▄█▀ ██ ▄█▀▀█▄ ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ", "▀██▄ ▀██ ██▀▀█▄ ▄█▀▀▄█▀ ██ ▄█▀▀█▄ ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ",
"▄▄ ▀██ ██ ██ ██ ▀█▄▄██ ██ ██▀▀▀▀ ██ ▄█ ██ ██ ██ ██▀▀▀▀ ", "▄▄ ▀██ ██ ██ ██ ▀█▄▄██ ██ ██▀▀▀▀ ██ ▄█ ██ ██ ██ ██▀▀▀▀ ",
" ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ", " ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -463,12 +460,12 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 70, 3)); let mut buf = Buffer::empty(Rect::new(0, 0, 70, 3));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"█▀██▀█ ▄█ ▀██", "█▀██▀█ ▄█ ▀██",
" ██ ▀█▄█▀█▄ ██ ██ ██▀▀█▄ ▄█▀▀█▄ ▀▀▀█▄ ▀██▀▀ ▄█▀▀█▄ ▄▄▄██", " ██ ▀█▄█▀█▄ ██ ██ ██▀▀█▄ ▄█▀▀█▄ ▀▀▀█▄ ▀██▀▀ ▄█▀▀█▄ ▄▄▄██",
" ██ ██ ▀▀ ██ ██ ██ ██ ██ ▄▄ ▄█▀▀██ ██ ▄ ██▀▀▀▀ ██ ██", " ██ ██ ▀▀ ██ ██ ██ ██ ██ ▄▄ ▄█▀▀██ ██ ▄ ██▀▀▀▀ ██ ██",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -480,7 +477,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"██▄ ▄██ ▀██ ▄█ ▀▀ ", "██▄ ▄██ ▀██ ▄█ ▀▀ ",
"███████ ██ ██ ██ ▀██▀▀ ▀██ ", "███████ ██ ██ ██ ▀██▀▀ ▀██ ",
"██ ▀ ██ ██ ██ ██ ██ ▄ ██ ", "██ ▀ ██ ██ ██ ██ ██ ▄ ██ ",
@ -490,7 +487,7 @@ mod tests {
" ██ ▄█ ██ ██ ██ ██▀▀▀▀ ▀▀▀█▄ ", " ██ ▄█ ██ ██ ██ ██▀▀▀▀ ▀▀▀█▄ ",
"▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀▀▀▀ ", "▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀▀▀▀ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -503,14 +500,13 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 48, 4)); let mut buf = Buffer::empty(Rect::new(0, 0, 48, 4));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▄█▀▀█▄ ▄█ ▀██ ▀██ ", "▄█▀▀█▄ ▄█ ▀██ ▀██ ".bold(),
"▀██▄ ▀██▀▀ ██ ██ ██ ▄█▀▀█▄ ▄▄▄██ ", "▀██▄ ▀██▀▀ ██ ██ ██ ▄█▀▀█▄ ▄▄▄██ ".bold(),
"▄▄ ▀██ ██ ▄ ▀█▄▄██ ██ ██▀▀▀▀ ██ ██ ", "▄▄ ▀██ ██ ▄ ▀█▄▄██ ██ ██▀▀▀▀ ██ ██ ".bold(),
" ▀▀▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ", " ▀▀▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ".bold(),
]); ]);
expected.set_style(Rect::new(0, 0, 48, 4), Style::new().bold()); assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -526,7 +522,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 12)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 12));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"▀██▀▀█▄ ▀██ ", "▀██▀▀█▄ ▀██ ",
" ██▄▄█▀ ▄█▀▀█▄ ▄▄▄██ ", " ██▄▄█▀ ▄█▀▀█▄ ▄▄▄██ ",
" ██ ▀█▄ ██▀▀▀▀ ██ ██ ", " ██ ▀█▄ ██▀▀▀▀ ██ ██ ",
@ -543,7 +539,7 @@ mod tests {
expected.set_style(Rect::new(0, 0, 24, 4), Style::new().red()); expected.set_style(Rect::new(0, 0, 24, 4), Style::new().red());
expected.set_style(Rect::new(0, 4, 40, 4), Style::new().green()); expected.set_style(Rect::new(0, 4, 40, 4), Style::new().green());
expected.set_style(Rect::new(0, 8, 32, 4), Style::new().blue()); expected.set_style(Rect::new(0, 8, 32, 4), Style::new().blue());
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -555,7 +551,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▐█▌ █ ▐█ ██ █ ", "▐█▌ █ ▐█ ██ █ ",
"█ █ █ ▐▌ ", "█ █ █ ▐▌ ",
"█▌ ▐█ ██▌ ▐█▐▌ █ ▐█▌ ▐▌ ▐█ ██▌ ▐█▌ ", "█▌ ▐█ ██▌ ▐█▐▌ █ ▐█▌ ▐▌ ▐█ ██▌ ▐█▌ ",
@ -565,7 +561,7 @@ mod tests {
"▐█▌ ▐█▌ █ █ █ ▐█▌ ▐█▌ ███▌▐█▌ █ █ ▐█▌ ", "▐█▌ ▐█▌ █ █ █ ▐█▌ ▐█▌ ███▌▐█▌ █ █ ▐█▌ ",
" ██▌ ", " ██▌ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -577,7 +573,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 35, 6)); let mut buf = Buffer::empty(Rect::new(0, 0, 35, 6));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"███ ▐ ▐█", "███ ▐ ▐█",
"▌█▐ █ █", "▌█▐ █ █",
" █ █▐█ █ █ ██▌ ▐█▌ ▐█▌ ▐██ ▐█▌ █", " █ █▐█ █ █ ██▌ ▐█▌ ▐█▌ ▐██ ▐█▌ █",
@ -585,7 +581,7 @@ mod tests {
" █ ▐▌▐▌█ █ █ █ █ ▐██ █ ███ █ █", " █ ▐▌▐▌█ █ █ █ █ ▐██ █ ███ █ █",
" █ ▐▌ █ █ █ █ █ █ █ █ █▐ █ █ █", " █ ▐▌ █ █ █ █ █ █ █ █ █▐ █ █ █",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -597,7 +593,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 16)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 16));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"█ ▐▌ ▐█ ▐ █ ", "█ ▐▌ ▐█ ▐ █ ",
"█▌█▌ █ █ ", "█▌█▌ █ █ ",
"███▌█ █ █ ▐██ ▐█ ", "███▌█ █ █ ▐██ ▐█ ",
@ -615,7 +611,7 @@ mod tests {
"███▌▐█▌ █ █ ▐█▌ ██▌ ", "███▌▐█▌ █ █ ▐█▌ ██▌ ",
" ", " ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -628,18 +624,17 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 24, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 24, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▐█▌ ▐ ▐█ ▐█ ", "▐█▌ ▐ ▐█ ▐█ ".bold(),
"█ █ █ █ █ ", "█ █ █ █ █ ".bold(),
"█▌ ▐██ █ █ █ ▐█▌ █ ", "█▌ ▐██ █ █ █ ▐█▌ █ ".bold(),
"▐█ █ █ █ █ █ █ ▐██ ", "▐█ █ █ █ █ █ █ ▐██ ".bold(),
" ▐█ █ █ █ █ ███ █ █ ", " ▐█ █ █ █ █ ███ █ █ ".bold(),
"█ █ █▐ ▐██ █ █ █ █ ", "█ █ █▐ ▐██ █ █ █ █ ".bold(),
"▐█▌ ▐▌ █ ▐█▌ ▐█▌ ▐█▐▌", "▐█▌ ▐▌ █ ▐█▌ ▐█▌ ▐█▐▌".bold(),
" ██▌ ", " ██▌ ".bold(),
]); ]);
expected.set_style(Rect::new(0, 0, 24, 8), Style::new().bold()); assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -655,7 +650,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 24)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 24));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"███ ▐█ ", "███ ▐█ ",
"▐▌▐▌ █ ", "▐▌▐▌ █ ",
"▐▌▐▌▐█▌ █ ", "▐▌▐▌▐█▌ █ ",
@ -684,7 +679,7 @@ mod tests {
expected.set_style(Rect::new(0, 0, 12, 8), Style::new().red()); expected.set_style(Rect::new(0, 0, 12, 8), Style::new().red());
expected.set_style(Rect::new(0, 8, 20, 8), Style::new().green()); expected.set_style(Rect::new(0, 8, 20, 8), Style::new().green());
expected.set_style(Rect::new(0, 16, 16, 8), Style::new().blue()); expected.set_style(Rect::new(0, 16, 16, 8), Style::new().blue());
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -717,13 +712,13 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4)); let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▟▀▙ ▀ ▝█ ▜▛ ▀ ", "▟▀▙ ▀ ▝█ ▜▛ ▀ ",
"▜▙ ▝█ █▀▙ ▟▀▟▘ █ ▟▀▙ ▐▌ ▝█ █▀▙ ▟▀▙ ", "▜▙ ▝█ █▀▙ ▟▀▟▘ █ ▟▀▙ ▐▌ ▝█ █▀▙ ▟▀▙ ",
"▄▝█ █ █ █ ▜▄█ █ █▀▀ ▐▌▗▌ █ █ █ █▀▀ ", "▄▝█ █ █ █ ▜▄█ █ █▀▀ ▐▌▗▌ █ █ █ █▀▀ ",
"▝▀▘ ▝▀▘ ▀ ▀ ▄▄▛ ▝▀▘ ▝▀▘ ▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ", "▝▀▘ ▝▀▘ ▀ ▀ ▄▄▛ ▝▀▘ ▝▀▘ ▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -735,12 +730,12 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 35, 3)); let mut buf = Buffer::empty(Rect::new(0, 0, 35, 3));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▛█▜ ▟ ▝█", "▛█▜ ▟ ▝█",
" █ ▜▟▜▖█ █ █▀▙ ▟▀▙ ▝▀▙ ▝█▀ ▟▀▙ ▗▄█", " █ ▜▟▜▖█ █ █▀▙ ▟▀▙ ▝▀▙ ▝█▀ ▟▀▙ ▗▄█",
" █ ▐▌▝▘█ █ █ █ █ ▄ ▟▀█ █▗ █▀▀ █ █", " █ ▐▌▝▘█ █ █ █ █ ▄ ▟▀█ █▗ █▀▀ █ █",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -752,7 +747,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 8)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 8));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"█▖▟▌ ▝█ ▟ ▀ ", "█▖▟▌ ▝█ ▟ ▀ ",
"███▌█ █ █ ▝█▀ ▝█ ", "███▌█ █ █ ▝█▀ ▝█ ",
"█▝▐▌█ █ █ █▗ █ ", "█▝▐▌█ █ █ █▗ █ ",
@ -762,7 +757,7 @@ mod tests {
"▐▌▗▌ █ █ █ █▀▀ ▝▀▙ ", "▐▌▗▌ █ █ █ █▀▀ ▝▀▙ ",
"▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ▀▀▘ ", "▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ▀▀▘ ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -775,14 +770,13 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 24, 4)); let mut buf = Buffer::empty(Rect::new(0, 0, 24, 4));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"▟▀▙ ▟ ▝█ ▝█ ", "▟▀▙ ▟ ▝█ ▝█ ".bold(),
"▜▙ ▝█▀ █ █ █ ▟▀▙ ▗▄█ ", "▜▙ ▝█▀ █ █ █ ▟▀▙ ▗▄█ ".bold(),
"▄▝█ █▗ ▜▄█ █ █▀▀ █ █ ", "▄▝█ █▗ ▜▄█ █ █▀▀ █ █ ".bold(),
"▝▀▘ ▝▘ ▄▄▛ ▝▀▘ ▝▀▘ ▝▀▝▘", "▝▀▘ ▝▘ ▄▄▛ ▝▀▘ ▝▀▘ ▝▀▝▘".bold(),
]); ]);
expected.set_style(Rect::new(0, 0, 24, 4), Style::new().bold()); assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
Ok(()) Ok(())
} }
@ -798,7 +792,7 @@ mod tests {
.build()?; .build()?;
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 12)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 12));
big_text.render(buf.area, &mut buf); big_text.render(buf.area, &mut buf);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"▜▛▜▖ ▝█ ", "▜▛▜▖ ▝█ ",
"▐▙▟▘▟▀▙ ▗▄█ ", "▐▙▟▘▟▀▙ ▗▄█ ",
"▐▌▜▖█▀▀ █ █ ", "▐▌▜▖█▀▀ █ █ ",
@ -815,7 +809,7 @@ mod tests {
expected.set_style(Rect::new(0, 0, 12, 4), Style::new().red()); expected.set_style(Rect::new(0, 0, 12, 4), Style::new().red());
expected.set_style(Rect::new(0, 4, 20, 4), Style::new().green()); expected.set_style(Rect::new(0, 4, 20, 4), Style::new().green());
expected.set_style(Rect::new(0, 8, 16, 4), Style::new().blue()); expected.set_style(Rect::new(0, 8, 16, 4), Style::new().blue());
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
Ok(()) Ok(())
} }
} }

View file

@ -9,7 +9,6 @@ use std::{
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use crate::{ use crate::{
assert_buffer_eq,
backend::{Backend, ClearType, WindowSize}, backend::{Backend, ClearType, WindowSize},
buffer::{Buffer, Cell}, buffer::{Buffer, Cell},
layout::{Rect, Size}, layout::{Rect, Size},
@ -29,7 +28,7 @@ use crate::{
/// ///
/// let mut backend = TestBackend::new(10, 2); /// let mut backend = TestBackend::new(10, 2);
/// backend.clear()?; /// backend.clear()?;
/// backend.assert_buffer(&Buffer::with_lines(vec![" "; 2])); /// backend.assert_buffer_lines([" "; 2]);
/// # std::io::Result::Ok(()) /// # std::io::Result::Ok(())
/// ``` /// ```
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
@ -96,11 +95,33 @@ impl TestBackend {
} }
/// Asserts that the `TestBackend`'s buffer is equal to the expected buffer. /// Asserts that the `TestBackend`'s buffer is equal to the expected buffer.
/// If the buffers are not equal, a panic occurs with a detailed error message ///
/// showing the differences between the expected and actual buffers. /// This is a shortcut for `assert_eq!(self.buffer(), &expected)`.
///
/// # Panics
/// When they are not equal, a panic occurs with a detailed error message showing the
/// differences between the expected and actual buffers.
#[allow(deprecated)]
#[track_caller] #[track_caller]
pub fn assert_buffer(&self, expected: &Buffer) { pub fn assert_buffer(&self, expected: &Buffer) {
assert_buffer_eq!(&self.buffer, expected); // TODO: use assert_eq!()
crate::assert_buffer_eq!(&self.buffer, expected);
}
/// Asserts that the `TestBackend`'s buffer is equal to the expected lines.
///
/// This is a shortcut for `assert_eq!(self.buffer(), &Buffer::with_lines(expected))`.
///
/// # Panics
/// When they are not equal, a panic occurs with a detailed error message showing the
/// differences between the expected and actual buffers.
#[track_caller]
pub fn assert_buffer_lines<'line, Lines>(&self, expected: Lines)
where
Lines: IntoIterator,
Lines::Item: Into<crate::text::Line<'line>>,
{
self.assert_buffer(&Buffer::with_lines(expected));
} }
} }
@ -245,7 +266,7 @@ mod tests {
TestBackend { TestBackend {
width: 10, width: 10,
height: 2, height: 2,
buffer: Buffer::with_lines(vec![" "; 2]), buffer: Buffer::with_lines([" "; 2]),
cursor: false, cursor: false,
pos: (0, 0), pos: (0, 0),
} }
@ -253,14 +274,14 @@ mod tests {
} }
#[test] #[test]
fn test_buffer_view() { fn test_buffer_view() {
let buffer = Buffer::with_lines(vec!["aaaa"; 2]); let buffer = Buffer::with_lines(["aaaa"; 2]);
assert_eq!(buffer_view(&buffer), "\"aaaa\"\n\"aaaa\"\n"); assert_eq!(buffer_view(&buffer), "\"aaaa\"\n\"aaaa\"\n");
} }
#[test] #[test]
fn buffer_view_with_overwrites() { fn buffer_view_with_overwrites() {
let multi_byte_char = "👨‍👩‍👧‍👦"; // renders 8 wide let multi_byte_char = "👨‍👩‍👧‍👦"; // renders 8 wide
let buffer = Buffer::with_lines(vec![multi_byte_char]); let buffer = Buffer::with_lines([multi_byte_char]);
assert_eq!( assert_eq!(
buffer_view(&buffer), buffer_view(&buffer),
format!( format!(
@ -273,29 +294,27 @@ mod tests {
#[test] #[test]
fn buffer() { fn buffer() {
let backend = TestBackend::new(10, 2); let backend = TestBackend::new(10, 2);
assert_eq!(backend.buffer(), &Buffer::with_lines(vec![" "; 2])); backend.assert_buffer_lines([" "; 2]);
} }
#[test] #[test]
fn resize() { fn resize() {
let mut backend = TestBackend::new(10, 2); let mut backend = TestBackend::new(10, 2);
backend.resize(5, 5); backend.resize(5, 5);
assert_eq!(backend.buffer(), &Buffer::with_lines(vec![" "; 5])); backend.assert_buffer_lines([" "; 5]);
} }
#[test] #[test]
fn assert_buffer() { fn assert_buffer() {
let backend = TestBackend::new(10, 2); let backend = TestBackend::new(10, 2);
let buffer = Buffer::with_lines(vec![" "; 2]); backend.assert_buffer_lines([" "; 2]);
backend.assert_buffer(&buffer);
} }
#[test] #[test]
#[should_panic = "buffer contents not equal"] #[should_panic = "buffer contents not equal"]
fn assert_buffer_panics() { fn assert_buffer_panics() {
let backend = TestBackend::new(10, 2); let backend = TestBackend::new(10, 2);
let buffer = Buffer::with_lines(vec!["aaaaaaaaaa"; 2]); backend.assert_buffer_lines(["aaaaaaaaaa"; 2]);
backend.assert_buffer(&buffer);
} }
#[test] #[test]
@ -311,7 +330,7 @@ mod tests {
cell.set_symbol("a"); cell.set_symbol("a");
backend.draw([(0, 0, &cell)].into_iter()).unwrap(); backend.draw([(0, 0, &cell)].into_iter()).unwrap();
backend.draw([(0, 1, &cell)].into_iter()).unwrap(); backend.draw([(0, 1, &cell)].into_iter()).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec!["a "; 2])); backend.assert_buffer_lines(["a "; 2]);
} }
#[test] #[test]
@ -343,24 +362,19 @@ mod tests {
#[test] #[test]
fn clear() { fn clear() {
let mut backend = TestBackend::new(10, 4); let mut backend = TestBackend::new(4, 2);
let mut cell = Cell::default(); let mut cell = Cell::default();
cell.set_symbol("a"); cell.set_symbol("a");
backend.draw([(0, 0, &cell)].into_iter()).unwrap(); backend.draw([(0, 0, &cell)].into_iter()).unwrap();
backend.draw([(0, 1, &cell)].into_iter()).unwrap(); backend.draw([(0, 1, &cell)].into_iter()).unwrap();
backend.clear().unwrap(); backend.clear().unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([" ", " "]);
" ",
" ",
" ",
" ",
]));
} }
#[test] #[test]
fn clear_region_all() { fn clear_region_all() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
@ -369,19 +383,19 @@ mod tests {
]); ]);
backend.clear_region(ClearType::All).unwrap(); backend.clear_region(ClearType::All).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
])); ]);
} }
#[test] #[test]
fn clear_region_after_cursor() { fn clear_region_after_cursor() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
@ -391,19 +405,19 @@ mod tests {
backend.set_cursor(3, 2).unwrap(); backend.set_cursor(3, 2).unwrap();
backend.clear_region(ClearType::AfterCursor).unwrap(); backend.clear_region(ClearType::AfterCursor).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaa ", "aaaa ",
" ", " ",
" ", " ",
])); ]);
} }
#[test] #[test]
fn clear_region_before_cursor() { fn clear_region_before_cursor() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
@ -413,19 +427,19 @@ mod tests {
backend.set_cursor(5, 3).unwrap(); backend.set_cursor(5, 3).unwrap();
backend.clear_region(ClearType::BeforeCursor).unwrap(); backend.clear_region(ClearType::BeforeCursor).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
" ", " ",
" ", " ",
" ", " ",
" aaaaa", " aaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
])); ]);
} }
#[test] #[test]
fn clear_region_current_line() { fn clear_region_current_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
@ -435,19 +449,19 @@ mod tests {
backend.set_cursor(3, 1).unwrap(); backend.set_cursor(3, 1).unwrap();
backend.clear_region(ClearType::CurrentLine).unwrap(); backend.clear_region(ClearType::CurrentLine).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
" ", " ",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
])); ]);
} }
#[test] #[test]
fn clear_region_until_new_line() { fn clear_region_until_new_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
@ -457,19 +471,19 @@ mod tests {
backend.set_cursor(3, 0).unwrap(); backend.set_cursor(3, 0).unwrap();
backend.clear_region(ClearType::UntilNewLine).unwrap(); backend.clear_region(ClearType::UntilNewLine).unwrap();
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"aaa ", "aaa ",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
"aaaaaaaaaa", "aaaaaaaaaa",
])); ]);
} }
#[test] #[test]
fn append_lines_not_at_last_line() { fn append_lines_not_at_last_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -495,19 +509,19 @@ mod tests {
assert_eq!(backend.get_cursor().unwrap(), (4, 4)); assert_eq!(backend.get_cursor().unwrap(), (4, 4));
// As such the buffer should remain unchanged // As such the buffer should remain unchanged
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
"dddddddddd", "dddddddddd",
"eeeeeeeeee", "eeeeeeeeee",
])); ]);
} }
#[test] #[test]
fn append_lines_at_last_line() { fn append_lines_at_last_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -521,7 +535,7 @@ mod tests {
backend.append_lines(1).unwrap(); backend.append_lines(1).unwrap();
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
"dddddddddd", "dddddddddd",
@ -537,7 +551,7 @@ mod tests {
#[test] #[test]
fn append_multiple_lines_not_at_last_line() { fn append_multiple_lines_not_at_last_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -554,19 +568,19 @@ mod tests {
assert_eq!(backend.get_cursor().unwrap(), (1, 4)); assert_eq!(backend.get_cursor().unwrap(), (1, 4));
// As such the buffer should remain unchanged // As such the buffer should remain unchanged
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
"dddddddddd", "dddddddddd",
"eeeeeeeeee", "eeeeeeeeee",
])); ]);
} }
#[test] #[test]
fn append_multiple_lines_past_last_line() { fn append_multiple_lines_past_last_line() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -579,19 +593,19 @@ mod tests {
backend.append_lines(3).unwrap(); backend.append_lines(3).unwrap();
assert_eq!(backend.get_cursor().unwrap(), (1, 4)); assert_eq!(backend.get_cursor().unwrap(), (1, 4));
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"cccccccccc", "cccccccccc",
"dddddddddd", "dddddddddd",
"eeeeeeeeee", "eeeeeeeeee",
" ", " ",
" ", " ",
])); ]);
} }
#[test] #[test]
fn append_multiple_lines_where_cursor_at_end_appends_height_lines() { fn append_multiple_lines_where_cursor_at_end_appends_height_lines() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -604,19 +618,19 @@ mod tests {
backend.append_lines(5).unwrap(); backend.append_lines(5).unwrap();
assert_eq!(backend.get_cursor().unwrap(), (1, 4)); assert_eq!(backend.get_cursor().unwrap(), (1, 4));
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
])); ]);
} }
#[test] #[test]
fn append_multiple_lines_where_cursor_appends_height_lines() { fn append_multiple_lines_where_cursor_appends_height_lines() {
let mut backend = TestBackend::new(10, 5); let mut backend = TestBackend::new(10, 5);
backend.buffer = Buffer::with_lines(vec![ backend.buffer = Buffer::with_lines([
"aaaaaaaaaa", "aaaaaaaaaa",
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
@ -629,13 +643,13 @@ mod tests {
backend.append_lines(5).unwrap(); backend.append_lines(5).unwrap();
assert_eq!(backend.get_cursor().unwrap(), (1, 4)); assert_eq!(backend.get_cursor().unwrap(), (1, 4));
backend.assert_buffer(&Buffer::with_lines(vec![ backend.assert_buffer_lines([
"bbbbbbbbbb", "bbbbbbbbbb",
"cccccccccc", "cccccccccc",
"dddddddddd", "dddddddddd",
"eeeeeeeeee", "eeeeeeeeee",
" ", " ",
])); ]);
} }
#[test] #[test]

View file

@ -1,57 +1,44 @@
/// Assert that two buffers are equal by comparing their areas and content. /// Assert that two buffers are equal by comparing their areas and content.
/// ///
/// On panic, displays the areas or the content and a diff of the contents. /// # Panics
/// When the buffers differ this method panics and displays the differences similar to
/// `assert_eq!()`.
#[deprecated = "use assert_eq!(&actual, &expected)"]
#[macro_export] #[macro_export]
macro_rules! assert_buffer_eq { macro_rules! assert_buffer_eq {
($actual_expr:expr, $expected_expr:expr) => { ($actual_expr:expr, $expected_expr:expr) => {
match (&$actual_expr, &$expected_expr) { match (&$actual_expr, &$expected_expr) {
(actual, expected) => { (actual, expected) => {
if actual.area != expected.area { assert!(
panic!( actual.area == expected.area,
indoc::indoc!( "buffer areas not equal\nexpected: {expected:?}\nactual: {actual:?}",
" );
buffer areas not equal let nice_diff = expected
expected: {:?} .diff(actual)
actual: {:?}" .into_iter()
), .enumerate()
expected, actual .map(|(i, (x, y, cell))| {
); let expected_cell = expected.get(x, y);
} format!("{i}: at ({x}, {y})\n expected: {expected_cell:?}\n actual: {cell:?}")
let diff = expected.diff(&actual); })
if !diff.is_empty() { .collect::<Vec<String>>()
let nice_diff = diff .join("\n");
.iter() assert!(
.enumerate() nice_diff.is_empty(),
.map(|(i, (x, y, cell))| { "buffer contents not equal\nexpected: {expected:?}\nactual: {actual:?}\ndiff:\n{nice_diff}",
let expected_cell = expected.get(*x, *y); );
indoc::formatdoc! {"
{i}: at ({x}, {y})
expected: {expected_cell:?}
actual: {cell:?}
"}
})
.collect::<Vec<String>>()
.join("\n");
panic!(
indoc::indoc!(
"
buffer contents not equal
expected: {:?}
actual: {:?}
diff:
{}"
),
expected, actual, nice_diff
);
}
// shouldn't get here, but this guards against future behavior // shouldn't get here, but this guards against future behavior
// that changes equality but not area or content // that changes equality but not area or content
assert_eq!(actual, expected, "buffers not equal"); assert_eq!(
actual, expected,
"buffers are not equal in an unexpected way. Please open an issue about this."
);
} }
} }
}; };
} }
#[allow(deprecated)]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*; use crate::prelude::*;

View file

@ -452,7 +452,6 @@ mod tests {
use rstest::{fixture, rstest}; use rstest::{fixture, rstest};
use super::*; use super::*;
use crate::assert_buffer_eq;
fn cell(s: &str) -> Cell { fn cell(s: &str) -> Cell {
let mut cell = Cell::default(); let mut cell = Cell::default();
@ -580,27 +579,27 @@ mod tests {
// Zero-width // Zero-width
buffer.set_stringn(0, 0, "aaa", 0, Style::default()); buffer.set_stringn(0, 0, "aaa", 0, Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" "])); assert_eq!(buffer, Buffer::with_lines([" "]));
buffer.set_string(0, 0, "aaa", Style::default()); buffer.set_string(0, 0, "aaa", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["aaa "])); assert_eq!(buffer, Buffer::with_lines(["aaa "]));
// Width limit: // Width limit:
buffer.set_stringn(0, 0, "bbbbbbbbbbbbbb", 4, Style::default()); buffer.set_stringn(0, 0, "bbbbbbbbbbbbbb", 4, Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["bbbb "])); assert_eq!(buffer, Buffer::with_lines(["bbbb "]));
buffer.set_string(0, 0, "12345", Style::default()); buffer.set_string(0, 0, "12345", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["12345"])); assert_eq!(buffer, Buffer::with_lines(["12345"]));
// Width truncation: // Width truncation:
buffer.set_string(0, 0, "123456", Style::default()); buffer.set_string(0, 0, "123456", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["12345"])); assert_eq!(buffer, Buffer::with_lines(["12345"]));
// multi-line // multi-line
buffer = Buffer::empty(Rect::new(0, 0, 5, 2)); buffer = Buffer::empty(Rect::new(0, 0, 5, 2));
buffer.set_string(0, 0, "12345", Style::default()); buffer.set_string(0, 0, "12345", Style::default());
buffer.set_string(0, 1, "67890", Style::default()); buffer.set_string(0, 1, "67890", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["12345", "67890"])); assert_eq!(buffer, Buffer::with_lines(["12345", "67890"]));
} }
#[test] #[test]
@ -611,7 +610,7 @@ mod tests {
// multi-width overwrite // multi-width overwrite
buffer.set_string(0, 0, "aaaaa", Style::default()); buffer.set_string(0, 0, "aaaaa", Style::default());
buffer.set_string(0, 0, "称号", Style::default()); buffer.set_string(0, 0, "称号", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["称号a"])); assert_eq!(buffer, Buffer::with_lines(["称号a"]));
} }
#[test] #[test]
@ -622,12 +621,12 @@ mod tests {
// Leading grapheme with zero width // Leading grapheme with zero width
let s = "\u{1}a"; let s = "\u{1}a";
buffer.set_stringn(0, 0, s, 1, Style::default()); buffer.set_stringn(0, 0, s, 1, Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["a"])); assert_eq!(buffer, Buffer::with_lines(["a"]));
// Trailing grapheme with zero with // Trailing grapheme with zero with
let s = "a\u{1}"; let s = "a\u{1}";
buffer.set_stringn(0, 0, s, 1, Style::default()); buffer.set_stringn(0, 0, s, 1, Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["a"])); assert_eq!(buffer, Buffer::with_lines(["a"]));
} }
#[test] #[test]
@ -635,11 +634,11 @@ mod tests {
let area = Rect::new(0, 0, 5, 1); let area = Rect::new(0, 0, 5, 1);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
buffer.set_string(0, 0, "コン", Style::default()); buffer.set_string(0, 0, "コン", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["コン "])); assert_eq!(buffer, Buffer::with_lines(["コン "]));
// Only 1 space left. // Only 1 space left.
buffer.set_string(0, 0, "コンピ", Style::default()); buffer.set_string(0, 0, "コンピ", Style::default());
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["コン "])); assert_eq!(buffer, Buffer::with_lines(["コン "]));
} }
#[fixture] #[fixture]
@ -664,7 +663,7 @@ mod tests {
// set_line // set_line
let mut expected_buffer = Buffer::empty(small_one_line_buffer.area); let mut expected_buffer = Buffer::empty(small_one_line_buffer.area);
expected_buffer.set_string(0, 0, expected, Style::default()); expected_buffer.set_string(0, 0, expected, Style::default());
assert_buffer_eq!(small_one_line_buffer, expected_buffer); assert_eq!(small_one_line_buffer, expected_buffer);
} }
#[rstest] #[rstest]
@ -705,28 +704,39 @@ mod tests {
#[test] #[test]
fn set_style() { fn set_style() {
let mut buffer = Buffer::with_lines(vec!["aaaaa", "bbbbb", "ccccc"]); let mut buffer = Buffer::with_lines(["aaaaa", "bbbbb", "ccccc"]);
buffer.set_style(Rect::new(0, 1, 5, 1), Style::new().red()); buffer.set_style(Rect::new(0, 1, 5, 1), Style::new().red());
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec!["aaaaa".into(), "bbbbb".red(), "ccccc".into(),]) "aaaaa".into(),
); "bbbbb".red(),
"ccccc".into(),
]);
assert_eq!(buffer, expected);
} }
#[test] #[test]
fn set_style_does_not_panic_when_out_of_area() { fn set_style_does_not_panic_when_out_of_area() {
let mut buffer = Buffer::with_lines(vec!["aaaaa", "bbbbb", "ccccc"]); let mut buffer = Buffer::with_lines(["aaaaa", "bbbbb", "ccccc"]);
buffer.set_style(Rect::new(0, 1, 10, 3), Style::new().red()); buffer.set_style(Rect::new(0, 1, 10, 3), Style::new().red());
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec!["aaaaa".into(), "bbbbb".red(), "ccccc".red(),]) "aaaaa".into(),
); "bbbbb".red(),
"ccccc".red(),
]);
assert_eq!(buffer, expected);
} }
#[test] #[test]
fn with_lines() { fn with_lines() {
let buffer = #[rustfmt::skip]
Buffer::with_lines(vec!["┌────────┐", "│コンピュ│", "│ーa 上で│", "└────────┘"]); let buffer = Buffer::with_lines([
"┌────────┐",
"│コンピュ│",
"│ーa 上で│",
"└────────┘",
]);
assert_eq!(buffer.area.x, 0); assert_eq!(buffer.area.x, 0);
assert_eq!(buffer.area.y, 0); assert_eq!(buffer.area.y, 0);
assert_eq!(buffer.area.width, 10); assert_eq!(buffer.area.width, 10);
@ -762,14 +772,14 @@ mod tests {
#[test] #[test]
fn diff_single_width() { fn diff_single_width() {
let prev = Buffer::with_lines(vec![ let prev = Buffer::with_lines([
" ", " ",
"┌Title─┐ ", "┌Title─┐ ",
"│ │ ", "│ │ ",
"│ │ ", "│ │ ",
"└──────┘ ", "└──────┘ ",
]); ]);
let next = Buffer::with_lines(vec![ let next = Buffer::with_lines([
" ", " ",
"┌TITLE─┐ ", "┌TITLE─┐ ",
"│ │ ", "│ │ ",
@ -791,11 +801,11 @@ mod tests {
#[test] #[test]
#[rustfmt::skip] #[rustfmt::skip]
fn diff_multi_width() { fn diff_multi_width() {
let prev = Buffer::with_lines(vec![ let prev = Buffer::with_lines([
"┌Title─┐ ", "┌Title─┐ ",
"└──────┘ ", "└──────┘ ",
]); ]);
let next = Buffer::with_lines(vec![ let next = Buffer::with_lines([
"┌称号──┐ ", "┌称号──┐ ",
"└──────┘ ", "└──────┘ ",
]); ]);
@ -814,8 +824,8 @@ mod tests {
#[test] #[test]
fn diff_multi_width_offset() { fn diff_multi_width_offset() {
let prev = Buffer::with_lines(vec!["┌称号──┐"]); let prev = Buffer::with_lines(["┌称号──┐"]);
let next = Buffer::with_lines(vec!["┌─称号─┐"]); let next = Buffer::with_lines(["┌─称号─┐"]);
let diff = prev.diff(&next); let diff = prev.diff(&next);
assert_eq!( assert_eq!(
@ -826,8 +836,8 @@ mod tests {
#[test] #[test]
fn diff_skip() { fn diff_skip() {
let prev = Buffer::with_lines(vec!["123"]); let prev = Buffer::with_lines(["123"]);
let mut next = Buffer::with_lines(vec!["456"]); let mut next = Buffer::with_lines(["456"]);
for i in 1..3 { for i in 1..3 {
next.content[i].set_skip(true); next.content[i].set_skip(true);
} }
@ -857,7 +867,7 @@ mod tests {
Cell::default().set_symbol("2"), Cell::default().set_symbol("2"),
); );
one.merge(&two); one.merge(&two);
assert_buffer_eq!(one, Buffer::with_lines(vec!["11", "11", "22", "22"])); assert_eq!(one, Buffer::with_lines(["11", "11", "22", "22"]));
} }
#[test] #[test]
@ -881,10 +891,7 @@ mod tests {
Cell::default().set_symbol("2"), Cell::default().set_symbol("2"),
); );
one.merge(&two); one.merge(&two);
assert_buffer_eq!( assert_eq!(one, Buffer::with_lines(["22 ", "22 ", " 11", " 11"]));
one,
Buffer::with_lines(vec!["22 ", "22 ", " 11", " 11"])
);
} }
#[test] #[test]
@ -908,14 +915,14 @@ mod tests {
Cell::default().set_symbol("2"), Cell::default().set_symbol("2"),
); );
one.merge(&two); one.merge(&two);
let mut merged = Buffer::with_lines(vec!["222 ", "222 ", "2221", "2221"]); let mut merged = Buffer::with_lines(["222 ", "222 ", "2221", "2221"]);
merged.area = Rect { merged.area = Rect {
x: 1, x: 1,
y: 1, y: 1,
width: 4, width: 4,
height: 4, height: 4,
}; };
assert_buffer_eq!(one, merged); assert_eq!(one, merged);
} }
#[test] #[test]
@ -974,6 +981,6 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 3, 2)); let mut buf = Buffer::empty(Rect::new(0, 0, 3, 2));
buf.set_string(0, 0, "foo", Style::new().red()); buf.set_string(0, 0, "foo", Style::new().red());
buf.set_string(0, 1, "bar", Style::new().blue()); buf.set_string(0, 1, "bar", Style::new().blue());
assert_eq!(buf, Buffer::with_lines(vec!["foo".red(), "bar".blue()])); assert_eq!(buf, Buffer::with_lines(["foo".red(), "bar".blue()]));
} }
} }

View file

@ -1334,7 +1334,6 @@ mod tests {
use rstest::rstest; use rstest::rstest;
use crate::{ use crate::{
assert_buffer_eq,
layout::flex::Flex, layout::flex::Flex,
prelude::{Constraint::*, *}, prelude::{Constraint::*, *},
widgets::Paragraph, widgets::Paragraph,
@ -1361,8 +1360,7 @@ mod tests {
let s = c.to_string().repeat(area.width as usize); let s = c.to_string().repeat(area.width as usize);
Paragraph::new(s).render(layout[i], &mut buffer); Paragraph::new(s).render(layout[i], &mut buffer);
} }
let expected = Buffer::with_lines(vec![expected]); assert_eq!(buffer, Buffer::with_lines([expected]));
assert_buffer_eq!(buffer, expected);
} }
#[rstest] #[rstest]

View file

@ -550,6 +550,8 @@ impl From<(Color, Color, Modifier, Modifier)> for Style {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rstest::rstest;
use super::*; use super::*;
#[test] #[test]
@ -606,26 +608,21 @@ mod tests {
} }
} }
#[test] #[rstest]
fn modifier_debug() { #[case(Modifier::empty(), "NONE")]
assert_eq!(format!("{:?}", Modifier::empty()), "NONE"); #[case(Modifier::BOLD, "BOLD")]
assert_eq!(format!("{:?}", Modifier::BOLD), "BOLD"); #[case(Modifier::DIM, "DIM")]
assert_eq!(format!("{:?}", Modifier::DIM), "DIM"); #[case(Modifier::ITALIC, "ITALIC")]
assert_eq!(format!("{:?}", Modifier::ITALIC), "ITALIC"); #[case(Modifier::UNDERLINED, "UNDERLINED")]
assert_eq!(format!("{:?}", Modifier::UNDERLINED), "UNDERLINED"); #[case(Modifier::SLOW_BLINK, "SLOW_BLINK")]
assert_eq!(format!("{:?}", Modifier::SLOW_BLINK), "SLOW_BLINK"); #[case(Modifier::RAPID_BLINK, "RAPID_BLINK")]
assert_eq!(format!("{:?}", Modifier::RAPID_BLINK), "RAPID_BLINK"); #[case(Modifier::REVERSED, "REVERSED")]
assert_eq!(format!("{:?}", Modifier::REVERSED), "REVERSED"); #[case(Modifier::HIDDEN, "HIDDEN")]
assert_eq!(format!("{:?}", Modifier::HIDDEN), "HIDDEN"); #[case(Modifier::CROSSED_OUT, "CROSSED_OUT")]
assert_eq!(format!("{:?}", Modifier::CROSSED_OUT), "CROSSED_OUT"); #[case(Modifier::BOLD | Modifier::DIM, "BOLD | DIM")]
assert_eq!( #[case(Modifier::all(), "BOLD | DIM | ITALIC | UNDERLINED | SLOW_BLINK | RAPID_BLINK | REVERSED | HIDDEN | CROSSED_OUT")]
format!("{:?}", Modifier::BOLD | Modifier::DIM), fn modifier_debug(#[case] modifier: Modifier, #[case] expected: &str) {
"BOLD | DIM" assert_eq!(format!("{modifier:?}"), expected);
);
assert_eq!(
format!("{:?}", Modifier::all()),
"BOLD | DIM | ITALIC | UNDERLINED | SLOW_BLINK | RAPID_BLINK | REVERSED | HIDDEN | CROSSED_OUT"
);
} }
#[test] #[test]

View file

@ -953,7 +953,7 @@ mod tests {
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use super::*; use super::*;
use crate::{assert_buffer_eq, buffer::Cell}; use crate::buffer::Cell;
const BLUE: Style = Style::new().fg(Color::Blue); const BLUE: Style = Style::new().fg(Color::Blue);
const GREEN: Style = Style::new().fg(Color::Green); const GREEN: Style = Style::new().fg(Color::Green);
@ -972,37 +972,36 @@ mod tests {
fn render() { fn render() {
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
hello_world().render(Rect::new(0, 0, 15, 1), &mut buf); hello_world().render(Rect::new(0, 0, 15, 1), &mut buf);
let mut expected = Buffer::with_lines(vec!["Hello world! "]); let mut expected = Buffer::with_lines(["Hello world! "]);
expected.set_style(Rect::new(0, 0, 15, 1), ITALIC); expected.set_style(Rect::new(0, 0, 15, 1), ITALIC);
expected.set_style(Rect::new(0, 0, 6, 1), BLUE); expected.set_style(Rect::new(0, 0, 6, 1), BLUE);
expected.set_style(Rect::new(6, 0, 6, 1), GREEN); expected.set_style(Rect::new(6, 0, 6, 1), GREEN);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[rstest] #[rstest]
fn render_out_of_bounds(hello_world: Line<'static>, mut small_buf: Buffer) { fn render_out_of_bounds(hello_world: Line<'static>, mut small_buf: Buffer) {
let out_of_bounds = Rect::new(20, 20, 10, 1); let out_of_bounds = Rect::new(20, 20, 10, 1);
hello_world.render(out_of_bounds, &mut small_buf); hello_world.render(out_of_bounds, &mut small_buf);
assert_buffer_eq!(small_buf, Buffer::empty(small_buf.area)); assert_eq!(small_buf, Buffer::empty(small_buf.area));
} }
#[test] #[test]
fn render_only_styles_line_area() { fn render_only_styles_line_area() {
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 1));
hello_world().render(Rect::new(0, 0, 15, 1), &mut buf); hello_world().render(Rect::new(0, 0, 15, 1), &mut buf);
let mut expected = Buffer::with_lines(vec!["Hello world! "]); let mut expected = Buffer::with_lines(["Hello world! "]);
expected.set_style(Rect::new(0, 0, 15, 1), ITALIC); expected.set_style(Rect::new(0, 0, 15, 1), ITALIC);
expected.set_style(Rect::new(0, 0, 6, 1), BLUE); expected.set_style(Rect::new(0, 0, 6, 1), BLUE);
expected.set_style(Rect::new(6, 0, 6, 1), GREEN); expected.set_style(Rect::new(6, 0, 6, 1), GREEN);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
fn render_truncates() { fn render_truncates() {
let mut buf = Buffer::empty(Rect::new(0, 0, 10, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 10, 1));
Line::from("Hello world!").render(Rect::new(0, 0, 5, 1), &mut buf); Line::from("Hello world!").render(Rect::new(0, 0, 5, 1), &mut buf);
let expected = Buffer::with_lines(vec!["Hello "]); assert_eq!(buf, Buffer::with_lines(["Hello "]));
assert_buffer_eq!(buf, expected);
} }
#[test] #[test]
@ -1010,11 +1009,11 @@ mod tests {
let line = hello_world().alignment(Alignment::Center); let line = hello_world().alignment(Alignment::Center);
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
line.render(Rect::new(0, 0, 15, 1), &mut buf); line.render(Rect::new(0, 0, 15, 1), &mut buf);
let mut expected = Buffer::with_lines(vec![" Hello world! "]); let mut expected = Buffer::with_lines([" Hello world! "]);
expected.set_style(Rect::new(0, 0, 15, 1), ITALIC); expected.set_style(Rect::new(0, 0, 15, 1), ITALIC);
expected.set_style(Rect::new(1, 0, 6, 1), BLUE); expected.set_style(Rect::new(1, 0, 6, 1), BLUE);
expected.set_style(Rect::new(7, 0, 6, 1), GREEN); expected.set_style(Rect::new(7, 0, 6, 1), GREEN);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1022,11 +1021,11 @@ mod tests {
let line = hello_world().alignment(Alignment::Right); let line = hello_world().alignment(Alignment::Right);
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
line.render(Rect::new(0, 0, 15, 1), &mut buf); line.render(Rect::new(0, 0, 15, 1), &mut buf);
let mut expected = Buffer::with_lines(vec![" Hello world!"]); let mut expected = Buffer::with_lines([" Hello world!"]);
expected.set_style(Rect::new(0, 0, 15, 1), ITALIC); expected.set_style(Rect::new(0, 0, 15, 1), ITALIC);
expected.set_style(Rect::new(3, 0, 6, 1), BLUE); expected.set_style(Rect::new(3, 0, 6, 1), BLUE);
expected.set_style(Rect::new(9, 0, 6, 1), GREEN); expected.set_style(Rect::new(9, 0, 6, 1), GREEN);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1035,7 +1034,7 @@ mod tests {
Line::from("Hello world") Line::from("Hello world")
.left_aligned() .left_aligned()
.render(buf.area, &mut buf); .render(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines(vec!["Hello"])); assert_eq!(buf, Buffer::with_lines(["Hello"]));
} }
#[test] #[test]
@ -1044,7 +1043,7 @@ mod tests {
Line::from("Hello world") Line::from("Hello world")
.right_aligned() .right_aligned()
.render(buf.area, &mut buf); .render(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines(vec!["world"])); assert_eq!(buf, Buffer::with_lines(["world"]));
} }
#[test] #[test]
@ -1053,7 +1052,7 @@ mod tests {
Line::from("Hello world") Line::from("Hello world")
.centered() .centered()
.render(buf.area, &mut buf); .render(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines(["lo wo"])); assert_eq!(buf, Buffer::with_lines(["lo wo"]));
} }
/// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which /// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which
@ -1065,7 +1064,7 @@ mod tests {
); );
let mut buf = Buffer::empty(Rect::new(0, 0, 83, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 83, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([ assert_eq!(buf, Buffer::with_lines([
"🦀 RFC8628 OAuth 2.0 Device Authorization GrantでCLIからGithubのaccess tokenを取得 " "🦀 RFC8628 OAuth 2.0 Device Authorization GrantでCLIからGithubのaccess tokenを取得 "
])); ]));
} }
@ -1102,7 +1101,7 @@ mod tests {
let line = Line::from("1234🦀7890").alignment(alignment); let line = Line::from("1234🦀7890").alignment(alignment);
let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
/// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which /// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which
@ -1155,7 +1154,7 @@ mod tests {
let line = Line::from(value).centered(); let line = Line::from(value).centered();
let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
/// Ensures the rendering also works away from the 0x0 position. /// Ensures the rendering also works away from the 0x0 position.
@ -1173,7 +1172,7 @@ mod tests {
let mut buf = Buffer::filled(Rect::new(0, 0, 10, 1), Cell::default().set_symbol("X")); let mut buf = Buffer::filled(Rect::new(0, 0, 10, 1), Cell::default().set_symbol("X"));
let area = Rect::new(2, 0, 6, 1); let area = Rect::new(2, 0, 6, 1);
line.render_ref(area, &mut buf); line.render_ref(area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
/// When two spans are rendered after each other the first needs to be padded in accordance /// When two spans are rendered after each other the first needs to be padded in accordance
@ -1191,7 +1190,7 @@ mod tests {
// Fill buffer with stuff to ensure the output is indeed padded // Fill buffer with stuff to ensure the output is indeed padded
let mut buf = Buffer::filled(area, Cell::default().set_symbol("X")); let mut buf = Buffer::filled(area, Cell::default().set_symbol("X"));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
/// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which /// Part of a regression test for <https://github.com/ratatui-org/ratatui/issues/1032> which
@ -1222,7 +1221,7 @@ mod tests {
let line = Line::from("🇺🇸1234"); let line = Line::from("🇺🇸1234");
let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, buf_width, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
// Buffer width is `u16`. A line can be longer. // Buffer width is `u16`. A line can be longer.
@ -1246,7 +1245,7 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 32, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 32, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
// Buffer width is `u16`. A single span inside a line can be longer. // Buffer width is `u16`. A single span inside a line can be longer.
@ -1270,7 +1269,7 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 32, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 32, 1));
line.render_ref(buf.area, &mut buf); line.render_ref(buf.area, &mut buf);
assert_buffer_eq!(buf, Buffer::with_lines([expected])); assert_eq!(buf, Buffer::with_lines([expected]));
} }
} }

View file

@ -16,7 +16,7 @@ use super::Text;
/// let password = Masked::new("12345", 'x'); /// let password = Masked::new("12345", 'x');
/// ///
/// Paragraph::new(password).render(buffer.area, &mut buffer); /// Paragraph::new(password).render(buffer.area, &mut buffer);
/// assert_eq!(buffer, Buffer::with_lines(vec!["xxxxx"])); /// assert_eq!(buffer, Buffer::with_lines(["xxxxx"]));
/// ``` /// ```
#[derive(Default, Clone, Eq, PartialEq, Hash)] #[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct Masked<'a> { pub struct Masked<'a> {

View file

@ -565,7 +565,6 @@ mod tests {
use rstest::rstest; use rstest::rstest;
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn render() { fn render() {
@ -573,12 +572,11 @@ mod tests {
let span = Span::styled("test content", style); let span = Span::styled("test content", style);
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
span.render(buf.area, &mut buf); span.render(buf.area, &mut buf);
let expected = Buffer::with_lines([Line::from(vec![
let expected = Buffer::with_lines(vec![Line::from(vec![
"test content".green().on_yellow(), "test content".green().on_yellow(),
" ".into(), " ".into(),
])]); ])]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[rstest] #[rstest]
@ -598,10 +596,11 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 10, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 10, 1));
span.render(Rect::new(0, 0, 5, 1), &mut buf); span.render(Rect::new(0, 0, 5, 1), &mut buf);
let mut expected = Buffer::with_lines(vec![Line::from("test ")]); let expected = Buffer::with_lines([Line::from(vec![
expected.set_style(Rect::new(0, 0, 5, 1), (Color::Green, Color::Yellow)); "test ".green().on_yellow(),
" ".into(),
assert_buffer_eq!(buf, expected); ])]);
assert_eq!(buf, expected);
} }
/// When there is already a style set on the buffer, the style of the span should be /// When there is already a style set on the buffer, the style of the span should be
@ -613,12 +612,11 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
buf.set_style(buf.area, Style::new().italic()); buf.set_style(buf.area, Style::new().italic());
span.render(buf.area, &mut buf); span.render(buf.area, &mut buf);
let expected = Buffer::with_lines([Line::from(vec![
let expected = Buffer::with_lines(vec![Line::from(vec![
"test content".green().on_yellow().italic(), "test content".green().on_yellow().italic(),
" ".italic(), " ".italic(),
])]); ])]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
/// When the span contains a multi-width grapheme, the grapheme will ensure that the cells /// When the span contains a multi-width grapheme, the grapheme will ensure that the cells
@ -629,12 +627,11 @@ mod tests {
let span = Span::styled("test 😃 content", style); let span = Span::styled("test 😃 content", style);
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
span.render(buf.area, &mut buf); span.render(buf.area, &mut buf);
// The existing code in buffer.set_line() handles multi-width graphemes by clearing the // The existing code in buffer.set_line() handles multi-width graphemes by clearing the
// cells of the hidden characters. This test ensures that the existing behavior is // cells of the hidden characters. This test ensures that the existing behavior is
// preserved. // preserved.
let expected = Buffer::with_lines(vec!["test 😃 content".green().on_yellow()]); let expected = Buffer::with_lines(["test 😃 content".green().on_yellow()]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
/// When the span contains a multi-width grapheme that does not fit in the area passed to /// When the span contains a multi-width grapheme that does not fit in the area passed to
@ -647,11 +644,9 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 6, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 6, 1));
span.render(buf.area, &mut buf); span.render(buf.area, &mut buf);
let expected = Buffer::with_lines(vec![Line::from(vec![ let expected =
"test ".green().on_yellow(), Buffer::with_lines([Line::from(vec!["test ".green().on_yellow(), " ".into()])]);
" ".into(), assert_eq!(buf, expected);
])]);
assert_buffer_eq!(buf, expected);
} }
/// When the area passed to render overflows the buffer, the content should be truncated /// When the area passed to render overflows the buffer, the content should be truncated
@ -663,11 +658,11 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 1));
span.render(Rect::new(10, 0, 20, 1), &mut buf); span.render(Rect::new(10, 0, 20, 1), &mut buf);
let expected = Buffer::with_lines(vec![Line::from(vec![ let expected = Buffer::with_lines([Line::from(vec![
" ".into(), " ".into(),
"test ".green().on_yellow(), "test ".green().on_yellow(),
])]); ])]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
} }
} }

View file

@ -962,19 +962,14 @@ mod tests {
mod widget { mod widget {
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn render() { fn render() {
let text = Text::from("foo"); let text = Text::from("foo");
let area = Rect::new(0, 0, 5, 1); let area = Rect::new(0, 0, 5, 1);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
text.render(area, &mut buf); text.render(area, &mut buf);
assert_eq!(buf, Buffer::with_lines(["foo "]));
let expected_buf = Buffer::with_lines(vec!["foo "]);
assert_buffer_eq!(buf, expected_buf);
} }
#[rstest] #[rstest]
@ -987,40 +982,28 @@ mod tests {
#[test] #[test]
fn render_right_aligned() { fn render_right_aligned() {
let text = Text::from("foo").alignment(Alignment::Right); let text = Text::from("foo").alignment(Alignment::Right);
let area = Rect::new(0, 0, 5, 1); let area = Rect::new(0, 0, 5, 1);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
text.render(area, &mut buf); text.render(area, &mut buf);
assert_eq!(buf, Buffer::with_lines([" foo"]));
let expected_buf = Buffer::with_lines(vec![" foo"]);
assert_buffer_eq!(buf, expected_buf);
} }
#[test] #[test]
fn render_centered_odd() { fn render_centered_odd() {
let text = Text::from("foo").alignment(Alignment::Center); let text = Text::from("foo").alignment(Alignment::Center);
let area = Rect::new(0, 0, 5, 1); let area = Rect::new(0, 0, 5, 1);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
text.render(area, &mut buf); text.render(area, &mut buf);
assert_eq!(buf, Buffer::with_lines([" foo "]));
let expected_buf = Buffer::with_lines(vec![" foo "]);
assert_buffer_eq!(buf, expected_buf);
} }
#[test] #[test]
fn render_centered_even() { fn render_centered_even() {
let text = Text::from("foo").alignment(Alignment::Center); let text = Text::from("foo").alignment(Alignment::Center);
let area = Rect::new(0, 0, 6, 1); let area = Rect::new(0, 0, 6, 1);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
text.render(area, &mut buf); text.render(area, &mut buf);
assert_eq!(buf, Buffer::with_lines([" foo "]));
let expected_buf = Buffer::with_lines(vec![" foo "]);
assert_buffer_eq!(buf, expected_buf);
} }
#[test] #[test]
@ -1030,14 +1013,10 @@ mod tests {
Line::from("bar").alignment(Alignment::Center), Line::from("bar").alignment(Alignment::Center),
]) ])
.alignment(Alignment::Right); .alignment(Alignment::Right);
let area = Rect::new(0, 0, 5, 2); let area = Rect::new(0, 0, 5, 2);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
text.render(area, &mut buf); text.render(area, &mut buf);
assert_eq!(buf, Buffer::with_lines([" foo", " bar "]));
let expected_buf = Buffer::with_lines(vec![" foo", " bar "]);
assert_buffer_eq!(buf, expected_buf);
} }
#[test] #[test]
@ -1046,10 +1025,9 @@ mod tests {
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
Text::from("foo".on_blue()).render(area, &mut buf); Text::from("foo".on_blue()).render(area, &mut buf);
let mut expected = Buffer::with_lines(vec!["foo "]); let mut expected = Buffer::with_lines(["foo "]);
expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue)); expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue));
assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
} }
#[test] #[test]
@ -1057,10 +1035,9 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 6, 1)); let mut buf = Buffer::empty(Rect::new(0, 0, 6, 1));
Text::from("foobar".on_blue()).render(Rect::new(0, 0, 3, 1), &mut buf); Text::from("foobar".on_blue()).render(Rect::new(0, 0, 3, 1), &mut buf);
let mut expected = Buffer::with_lines(vec!["foo "]); let mut expected = Buffer::with_lines(["foo "]);
expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue)); expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue));
assert_eq!(buf, expected);
assert_buffer_eq!(buf, expected);
} }
} }

View file

@ -653,6 +653,6 @@ mod tests {
#[rstest] #[rstest]
fn string_option_render_ref(mut buf: Buffer) { fn string_option_render_ref(mut buf: Buffer) {
Some(String::from("hello world")).render_ref(buf.area, &mut buf); Some(String::from("hello world")).render_ref(buf.area, &mut buf);
assert_eq!(buf, Buffer::with_lines(["hello world "]),); assert_eq!(buf, Buffer::with_lines(["hello world "]));
} }
} }

View file

@ -615,34 +615,33 @@ mod tests {
use itertools::iproduct; use itertools::iproduct;
use super::*; use super::*;
use crate::{assert_buffer_eq, widgets::BorderType}; use crate::widgets::BorderType;
#[test] #[test]
fn default() { fn default() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default(); let widget = BarChart::default();
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" "; 3])); assert_eq!(buffer, Buffer::with_lines([" "; 3]));
} }
#[test] #[test]
fn data() { fn data() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default().data(&[("foo", 1), ("bar", 2)]); let widget = BarChart::default().data(&[("foo", 1), ("bar", 2)]);
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "",
"", "1 2 ",
"1 2 ", "f b ",
"f b ", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn block() { fn block() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 5)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 5));
let block = Block::bordered() let block = Block::bordered()
.border_type(BorderType::Double) .border_type(BorderType::Double)
.title("Block"); .title("Block");
@ -650,112 +649,106 @@ mod tests {
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.block(block); .block(block);
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!( let expected = Buffer::with_lines([
buffer, "╔Block═══╗",
Buffer::with_lines(vec![ "║ █ ║",
"╔Block════════╗", "║1 2 ║",
"║ █ ║", "║f b ║",
"║1 2 ║", "╚════════╝",
"║f b ║", ]);
"╚═════════════╝", assert_eq!(buffer, expected);
])
);
} }
#[test] #[test]
fn max() { fn max() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let without_max = BarChart::default().data(&[("foo", 1), ("bar", 2), ("baz", 100)]); let without_max = BarChart::default().data(&[("foo", 1), ("bar", 2), ("baz", 100)]);
without_max.render(buffer.area, &mut buffer); without_max.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "",
"", "",
"", "f b b ",
"f b b ", ]);
]) assert_eq!(buffer, expected);
);
let with_max = BarChart::default() let with_max = BarChart::default()
.data(&[("foo", 1), ("bar", 2), ("baz", 100)]) .data(&[("foo", 1), ("bar", 2), ("baz", 100)])
.max(2); .max(2);
with_max.render(buffer.area, &mut buffer); with_max.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ " █ █ ",
" █ █ ", "1 2 █ ",
"1 2 █ ", "f b b ",
"f b b ", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn bar_style() { fn bar_style() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.bar_style(Style::new().red()); .bar_style(Style::new().red());
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ #[rustfmt::skip]
"", let mut expected = Buffer::with_lines([
"1 2 ", "",
"f b ", "1 2 ",
"f b ",
]); ]);
for (x, y) in iproduct!([0, 2], [0, 1]) { for (x, y) in iproduct!([0, 2], [0, 1]) {
expected.get_mut(x, y).set_fg(Color::Red); expected.get_mut(x, y).set_fg(Color::Red);
} }
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
fn bar_width() { fn bar_width() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.bar_width(3); .bar_width(3);
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ " ███ ",
" ███ ", "█1█ █2█ ",
"█1█ █2█ ", "foo bar ",
"foo bar ", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn bar_gap() { fn bar_gap() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.bar_gap(2); .bar_gap(2);
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "",
"", "1 2 ",
"1 2 ", "f b ",
"f b ", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn bar_set() { fn bar_set() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 0), ("bar", 1), ("baz", 3)]) .data(&[("foo", 0), ("bar", 1), ("baz", 3)])
.bar_set(symbols::bar::THREE_LEVELS); .bar_set(symbols::bar::THREE_LEVELS);
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "",
"", " ▄ 3 ",
" ▄ 3 ", "f b b ",
"f b b ", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
@ -775,67 +768,68 @@ mod tests {
]) ])
.bar_set(symbols::bar::NINE_LEVELS); .bar_set(symbols::bar::NINE_LEVELS);
widget.render(Rect::new(0, 1, 18, 2), &mut buffer); widget.render(Rect::new(0, 1, 18, 2), &mut buffer);
assert_buffer_eq!( let expected = Buffer::with_lines([
buffer, " ",
Buffer::with_lines(vec![ " ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8 ",
" ", "a b c d e f g h i ",
" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8 ", ]);
"a b c d e f g h i ", assert_eq!(buffer, expected);
])
);
} }
#[test] #[test]
fn value_style() { fn value_style() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.bar_width(3) .bar_width(3)
.value_style(Style::new().red()); .value_style(Style::new().red());
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ #[rustfmt::skip]
" ███ ", let mut expected = Buffer::with_lines([
"█1█ █2█ ", " ███ ",
"foo bar ", "█1█ █2█ ",
"foo bar ",
]); ]);
expected.get_mut(1, 1).set_fg(Color::Red); expected.get_mut(1, 1).set_fg(Color::Red);
expected.get_mut(5, 1).set_fg(Color::Red); expected.get_mut(5, 1).set_fg(Color::Red);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
fn label_style() { fn label_style() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.label_style(Style::new().red()); .label_style(Style::new().red());
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ #[rustfmt::skip]
"", let mut expected = Buffer::with_lines([
"1 2 ", "",
"f b ", "1 2 ",
"f b ",
]); ]);
expected.get_mut(0, 2).set_fg(Color::Red); expected.get_mut(0, 2).set_fg(Color::Red);
expected.get_mut(2, 2).set_fg(Color::Red); expected.get_mut(2, 2).set_fg(Color::Red);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
fn style() { fn style() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
let widget = BarChart::default() let widget = BarChart::default()
.data(&[("foo", 1), ("bar", 2)]) .data(&[("foo", 1), ("bar", 2)])
.style(Style::new().red()); .style(Style::new().red());
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ #[rustfmt::skip]
"", let mut expected = Buffer::with_lines([
"1 2 ", "",
"f b ", "1 2 ",
"f b ",
]); ]);
for (x, y) in iproduct!(0..15, 0..3) { for (x, y) in iproduct!(0..10, 0..3) {
expected.get_mut(x, y).set_fg(Color::Red); expected.get_mut(x, y).set_fg(Color::Red);
} }
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -861,8 +855,13 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 3, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 3, 3));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec!["", "1 2", "G "]); #[rustfmt::skip]
assert_buffer_eq!(buffer, expected); let expected = Buffer::with_lines([
"",
"1 2",
"G ",
]);
assert_eq!(buffer, expected);
} }
fn build_test_barchart<'a>() -> BarChart<'a> { fn build_test_barchart<'a>() -> BarChart<'a> {
@ -888,7 +887,7 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 8)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 8));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"2█ ", "2█ ",
"3██ ", "3██ ",
"4███ ", "4███ ",
@ -898,8 +897,7 @@ mod tests {
"5████", "5████",
"G2 ", "G2 ",
]); ]);
assert_eq!(buffer, expected);
assert_buffer_eq!(buffer, expected);
} }
#[test] #[test]
@ -908,7 +906,7 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 7)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 7));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
"2█ ", "2█ ",
"3██ ", "3██ ",
"4███ ", "4███ ",
@ -917,8 +915,7 @@ mod tests {
"4███ ", "4███ ",
"5████", "5████",
]); ]);
assert_eq!(buffer, expected);
assert_buffer_eq!(buffer, expected);
} }
#[test] #[test]
@ -927,9 +924,15 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 5)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 5));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec!["2█ ", "3██ ", "4███ ", "G1 ", "3██ "]); #[rustfmt::skip]
let expected = Buffer::with_lines([
assert_buffer_eq!(buffer, expected); "2█ ",
"3██ ",
"4███ ",
"G1 ",
"3██ ",
]);
assert_eq!(buffer, expected);
} }
fn test_horizontal_bars_label_width_greater_than_bar(bar_color: Option<Color>) { fn test_horizontal_bars_label_width_greater_than_bar(bar_color: Option<Color>) {
@ -952,7 +955,7 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 2)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, 2));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec!["label", "5████"]); let mut expected = Buffer::with_lines(["label", "5████"]);
// first line has a yellow foreground. first cell contains italic "5" // first line has a yellow foreground. first cell contains italic "5"
expected.get_mut(0, 1).modifier.insert(Modifier::ITALIC); expected.get_mut(0, 1).modifier.insert(Modifier::ITALIC);
@ -977,7 +980,7 @@ mod tests {
expected.get_mut(3, 0).set_fg(expected_color); expected.get_mut(3, 0).set_fg(expected_color);
expected.get_mut(4, 0).set_fg(expected_color); expected.get_mut(4, 0).set_fg(expected_color);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -1000,9 +1003,13 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec!["Jan 10█ ", "Feb 20████", "Mar 5 "]); #[rustfmt::skip]
let expected = Buffer::with_lines([
assert_buffer_eq!(buffer, expected); "Jan 10█ ",
"Feb 20████",
"Mar 5 ",
]);
assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -1023,13 +1030,13 @@ mod tests {
// G1 should have the bold red style // G1 should have the bold red style
// bold: because of BarChart::label_style // bold: because of BarChart::label_style
// red: is included with the label itself // red: is included with the label itself
let mut expected = Buffer::with_lines(vec!["2████", "G1 "]); let mut expected = Buffer::with_lines(["2████", "G1 "]);
let cell = expected.get_mut(0, 1).set_fg(Color::Red); let cell = expected.get_mut(0, 1).set_fg(Color::Red);
cell.modifier.insert(Modifier::BOLD); cell.modifier.insert(Modifier::BOLD);
let cell = expected.get_mut(1, 1).set_fg(Color::Red); let cell = expected.get_mut(1, 1).set_fg(Color::Red);
cell.modifier.insert(Modifier::BOLD); cell.modifier.insert(Modifier::BOLD);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -1046,17 +1053,14 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 13, 5)); let mut buffer = Buffer::empty(Rect::new(0, 0, 13, 5));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ▂ █ ▂",
buffer, " ▄ █ █ ▄ █",
Buffer::with_lines(vec![ "▆ 2 3 4 ▆ 2 3",
" ▂ █ ▂", "a b c c a b c",
" ▄ █ █ ▄ █", " G1 G2 ",
"▆ 2 3 4 ▆ 2 3", ]);
"a b c c a b c", assert_eq!(buffer, expected);
" G1 G2 ",
])
);
} }
#[test] #[test]
@ -1069,9 +1073,13 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 3, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 3, 3));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
#[rustfmt::skip]
let expected = Buffer::with_lines(vec!["", "▆ 5", " G"]); let expected = Buffer::with_lines([
assert_buffer_eq!(buffer, expected); "",
"▆ 5",
" G",
]);
assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -1094,15 +1102,14 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 11, 5)); let mut buffer = Buffer::empty(Rect::new(0, 0, 11, 5));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
let expected = Buffer::with_lines(vec![
" ▆▆▆ ███", " ▆▆▆ ███",
" ███ ███", " ███ ███",
"▃▃▃ ███ ███", "▃▃▃ ███ ███",
"写█ 写█ 写█", "写█ 写█ 写█",
"B1 B2 B2 ", "B1 B2 B2 ",
]); ]);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -1114,7 +1121,7 @@ mod tests {
.bar_gap(0); .bar_gap(0);
let mut buffer = Buffer::empty(Rect::new(0, 0, 0, 10)); let mut buffer = Buffer::empty(Rect::new(0, 0, 0, 10));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
assert_buffer_eq!(buffer, Buffer::empty(Rect::new(0, 0, 0, 10))); assert_eq!(buffer, Buffer::empty(Rect::new(0, 0, 0, 10)));
} }
#[test] #[test]
@ -1139,8 +1146,7 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 1));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
assert_eq!(buffer, Buffer::with_lines([" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8"]));
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8"]));
} }
#[test] #[test]
@ -1165,15 +1171,12 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3));
chart.render(Rect::new(0, 1, buffer.area.width, 2), &mut buffer); chart.render(Rect::new(0, 1, buffer.area.width, 2), &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ",
buffer, " ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8",
Buffer::with_lines(vec![ "a b c d e f g h i",
" ", ]);
" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8", assert_eq!(buffer, expected);
"a b c d e f g h i",
])
);
} }
#[test] #[test]
@ -1198,15 +1201,12 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8",
buffer, "a b c d e f g h i",
Buffer::with_lines(vec![ " Group ",
" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8", ]);
"a b c d e f g h i", assert_eq!(buffer, expected);
" Group ",
])
);
} }
#[test] #[test]
@ -1231,15 +1231,12 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 26, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 26, 3));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " 1▁ 2▂ 3▃ 4▄ 5▅ 6▆ 7▇ 8█",
buffer, "a b c d e f g h i ",
Buffer::with_lines(vec![ " Group ",
" 1▁ 2▂ 3▃ 4▄ 5▅ 6▆ 7▇ 8█", ]);
"a b c d e f g h i ", assert_eq!(buffer, expected);
" Group ",
])
);
} }
#[test] #[test]
@ -1264,16 +1261,13 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 4)); let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 4));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ▂ ▄ ▆ █",
buffer, " ▂ ▄ ▆ 4 5 6 7 8",
Buffer::with_lines(vec![ "a b c d e f g h i",
" ▂ ▄ ▆ █", " Group ",
" ▂ ▄ ▆ 4 5 6 7 8", ]);
"a b c d e f g h i", assert_eq!(buffer, expected);
" Group ",
])
);
} }
#[test] #[test]
@ -1296,15 +1290,12 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 17, 3));
chart.render(Rect::new(0, 1, buffer.area.width, 2), &mut buffer); chart.render(Rect::new(0, 1, buffer.area.width, 2), &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ",
buffer, " ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8",
Buffer::with_lines(vec![ " Group ",
" ", ]);
" ▁ ▂ ▃ ▄ ▅ ▆ ▇ 8", assert_eq!(buffer, expected);
" Group ",
])
);
} }
#[test] #[test]
@ -1315,13 +1306,9 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 59, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, 59, 1));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected =
assert_buffer_eq!( Buffer::with_lines([" ▁ ▁ ▁ ▁ ▂ ▂ ▂ ▃ ▃ ▃ ▃ ▄ ▄ ▄ ▄ ▅ ▅ ▅ ▆ ▆ ▆ ▆ ▇ ▇ ▇ █"]);
buffer, assert_eq!(buffer, expected);
Buffer::with_lines(vec![
" ▁ ▁ ▁ ▁ ▂ ▂ ▂ ▃ ▃ ▃ ▃ ▄ ▄ ▄ ▄ ▅ ▅ ▅ ▆ ▆ ▆ ▆ ▇ ▇ ▇ █",
])
);
} }
#[test] #[test]
@ -1333,17 +1320,14 @@ mod tests {
let mut buffer = Buffer::empty(Rect::new(0, 0, 7, 6)); let mut buffer = Buffer::empty(Rect::new(0, 0, 7, 6));
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
assert_buffer_eq!( " ██ ",
buffer, " ██ ",
Buffer::with_lines(vec![ "▄▄ ██ ",
" ██ ", "██ ██ ",
" ██ ", "1█ 2█ ",
"▄▄ ██ ", "a b ",
"██ ██ ", ]);
"1█ 2█ ", assert_eq!(buffer, expected);
"a b ",
])
);
} }
} }

View file

@ -864,7 +864,6 @@ mod tests {
use strum::ParseError; use strum::ParseError;
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn create_with_all_borders() { fn create_with_all_borders() {
@ -1078,7 +1077,7 @@ mod tests {
fn title() { fn title() {
use Alignment::*; use Alignment::*;
use Position::*; use Position::*;
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 11, 3));
Block::bordered() Block::bordered()
.title(Title::from("A").position(Top).alignment(Left)) .title(Title::from("A").position(Top).alignment(Left))
.title(Title::from("B").position(Top).alignment(Center)) .title(Title::from("B").position(Top).alignment(Center))
@ -1087,19 +1086,18 @@ mod tests {
.title(Title::from("E").position(Bottom).alignment(Center)) .title(Title::from("E").position(Bottom).alignment(Center))
.title(Title::from("F").position(Bottom).alignment(Right)) .title(Title::from("F").position(Bottom).alignment(Right))
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "┌A───B───C┐",
"┌A─────B─────C┐", "│ │",
"│ │", "└D───E───F┘",
"└D─────E─────F┘", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn title_top_bottom() { fn title_top_bottom() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 11, 3));
Block::bordered() Block::bordered()
.title_top(Line::raw("A").left_aligned()) .title_top(Line::raw("A").left_aligned())
.title_top(Line::raw("B").centered()) .title_top(Line::raw("B").centered())
@ -1108,14 +1106,13 @@ mod tests {
.title_bottom(Line::raw("E").centered()) .title_bottom(Line::raw("E").centered())
.title_bottom(Line::raw("F").right_aligned()) .title_bottom(Line::raw("F").right_aligned())
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "┌A───B───C┐",
"┌A─────B─────C┐", "│ │",
"│ │", "└D───E───F┘",
"└D─────E─────F┘", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
@ -1131,7 +1128,7 @@ mod tests {
.title_alignment(alignment) .title_alignment(alignment)
.title("test") .title("test")
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![expected])); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
} }
@ -1148,7 +1145,7 @@ mod tests {
.title_alignment(block_title_alignment) .title_alignment(block_title_alignment)
.title(Title::from("test").alignment(alignment)) .title(Title::from("test").alignment(alignment))
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![expected])); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
} }
@ -1160,14 +1157,7 @@ mod tests {
.title_alignment(Alignment::Right) .title_alignment(Alignment::Right)
.title("") .title("")
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( assert_eq!(buffer, Buffer::with_lines([" "; 3]));
buffer,
Buffer::with_lines(vec![
" ",
" ",
" ",
])
);
} }
#[test] #[test]
@ -1177,7 +1167,7 @@ mod tests {
.title_position(Position::Bottom) .title_position(Position::Bottom)
.title("test") .title("test")
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" ", "test"])); assert_eq!(buffer, Buffer::with_lines([" ", "test"]));
} }
#[test] #[test]
@ -1188,11 +1178,7 @@ mod tests {
.title_alignment(alignment) .title_alignment(alignment)
.title("test".yellow()) .title("test".yellow())
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_eq!(buffer, Buffer::with_lines(["test".yellow()]));
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
expected_buffer.set_style(Rect::new(0, 0, 4, 1), Style::new().yellow());
assert_buffer_eq!(buffer, expected_buffer);
} }
} }
@ -1205,11 +1191,7 @@ mod tests {
.title_style(Style::new().yellow()) .title_style(Style::new().yellow())
.title("test") .title("test")
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_eq!(buffer, Buffer::with_lines(["test".yellow()]));
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
expected_buffer.set_style(Rect::new(0, 0, 4, 1), Style::new().yellow());
assert_buffer_eq!(buffer, expected_buffer);
} }
} }
@ -1222,31 +1204,26 @@ mod tests {
.title_style(Style::new().green().on_red()) .title_style(Style::new().green().on_red())
.title("test".yellow()) .title("test".yellow())
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_eq!(buffer, Buffer::with_lines(["test".yellow().on_red()]));
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
expected_buffer.set_style(Rect::new(0, 0, 4, 1), Style::new().yellow().on_red());
assert_buffer_eq!(buffer, expected_buffer);
} }
} }
#[test] #[test]
fn title_border_style() { fn title_border_style() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.title("test") .title("test")
.border_style(Style::new().yellow()) .border_style(Style::new().yellow())
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
#[rustfmt::skip]
let mut expected_buffer = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"┌test─────────", "┌test────",
" ", "",
"└─────────────", "└────────",
]); ]);
expected_buffer.set_style(Rect::new(0, 0, 15, 3), Style::new().yellow()); expected.set_style(Rect::new(0, 0, 10, 3), Style::new().yellow());
expected_buffer.set_style(Rect::new(1, 1, 13, 1), Style::reset()); expected.set_style(Rect::new(1, 1, 8, 1), Style::reset());
assert_eq!(buffer, expected);
assert_buffer_eq!(buffer, expected_buffer);
} }
#[test] #[test]
@ -1268,103 +1245,97 @@ mod tests {
#[test] #[test]
fn render_plain_border() { fn render_plain_border() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::Plain) .border_type(BorderType::Plain)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "┌────────┐",
"┌─────────────┐", "│ │",
"│ │", "└────────┘",
"└─────────────┘" ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_rounded_border() { fn render_rounded_border() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::Rounded) .border_type(BorderType::Rounded)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "╭────────╮",
"╭─────────────╮", "│ │",
"│ │", "╰────────╯",
"╰─────────────╯" ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_double_border() { fn render_double_border() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::Double) .border_type(BorderType::Double)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "╔════════╗",
"╔═════════════╗", "║ ║",
"║ ║", "╚════════╝",
"╚═════════════╝" ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_quadrant_inside() { fn render_quadrant_inside() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::QuadrantInside) .border_type(BorderType::QuadrantInside)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "▗▄▄▄▄▄▄▄▄▖",
"▗▄▄▄▄▄▄▄▄▄▄▄▄▄▖", "▐ ▌",
"▐ ▌", "▝▀▀▀▀▀▀▀▀▘",
"▝▀▀▀▀▀▀▀▀▀▀▀▀▀▘", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_border_quadrant_outside() { fn render_border_quadrant_outside() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::QuadrantOutside) .border_type(BorderType::QuadrantOutside)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "▛▀▀▀▀▀▀▀▀▜",
"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▜", "▌ ▐",
"▌ ▐", "▙▄▄▄▄▄▄▄▄▟",
"▙▄▄▄▄▄▄▄▄▄▄▄▄▄▟", ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_solid_border() { fn render_solid_border() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_type(BorderType::Thick) .border_type(BorderType::Thick)
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "┏━━━━━━━━┓",
"┏━━━━━━━━━━━━━┓", "┃ ┃",
"┃ ┃", "┗━━━━━━━━┛",
"┗━━━━━━━━━━━━━┛" ]);
]) assert_eq!(buffer, expected);
);
} }
#[test] #[test]
fn render_custom_border_set() { fn render_custom_border_set() {
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 3));
Block::bordered() Block::bordered()
.border_set(border::Set { .border_set(border::Set {
top_left: "1", top_left: "1",
@ -1377,13 +1348,12 @@ mod tests {
horizontal_bottom: "B", horizontal_bottom: "B",
}) })
.render(buffer.area, &mut buffer); .render(buffer.area, &mut buffer);
assert_buffer_eq!( #[rustfmt::skip]
buffer, let expected = Buffer::with_lines([
Buffer::with_lines(vec![ "1TTTTTTTT2",
"1TTTTTTTTTTTTT2", "L R",
"L R", "3BBBBBBBB4",
"3BBBBBBBBBBBBB4", ]);
]) assert_eq!(buffer, expected);
);
} }
} }

View file

@ -58,7 +58,7 @@ mod tests {
.x_bounds([-10.0, 10.0]) .x_bounds([-10.0, 10.0])
.y_bounds([-10.0, 10.0]); .y_bounds([-10.0, 10.0]);
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" ⢀⣠⢤⣀ ", " ⢀⣠⢤⣀ ",
" ⢰⠋ ⠈⣇", " ⢰⠋ ⠈⣇",
" ⠘⣆⡀ ⣠⠇", " ⠘⣆⡀ ⣠⠇",

View file

@ -112,154 +112,111 @@ fn draw_line_high(painter: &mut Painter, x1: usize, y1: usize, x2: usize, y2: us
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Line; use rstest::rstest;
use crate::{assert_buffer_eq, prelude::*, widgets::canvas::Canvas};
#[allow(clippy::needless_pass_by_value)] use super::{super::*, *};
#[track_caller] use crate::{buffer::Buffer, layout::Rect};
fn test(line: Line, expected_lines: Vec<&str>) {
#[rstest]
#[case::off_grid(&Line::new(-1.0, -1.0, 10.0, 10.0, Color::Red), [" "; 10])]
#[case::off_grid(&Line::new(0.0, 0.0, 11.0, 11.0, Color::Red), [" "; 10])]
#[case::horizontal(&Line::new(0.0, 0.0, 10.0, 0.0, Color::Red), [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"••••••••••",
])]
#[case::horizontal(&Line::new(10.0, 10.0, 0.0, 10.0, Color::Red), [
"••••••••••",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
])]
#[case::vertical(&Line::new(0.0, 0.0, 0.0, 10.0, Color::Red), [""; 10])]
#[case::vertical(&Line::new(10.0, 10.0, 10.0, 0.0, Color::Red), [""; 10])]
// dy < dx, x1 < x2
#[case::diagonal(&Line::new(0.0, 0.0, 10.0, 5.0, Color::Red), [
" ",
" ",
" ",
" ",
"",
" •• ",
" •• ",
" •• ",
" •• ",
"",
])]
// dy < dx, x1 > x2
#[case::diagonal(&Line::new(10.0, 0.0, 0.0, 5.0, Color::Red), [
" ",
" ",
" ",
" ",
"",
" •• ",
" •• ",
" •• ",
" •• ",
"",
])]
// dy > dx, y1 < y2
#[case::diagonal(&Line::new(0.0, 0.0, 5.0, 10.0, Color::Red), [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
])]
// dy > dx, y1 > y2
#[case::diagonal(&Line::new(0.0, 10.0, 5.0, 0.0, Color::Red), [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
])]
fn tests<'expected_line, ExpectedLines>(#[case] line: &Line, #[case] expected: ExpectedLines)
where
ExpectedLines: IntoIterator,
ExpectedLines::Item: Into<crate::text::Line<'expected_line>>,
{
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10)); let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
let canvas = Canvas::default() let canvas = Canvas::default()
.marker(Marker::Dot) .marker(Marker::Dot)
.x_bounds([0.0, 10.0]) .x_bounds([0.0, 10.0])
.y_bounds([0.0, 10.0]) .y_bounds([0.0, 10.0])
.paint(|context| { .paint(|context| context.draw(line));
context.draw(&line);
});
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(expected_lines); let mut expected = Buffer::with_lines(expected);
for cell in &mut expected.content { for cell in &mut expected.content {
if cell.symbol() == "" { if cell.symbol() == "" {
cell.set_style(Style::new().red()); cell.set_style(Style::new().red());
} }
} }
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
}
#[test]
fn off_grid() {
test(
Line::new(-1.0, -1.0, 10.0, 10.0, Color::Red),
vec![" "; 10],
);
test(
Line::new(0.0, 0.0, 11.0, 11.0, Color::Red),
vec![" "; 10],
);
}
#[test]
fn horizontal() {
test(
Line::new(0.0, 0.0, 10.0, 0.0, Color::Red),
vec![
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"••••••••••",
],
);
test(
Line::new(10.0, 10.0, 0.0, 10.0, Color::Red),
vec![
"••••••••••",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
],
);
}
#[test]
fn vertical() {
test(
Line::new(0.0, 0.0, 0.0, 10.0, Color::Red),
vec![""; 10],
);
test(
Line::new(10.0, 10.0, 10.0, 0.0, Color::Red),
vec![""; 10],
);
}
#[test]
fn diagonal() {
// dy < dx, x1 < x2
test(
Line::new(0.0, 0.0, 10.0, 5.0, Color::Red),
vec![
" ",
" ",
" ",
" ",
"",
" •• ",
" •• ",
" •• ",
" •• ",
"",
],
);
// dy < dx, x1 > x2
test(
Line::new(10.0, 0.0, 0.0, 5.0, Color::Red),
vec![
" ",
" ",
" ",
" ",
"",
" •• ",
" •• ",
" •• ",
" •• ",
"",
],
);
// dy > dx, y1 < y2
test(
Line::new(0.0, 0.0, 5.0, 10.0, Color::Red),
vec![
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
],
);
// dy > dx, y1 > y2
test(
Line::new(0.0, 10.0, 5.0, 0.0, Color::Red),
vec![
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
],
);
} }
} }

View file

@ -65,7 +65,7 @@ mod tests {
use strum::ParseError; use strum::ParseError;
use super::*; use super::*;
use crate::{assert_buffer_eq, prelude::*, widgets::canvas::Canvas}; use crate::{prelude::*, widgets::canvas::Canvas};
#[test] #[test]
fn map_resolution_to_string() { fn map_resolution_to_string() {
@ -101,7 +101,7 @@ mod tests {
context.draw(&Map::default()); context.draw(&Map::default());
}); });
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" ", " ",
" ••••••• •• •• •• • ", " ••••••• •• •• •• • ",
" •••••••••••••• ••• •••• ••• •• •••• ", " •••••••••••••• ••• •••• ••• •• •••• ",
@ -143,7 +143,7 @@ mod tests {
"", "",
" ", " ",
]); ]);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -160,7 +160,7 @@ mod tests {
}); });
}); });
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" ", " ",
" ⢀⣠⠤⠤⠤⠔⢤⣤⡄⠤⡠⣄⠢⠂⢢⠰⣠⡄⣀⡀ ⣀ ", " ⢀⣠⠤⠤⠤⠔⢤⣤⡄⠤⡠⣄⠢⠂⢢⠰⣠⡄⣀⡀ ⣀ ",
" ⢀⣀⡤⣦⠲⢶⣿⣮⣿⡉⣰⢶⢏⡂ ⢀⣟⠁ ⢺⣻⢿⠏ ⠈⠉⠁ ⢀⣀ ⠈⠓⢳⣢⣂⡀ ", " ⢀⣀⡤⣦⠲⢶⣿⣮⣿⡉⣰⢶⢏⡂ ⢀⣟⠁ ⢺⣻⢿⠏ ⠈⠉⠁ ⢀⣀ ⠈⠓⢳⣢⣂⡀ ",
@ -202,6 +202,6 @@ mod tests {
"⠶⠔⠲⠤⠠⠜⢗⠤⠄ ⠘⠉ ⠁ ⠈⠉⠒⠔⠤", "⠶⠔⠲⠤⠠⠜⢗⠤⠄ ⠘⠉ ⠁ ⠈⠉⠒⠔⠤",
" ", " ",
]); ]);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
} }

View file

@ -66,7 +66,7 @@ impl Shape for Rectangle {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{assert_buffer_eq, prelude::*, widgets::canvas::Canvas}; use crate::{prelude::*, widgets::canvas::Canvas};
#[test] #[test]
fn draw_block_lines() { fn draw_block_lines() {
@ -85,7 +85,7 @@ mod tests {
}); });
}); });
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"██████████", "██████████",
"█ █", "█ █",
"█ █", "█ █",
@ -99,7 +99,7 @@ mod tests {
]); ]);
expected.set_style(buffer.area, Style::new().red()); expected.set_style(buffer.area, Style::new().red());
expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::reset()); expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::reset());
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -119,7 +119,7 @@ mod tests {
}); });
}); });
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"█▀▀▀▀▀▀▀▀█", "█▀▀▀▀▀▀▀▀█",
"█ █", "█ █",
"█ █", "█ █",
@ -134,7 +134,7 @@ mod tests {
expected.set_style(buffer.area, Style::new().red().on_red()); expected.set_style(buffer.area, Style::new().red().on_red());
expected.set_style(buffer.area.inner(&Margin::new(1, 0)), Style::reset().red()); expected.set_style(buffer.area.inner(&Margin::new(1, 0)), Style::reset().red());
expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::reset()); expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::reset());
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
@ -163,7 +163,7 @@ mod tests {
}); });
}); });
canvas.render(buffer.area, &mut buffer); canvas.render(buffer.area, &mut buffer);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"⡏⠉⠉⠉⠉⠉⠉⠉⠉⢹", "⡏⠉⠉⠉⠉⠉⠉⠉⠉⢹",
"⡇⢠⠤⠤⠤⠤⠤⠤⡄⢸", "⡇⢠⠤⠤⠤⠤⠤⠤⡄⢸",
"⡇⢸ ⡇⢸", "⡇⢸ ⡇⢸",
@ -178,6 +178,6 @@ mod tests {
expected.set_style(buffer.area, Style::new().red()); expected.set_style(buffer.area, Style::new().red());
expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::new().green()); expected.set_style(buffer.area.inner(&Margin::new(1, 1)), Style::new().green());
expected.set_style(buffer.area.inner(&Margin::new(2, 2)), Style::reset()); expected.set_style(buffer.area.inner(&Margin::new(2, 2)), Style::reset());
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
} }

View file

@ -1111,10 +1111,10 @@ impl<'a> Styled for Chart<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rstest::rstest;
use strum::ParseError; use strum::ParseError;
use super::*; use super::*;
use crate::assert_buffer_eq;
struct LegendTestCase { struct LegendTestCase {
chart_area: Rect, chart_area: Rect,
@ -1209,7 +1209,6 @@ mod tests {
.x_axis(Axis::default().title("xxxxxxxxxxxxxxxx")); .x_axis(Axis::default().title("xxxxxxxxxxxxxxxx"));
let mut buffer = Buffer::empty(Rect::new(0, 0, 8, 4)); let mut buffer = Buffer::empty(Rect::new(0, 0, 8, 4));
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
assert_eq!(buffer, Buffer::with_lines(vec![" ".repeat(8); 4])); assert_eq!(buffer, Buffer::with_lines(vec![" ".repeat(8); 4]));
} }
@ -1244,30 +1243,25 @@ mod tests {
let widget = Chart::new(vec![long_dataset_name, short_dataset]) let widget = Chart::new(vec![long_dataset_name, short_dataset])
.hidden_legend_constraints((100.into(), 100.into())); .hidden_legend_constraints((100.into(), 100.into()));
let mut buffer = Buffer::empty(Rect::new(0, 0, 20, 5)); let mut buffer = Buffer::empty(Rect::new(0, 0, 20, 5));
widget.render(buffer.area, &mut buffer); widget.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
let expected = Buffer::with_lines(vec![
" ┌──────────────┐", " ┌──────────────┐",
" │Very long name│", " │Very long name│",
" │ Short name│", " │ Short name│",
" └──────────────┘", " └──────────────┘",
" ", " ",
]); ]);
assert_buffer_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
#[test] #[test]
fn test_chart_have_a_topleft_legend() { fn test_chart_have_a_topleft_legend() {
let chart = Chart::new(vec![Dataset::default().name("Ds1")]) let chart = Chart::new(vec![Dataset::default().name("Ds1")])
.legend_position(Some(LegendPosition::TopLeft)); .legend_position(Some(LegendPosition::TopLeft));
let area = Rect::new(0, 0, 30, 20); let area = Rect::new(0, 0, 30, 20);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
let expected = Buffer::with_lines(vec![
"┌───┐ ", "┌───┐ ",
"│Ds1│ ", "│Ds1│ ",
"└───┘ ", "└───┘ ",
@ -1289,7 +1283,6 @@ mod tests {
" ", " ",
" ", " ",
]); ]);
assert_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
@ -1297,13 +1290,10 @@ mod tests {
fn test_chart_have_a_long_y_axis_title_overlapping_legend() { fn test_chart_have_a_long_y_axis_title_overlapping_legend() {
let chart = Chart::new(vec![Dataset::default().name("Ds1")]) let chart = Chart::new(vec![Dataset::default().name("Ds1")])
.y_axis(Axis::default().title("The title overlap a legend.")); .y_axis(Axis::default().title("The title overlap a legend."));
let area = Rect::new(0, 0, 30, 20); let area = Rect::new(0, 0, 30, 20);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
let expected = Buffer::with_lines(vec![
"The title overlap a legend. ", "The title overlap a legend. ",
" ┌───┐", " ┌───┐",
" │Ds1│", " │Ds1│",
@ -1325,7 +1315,6 @@ mod tests {
" ", " ",
" ", " ",
]); ]);
assert_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
@ -1333,13 +1322,10 @@ mod tests {
fn test_chart_have_overflowed_y_axis() { fn test_chart_have_overflowed_y_axis() {
let chart = Chart::new(vec![Dataset::default().name("Ds1")]) let chart = Chart::new(vec![Dataset::default().name("Ds1")])
.y_axis(Axis::default().title("The title overlap a legend.")); .y_axis(Axis::default().title("The title overlap a legend."));
let area = Rect::new(0, 0, 10, 10); let area = Rect::new(0, 0, 10, 10);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
let expected = Buffer::with_lines([
let expected = Buffer::with_lines(vec![
" ", " ",
" ", " ",
" ", " ",
@ -1351,7 +1337,6 @@ mod tests {
" ", " ",
" ", " ",
]); ]);
assert_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
@ -1360,12 +1345,8 @@ mod tests {
let name = "Data"; let name = "Data";
let chart = Chart::new(vec![Dataset::default().name(name)]) let chart = Chart::new(vec![Dataset::default().name(name)])
.hidden_legend_constraints((Constraint::Percentage(100), Constraint::Percentage(100))); .hidden_legend_constraints((Constraint::Percentage(100), Constraint::Percentage(100)));
let area = Rect::new(0, 0, name.len() as u16 + 2, 3); let area = Rect::new(0, 0, name.len() as u16 + 2, 3);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
let expected = Buffer::with_lines(vec!["┌────┐", "│Data│", "└────┘"]);
for position in [ for position in [
LegendPosition::TopLeft, LegendPosition::TopLeft,
LegendPosition::Top, LegendPosition::Top,
@ -1379,171 +1360,103 @@ mod tests {
let chart = chart.clone().legend_position(Some(position)); let chart = chart.clone().legend_position(Some(position));
buffer.reset(); buffer.reset();
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
#[rustfmt::skip]
let expected = Buffer::with_lines([
"┌────┐",
"│Data│",
"└────┘",
]);
assert_eq!(buffer, expected); assert_eq!(buffer, expected);
} }
} }
#[allow(clippy::too_many_lines)] #[rstest]
#[test] #[case(Some(LegendPosition::TopLeft), [
fn test_legend_of_chart_have_odd_margin_size() { "┌────┐ ",
"│Data│ ",
"└────┘ ",
" ",
" ",
" ",
])]
#[case(Some(LegendPosition::Top), [
" ┌────┐ ",
" │Data│ ",
" └────┘ ",
" ",
" ",
" ",
])]
#[case(Some(LegendPosition::TopRight), [
" ┌────┐",
" │Data│",
" └────┘",
" ",
" ",
" ",
])]
#[case(Some(LegendPosition::Left), [
" ",
"┌────┐ ",
"│Data│ ",
"└────┘ ",
" ",
" ",
])]
#[case(Some(LegendPosition::Right), [
" ",
" ┌────┐",
" │Data│",
" └────┘",
" ",
" ",
])]
#[case(Some(LegendPosition::BottomLeft), [
" ",
" ",
" ",
"┌────┐ ",
"│Data│ ",
"└────┘ ",
])]
#[case(Some(LegendPosition::Bottom), [
" ",
" ",
" ",
" ┌────┐ ",
" │Data│ ",
" └────┘ ",
])]
#[case(Some(LegendPosition::BottomRight), [
" ",
" ",
" ",
" ┌────┐",
" │Data│",
" └────┘",
])]
#[case(None, [
" ",
" ",
" ",
" ",
" ",
" ",
])]
fn test_legend_of_chart_have_odd_margin_size<'line, Lines>(
#[case] legend_position: Option<LegendPosition>,
#[case] expected: Lines,
) where
Lines: IntoIterator,
Lines::Item: Into<Line<'line>>,
{
let name = "Data"; let name = "Data";
let base_chart = Chart::new(vec![Dataset::default().name(name)])
.hidden_legend_constraints((Constraint::Percentage(100), Constraint::Percentage(100)));
let area = Rect::new(0, 0, name.len() as u16 + 2 + 3, 3 + 3); let area = Rect::new(0, 0, name.len() as u16 + 2 + 3, 3 + 3);
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
let chart = Chart::new(vec![Dataset::default().name(name)])
let chart = base_chart .legend_position(legend_position)
.clone() .hidden_legend_constraints((Constraint::Percentage(100), Constraint::Percentage(100)));
.legend_position(Some(LegendPosition::TopLeft));
buffer.reset();
chart.render(buffer.area, &mut buffer); chart.render(buffer.area, &mut buffer);
assert_eq!( assert_eq!(buffer, Buffer::with_lines(expected));
buffer,
Buffer::with_lines(vec![
"┌────┐ ",
"│Data│ ",
"└────┘ ",
" ",
" ",
" ",
])
);
buffer.reset();
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::Top));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ┌────┐ ",
" │Data│ ",
" └────┘ ",
" ",
" ",
" ",
])
);
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::TopRight));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ┌────┐",
" │Data│",
" └────┘",
" ",
" ",
" ",
])
);
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::Left));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
"┌────┐ ",
"│Data│ ",
"└────┘ ",
" ",
" ",
])
);
buffer.reset();
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::Right));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
" ┌────┐",
" │Data│",
" └────┘",
" ",
" ",
])
);
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::BottomLeft));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
" ",
" ",
"┌────┐ ",
"│Data│ ",
"└────┘ ",
])
);
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::Bottom));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
" ",
" ",
" ┌────┐ ",
" │Data│ ",
" └────┘ ",
])
);
let chart = base_chart
.clone()
.legend_position(Some(LegendPosition::BottomRight));
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
" ",
" ",
" ┌────┐",
" │Data│",
" └────┘",
])
);
let chart = base_chart.clone().legend_position(None);
buffer.reset();
chart.render(buffer.area, &mut buffer);
assert_eq!(
buffer,
Buffer::with_lines(vec![
" ",
" ",
" ",
" ",
" ",
" ",
])
);
} }
} }

View file

@ -43,24 +43,21 @@ impl WidgetRef for Clear {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn render() { fn render() {
let mut buf = Buffer::with_lines(vec!["xxxxxxxxxxxxxxx"; 7]); let mut buffer = Buffer::with_lines(["xxxxxxxxxxxxxxx"; 7]);
let clear = Clear; let clear = Clear;
clear.render(Rect::new(1, 2, 3, 4), &mut buf); clear.render(Rect::new(1, 2, 3, 4), &mut buffer);
assert_buffer_eq!( let expected = Buffer::with_lines([
buf, "xxxxxxxxxxxxxxx",
Buffer::with_lines(vec![ "xxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxx", "x xxxxxxxxxxx",
"xxxxxxxxxxxxxxx", "x xxxxxxxxxxx",
"x xxxxxxxxxxx", "x xxxxxxxxxxx",
"x xxxxxxxxxxx", "x xxxxxxxxxxx",
"x xxxxxxxxxxx", "xxxxxxxxxxxxxxx",
"x xxxxxxxxxxx", ]);
"xxxxxxxxxxxxxxx", assert_eq!(buffer, expected);
])
);
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -414,73 +414,65 @@ mod test {
/// area and comparing the rendered and expected content. /// area and comparing the rendered and expected content.
/// This can be used for easy testing of varying configured paragraphs with the same expected /// This can be used for easy testing of varying configured paragraphs with the same expected
/// buffer or any other test case really. /// buffer or any other test case really.
#[allow(clippy::needless_pass_by_value)] #[track_caller]
fn test_case(paragraph: &Paragraph, expected: Buffer) { fn test_case(paragraph: &Paragraph, expected: &Buffer) {
let backend = TestBackend::new(expected.area.width, expected.area.height); let backend = TestBackend::new(expected.area.width, expected.area.height);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
terminal terminal
.draw(|f| { .draw(|f| {
let size = f.size(); let size = f.size();
f.render_widget(paragraph.clone(), size); f.render_widget(paragraph.clone(), size);
}) })
.unwrap(); .unwrap();
terminal.backend().assert_buffer(expected);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
fn zero_width_char_at_end_of_line() { fn zero_width_char_at_end_of_line() {
let line = "foo\0"; let line = "foo\0";
let paragraphs = vec![ for paragraph in [
Paragraph::new(line), Paragraph::new(line),
Paragraph::new(line).wrap(Wrap { trim: false }), Paragraph::new(line).wrap(Wrap { trim: false }),
Paragraph::new(line).wrap(Wrap { trim: true }), Paragraph::new(line).wrap(Wrap { trim: true }),
]; ] {
test_case(&paragraph, &Buffer::with_lines(["foo"]));
for paragraph in paragraphs { test_case(&paragraph, &Buffer::with_lines(["foo "]));
test_case(&paragraph, Buffer::with_lines(vec!["foo"])); test_case(&paragraph, &Buffer::with_lines(["foo ", " "]));
test_case(&paragraph, Buffer::with_lines(vec!["foo "])); test_case(&paragraph, &Buffer::with_lines(["foo", " "]));
test_case(&paragraph, Buffer::with_lines(vec!["foo ", " "]));
test_case(&paragraph, Buffer::with_lines(vec!["foo", " "]));
} }
} }
#[test] #[test]
fn test_render_empty_paragraph() { fn test_render_empty_paragraph() {
let paragraphs = vec![ for paragraph in [
Paragraph::new(""), Paragraph::new(""),
Paragraph::new("").wrap(Wrap { trim: false }), Paragraph::new("").wrap(Wrap { trim: false }),
Paragraph::new("").wrap(Wrap { trim: true }), Paragraph::new("").wrap(Wrap { trim: true }),
]; ] {
test_case(&paragraph, &Buffer::with_lines([" "]));
for paragraph in paragraphs { test_case(&paragraph, &Buffer::with_lines([" "]));
test_case(&paragraph, Buffer::with_lines(vec![" "])); test_case(&paragraph, &Buffer::with_lines([" "; 10]));
test_case(&paragraph, Buffer::with_lines(vec![" "])); test_case(&paragraph, &Buffer::with_lines([" ", " "]));
test_case(&paragraph, Buffer::with_lines(vec![" "; 10]));
test_case(&paragraph, Buffer::with_lines(vec![" ", " "]));
} }
} }
#[test] #[test]
fn test_render_single_line_paragraph() { fn test_render_single_line_paragraph() {
let text = "Hello, world!"; let text = "Hello, world!";
let truncated_paragraph = Paragraph::new(text); for paragraph in [
let wrapped_paragraph = Paragraph::new(text).wrap(Wrap { trim: false }); Paragraph::new(text),
let trimmed_paragraph = Paragraph::new(text).wrap(Wrap { trim: true }); Paragraph::new(text).wrap(Wrap { trim: false }),
Paragraph::new(text).wrap(Wrap { trim: true }),
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; ] {
test_case(&paragraph, &Buffer::with_lines(["Hello, world! "]));
for paragraph in paragraphs { test_case(&paragraph, &Buffer::with_lines(["Hello, world!"]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world! "]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world!"]));
test_case( test_case(
paragraph, &paragraph,
Buffer::with_lines(vec!["Hello, world! ", " "]), &Buffer::with_lines(["Hello, world! ", " "]),
); );
test_case( test_case(
paragraph, &paragraph,
Buffer::with_lines(vec!["Hello, world!", " "]), &Buffer::with_lines(["Hello, world!", " "]),
); );
} }
} }
@ -488,29 +480,22 @@ mod test {
#[test] #[test]
fn test_render_multi_line_paragraph() { fn test_render_multi_line_paragraph() {
let text = "This is a\nmultiline\nparagraph."; let text = "This is a\nmultiline\nparagraph.";
for paragraph in [
let paragraphs = vec![
Paragraph::new(text), Paragraph::new(text),
Paragraph::new(text).wrap(Wrap { trim: false }), Paragraph::new(text).wrap(Wrap { trim: false }),
Paragraph::new(text).wrap(Wrap { trim: true }), Paragraph::new(text).wrap(Wrap { trim: true }),
]; ] {
for paragraph in paragraphs {
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec!["This is a ", "multiline ", "paragraph."]), &Buffer::with_lines(["This is a ", "multiline ", "paragraph."]),
); );
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines(["This is a ", "multiline ", "paragraph. "]),
"This is a ",
"multiline ",
"paragraph. ",
]),
); );
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"This is a ", "This is a ",
"multiline ", "multiline ",
"paragraph. ", "paragraph. ",
@ -530,12 +515,11 @@ mod test {
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false }); let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true }); let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
#[rustfmt::skip]
for paragraph in paragraphs {
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title─────────┐", "┌Title─────────┐",
"│Hello, worlds!│", "│Hello, worlds!│",
"└──────────────┘", "└──────────────┘",
@ -543,7 +527,7 @@ mod test {
); );
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title───────────┐", "┌Title───────────┐",
"│Hello, worlds! │", "│Hello, worlds! │",
"└────────────────┘", "└────────────────┘",
@ -551,7 +535,7 @@ mod test {
); );
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title────────────┐", "┌Title────────────┐",
"│Hello, worlds! │", "│Hello, worlds! │",
"│ │", "│ │",
@ -562,7 +546,7 @@ mod test {
test_case( test_case(
&truncated_paragraph, &truncated_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title───────┐", "┌Title───────┐",
"│Hello, world│", "│Hello, world│",
"│ │", "│ │",
@ -571,7 +555,7 @@ mod test {
); );
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title──────┐", "┌Title──────┐",
"│Hello, │", "│Hello, │",
"│worlds! │", "│worlds! │",
@ -580,7 +564,7 @@ mod test {
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌Title──────┐", "┌Title──────┐",
"│Hello, │", "│Hello, │",
"│worlds! │", "│worlds! │",
@ -598,29 +582,29 @@ mod test {
let paragraph = Paragraph::new(vec![l0, l1, l2, l3]); let paragraph = Paragraph::new(vec![l0, l1, l2, l3]);
let mut expected = let mut expected =
Buffer::with_lines(vec!["unformatted", "bold text", "cyan text", "dim text"]); Buffer::with_lines(["unformatted", "bold text", "cyan text", "dim text"]);
expected.set_style(Rect::new(0, 1, 9, 1), Style::new().bold()); expected.set_style(Rect::new(0, 1, 9, 1), Style::new().bold());
expected.set_style(Rect::new(0, 2, 9, 1), Style::new().cyan()); expected.set_style(Rect::new(0, 2, 9, 1), Style::new().cyan());
expected.set_style(Rect::new(0, 3, 8, 1), Style::new().dim()); expected.set_style(Rect::new(0, 3, 8, 1), Style::new().dim());
test_case(&paragraph, expected); test_case(&paragraph, &expected);
} }
#[test] #[test]
fn test_render_line_spans_styled() { fn test_render_line_spans_styled() {
let l0 = Line::default().spans(vec![ let l0 = Line::default().spans([
Span::styled("bold", Style::new().bold()), Span::styled("bold", Style::new().bold()),
Span::raw(" and "), Span::raw(" and "),
Span::styled("cyan", Style::new().cyan()), Span::styled("cyan", Style::new().cyan()),
]); ]);
let l1 = Line::default().spans(vec![Span::raw("unformatted")]); let l1 = Line::default().spans([Span::raw("unformatted")]);
let paragraph = Paragraph::new(vec![l0, l1]); let paragraph = Paragraph::new(vec![l0, l1]);
let mut expected = Buffer::with_lines(vec!["bold and cyan", "unformatted"]); let mut expected = Buffer::with_lines(["bold and cyan", "unformatted"]);
expected.set_style(Rect::new(0, 0, 4, 1), Style::new().bold()); expected.set_style(Rect::new(0, 0, 4, 1), Style::new().bold());
expected.set_style(Rect::new(9, 0, 4, 1), Style::new().cyan()); expected.set_style(Rect::new(9, 0, 4, 1), Style::new().cyan());
test_case(&paragraph, expected); test_case(&paragraph, &expected);
} }
#[test] #[test]
@ -630,10 +614,9 @@ mod test {
.title_position(Position::Bottom) .title_position(Position::Bottom)
.title("Title"); .title("Title");
let paragraph = Paragraph::new("Hello, world!").block(block); let paragraph = Paragraph::new("Hello, world!").block(block);
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec!["Hello, world! ", "Title──────────"]), &Buffer::with_lines(["Hello, world! ", "Title──────────"]),
); );
} }
@ -645,7 +628,7 @@ mod test {
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"This is a long line", "This is a long line",
"of text that should", "of text that should",
"wrap and ", "wrap and ",
@ -656,7 +639,7 @@ mod test {
); );
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"This is a ", "This is a ",
"long line of", "long line of",
"text that ", "text that ",
@ -671,7 +654,7 @@ mod test {
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"This is a long line", "This is a long line",
"of text that should", "of text that should",
"wrap and ", "wrap and ",
@ -682,7 +665,7 @@ mod test {
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"This is a ", "This is a ",
"long line of", "long line of",
"text that ", "text that ",
@ -703,19 +686,19 @@ mod test {
test_case( test_case(
&truncated_paragraph, &truncated_paragraph,
Buffer::with_lines(vec!["This is a long line of"]), &Buffer::with_lines(["This is a long line of"]),
); );
test_case( test_case(
&truncated_paragraph, &truncated_paragraph,
Buffer::with_lines(vec!["This is a long line of te"]), &Buffer::with_lines(["This is a long line of te"]),
); );
test_case( test_case(
&truncated_paragraph, &truncated_paragraph,
Buffer::with_lines(vec!["This is a long line of "]), &Buffer::with_lines(["This is a long line of "]),
); );
test_case( test_case(
&truncated_paragraph.clone().scroll((0, 2)), &truncated_paragraph.clone().scroll((0, 2)),
Buffer::with_lines(vec!["is is a long line of te"]), &Buffer::with_lines(["is is a long line of te"]),
); );
} }
@ -726,21 +709,19 @@ mod test {
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false }); let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true }); let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
test_case(paragraph, &Buffer::with_lines(["Hello, world! "]));
for paragraph in paragraphs { test_case(paragraph, &Buffer::with_lines(["Hello, world!"]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world! "]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world!"]));
} }
test_case(&truncated_paragraph, Buffer::with_lines(vec!["Hello, wor"])); test_case(&truncated_paragraph, &Buffer::with_lines(["Hello, wor"]));
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec!["Hello, ", "world! "]), &Buffer::with_lines(["Hello, ", "world! "]),
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec!["Hello, ", "world! "]), &Buffer::with_lines(["Hello, ", "world! "]),
); );
} }
@ -751,23 +732,21 @@ mod test {
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false }); let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true }); let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
test_case(paragraph, &Buffer::with_lines([" Hello, world! "]));
for paragraph in paragraphs { test_case(paragraph, &Buffer::with_lines([" Hello, world! "]));
test_case(paragraph, Buffer::with_lines(vec![" Hello, world! "])); test_case(paragraph, &Buffer::with_lines([" Hello, world! "]));
test_case(paragraph, Buffer::with_lines(vec![" Hello, world! "])); test_case(paragraph, &Buffer::with_lines(["Hello, world!"]));
test_case(paragraph, Buffer::with_lines(vec![" Hello, world! "]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world!"]));
} }
test_case(&truncated_paragraph, Buffer::with_lines(vec!["Hello, wor"])); test_case(&truncated_paragraph, &Buffer::with_lines(["Hello, wor"]));
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec![" Hello, ", " world! "]), &Buffer::with_lines([" Hello, ", " world! "]),
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec![" Hello, ", " world! "]), &Buffer::with_lines([" Hello, ", " world! "]),
); );
} }
@ -778,21 +757,19 @@ mod test {
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false }); let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true }); let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
test_case(paragraph, &Buffer::with_lines([" Hello, world!"]));
for paragraph in paragraphs { test_case(paragraph, &Buffer::with_lines(["Hello, world!"]));
test_case(paragraph, Buffer::with_lines(vec![" Hello, world!"]));
test_case(paragraph, Buffer::with_lines(vec!["Hello, world!"]));
} }
test_case(&truncated_paragraph, Buffer::with_lines(vec!["Hello, wor"])); test_case(&truncated_paragraph, &Buffer::with_lines(["Hello, wor"]));
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec![" Hello,", " world!"]), &Buffer::with_lines([" Hello,", " world!"]),
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec![" Hello,", " world!"]), &Buffer::with_lines([" Hello,", " world!"]),
); );
} }
@ -803,57 +780,51 @@ mod test {
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false }); let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true }); let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
for paragraph in paragraphs {
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec!["multiline ", "paragraph. ", " "]), &Buffer::with_lines(["multiline ", "paragraph. ", " "]),
); );
test_case(paragraph, Buffer::with_lines(vec!["multiline "])); test_case(paragraph, &Buffer::with_lines(["multiline "]));
} }
test_case( test_case(
&truncated_paragraph.clone().scroll((2, 4)), &truncated_paragraph.clone().scroll((2, 4)),
Buffer::with_lines(vec!["iline ", "graph. "]), &Buffer::with_lines(["iline ", "graph. "]),
); );
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec!["cool ", "multili", "ne "]), &Buffer::with_lines(["cool ", "multili", "ne "]),
); );
} }
#[test] #[test]
fn test_render_paragraph_with_zero_width_area() { fn test_render_paragraph_with_zero_width_area() {
let text = "Hello, world!"; let text = "Hello, world!";
let area = Rect::new(0, 0, 0, 3);
let paragraphs = vec![ for paragraph in [
Paragraph::new(text), Paragraph::new(text),
Paragraph::new(text).wrap(Wrap { trim: false }), Paragraph::new(text).wrap(Wrap { trim: false }),
Paragraph::new(text).wrap(Wrap { trim: true }), Paragraph::new(text).wrap(Wrap { trim: true }),
]; ] {
test_case(&paragraph, &Buffer::empty(area));
let area = Rect::new(0, 0, 0, 3); test_case(&paragraph.clone().scroll((2, 4)), &Buffer::empty(area));
for paragraph in paragraphs {
test_case(&paragraph, Buffer::empty(area));
test_case(&paragraph.clone().scroll((2, 4)), Buffer::empty(area));
} }
} }
#[test] #[test]
fn test_render_paragraph_with_zero_height_area() { fn test_render_paragraph_with_zero_height_area() {
let text = "Hello, world!"; let text = "Hello, world!";
let area = Rect::new(0, 0, 10, 0);
let paragraphs = vec![ for paragraph in [
Paragraph::new(text), Paragraph::new(text),
Paragraph::new(text).wrap(Wrap { trim: false }), Paragraph::new(text).wrap(Wrap { trim: false }),
Paragraph::new(text).wrap(Wrap { trim: true }), Paragraph::new(text).wrap(Wrap { trim: true }),
]; ] {
test_case(&paragraph, &Buffer::empty(area));
let area = Rect::new(0, 0, 10, 0); test_case(&paragraph.clone().scroll((2, 4)), &Buffer::empty(area));
for paragraph in paragraphs {
test_case(&paragraph, Buffer::empty(area));
test_case(&paragraph.clone().scroll((2, 4)), Buffer::empty(area));
} }
} }
@ -864,13 +835,7 @@ mod test {
Span::styled("world!", Style::default().fg(Color::Blue)), Span::styled("world!", Style::default().fg(Color::Blue)),
]); ]);
let paragraphs = vec![ let mut expected_buffer = Buffer::with_lines(["Hello, world!"]);
Paragraph::new(text.clone()),
Paragraph::new(text.clone()).wrap(Wrap { trim: false }),
Paragraph::new(text.clone()).wrap(Wrap { trim: true }),
];
let mut expected_buffer = Buffer::with_lines(vec!["Hello, world!"]);
expected_buffer.set_style( expected_buffer.set_style(
Rect::new(0, 0, 7, 1), Rect::new(0, 0, 7, 1),
Style::default().fg(Color::Red).bg(Color::Green), Style::default().fg(Color::Red).bg(Color::Green),
@ -879,10 +844,15 @@ mod test {
Rect::new(7, 0, 6, 1), Rect::new(7, 0, 6, 1),
Style::default().fg(Color::Blue).bg(Color::Green), Style::default().fg(Color::Blue).bg(Color::Green),
); );
for paragraph in paragraphs {
for paragraph in [
Paragraph::new(text.clone()),
Paragraph::new(text.clone()).wrap(Wrap { trim: false }),
Paragraph::new(text.clone()).wrap(Wrap { trim: true }),
] {
test_case( test_case(
&paragraph.style(Style::default().bg(Color::Green)), &paragraph.style(Style::default().bg(Color::Green)),
expected_buffer.clone(), &expected_buffer,
); );
} }
} }
@ -890,22 +860,20 @@ mod test {
#[test] #[test]
fn test_render_paragraph_with_special_characters() { fn test_render_paragraph_with_special_characters() {
let text = "Hello, <world>!"; let text = "Hello, <world>!";
let paragraphs = vec![ for paragraph in [
Paragraph::new(text), Paragraph::new(text),
Paragraph::new(text).wrap(Wrap { trim: false }), Paragraph::new(text).wrap(Wrap { trim: false }),
Paragraph::new(text).wrap(Wrap { trim: true }), Paragraph::new(text).wrap(Wrap { trim: true }),
]; ] {
test_case(&paragraph, &Buffer::with_lines(["Hello, <world>!"]));
for paragraph in paragraphs { test_case(&paragraph, &Buffer::with_lines(["Hello, <world>! "]));
test_case(&paragraph, Buffer::with_lines(vec!["Hello, <world>!"]));
test_case(&paragraph, Buffer::with_lines(vec!["Hello, <world>! "]));
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec!["Hello, <world>! ", " "]), &Buffer::with_lines(["Hello, <world>! ", " "]),
); );
test_case( test_case(
&paragraph, &paragraph,
Buffer::with_lines(vec!["Hello, <world>!", " "]), &Buffer::with_lines(["Hello, <world>!", " "]),
); );
} }
} }
@ -917,27 +885,25 @@ mod test {
let wrapped_paragraph = Paragraph::new(text).wrap(Wrap { trim: false }); let wrapped_paragraph = Paragraph::new(text).wrap(Wrap { trim: false });
let trimmed_paragraph = Paragraph::new(text).wrap(Wrap { trim: true }); let trimmed_paragraph = Paragraph::new(text).wrap(Wrap { trim: true });
let paragraphs = vec![&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph]; for paragraph in [&truncated_paragraph, &wrapped_paragraph, &trimmed_paragraph] {
test_case(paragraph, &Buffer::with_lines(["こんにちは, 世界! 😃"]));
for paragraph in paragraphs {
test_case(paragraph, Buffer::with_lines(vec!["こんにちは, 世界! 😃"]));
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec!["こんにちは, 世界! 😃 "]), &Buffer::with_lines(["こんにちは, 世界! 😃 "]),
); );
} }
test_case( test_case(
&truncated_paragraph, &truncated_paragraph,
Buffer::with_lines(vec!["こんにちは, 世 "]), &Buffer::with_lines(["こんにちは, 世 "]),
); );
test_case( test_case(
&wrapped_paragraph, &wrapped_paragraph,
Buffer::with_lines(vec!["こんにちは, ", "世界! 😃 "]), &Buffer::with_lines(["こんにちは, ", "世界! 😃 "]),
); );
test_case( test_case(
&trimmed_paragraph, &trimmed_paragraph,
Buffer::with_lines(vec!["こんにちは, ", "世界! 😃 "]), &Buffer::with_lines(["こんにちは, ", "世界! 😃 "]),
); );
} }
@ -1025,13 +991,12 @@ mod test {
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 3)); let mut buf = Buffer::empty(Rect::new(0, 0, 20, 3));
paragraph.render(Rect::new(0, 0, 20, 3), &mut buf); paragraph.render(Rect::new(0, 0, 20, 3), &mut buf);
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│Styled text │", "│Styled text │",
"└──────────────────┘", "└──────────────────┘",
]); ]);
expected.set_style(Rect::new(1, 1, 11, 1), Style::default().fg(Color::Green)); expected.set_style(Rect::new(1, 1, 11, 1), Style::default().fg(Color::Green));
assert_eq!(buf, expected); assert_eq!(buf, expected);
} }
} }

View file

@ -674,113 +674,107 @@ mod tests {
} }
#[rstest] #[rstest]
#[case("#-", 0, 2, "area 2, position_0")] #[case::area_2_position_0("#-", 0, 2)]
#[case("-#", 1, 2, "area 2, position_1")] #[case::area_2_position_1("-#", 1, 2)]
fn render_scrollbar_simplest( fn render_scrollbar_simplest(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let mut buffer = Buffer::empty(Rect::new(0, 0, expected.width() as u16, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, expected.width() as u16, 1));
let mut state = ScrollbarState::new(content_length).position(position); let mut state = ScrollbarState::new(content_length).position(position);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}",); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
#[rstest] #[rstest]
#[case("#####-----", 0, 10, "position_0")] #[case::position_0("#####-----", 0, 10)]
#[case("-#####----", 1, 10, "position_1")] #[case::position_1("-#####----", 1, 10)]
#[case("-#####----", 2, 10, "position_2")] #[case::position_2("-#####----", 2, 10)]
#[case("--#####---", 3, 10, "position_3")] #[case::position_3("--#####---", 3, 10)]
#[case("--#####---", 4, 10, "position_4")] #[case::position_4("--#####---", 4, 10)]
#[case("---#####--", 5, 10, "position_5")] #[case::position_5("---#####--", 5, 10)]
#[case("---#####--", 6, 10, "position_6")] #[case::position_6("---#####--", 6, 10)]
#[case("----#####-", 7, 10, "position_7")] #[case::position_7("----#####-", 7, 10)]
#[case("----#####-", 8, 10, "position_8")] #[case::position_8("----#####-", 8, 10)]
#[case("-----#####", 9, 10, "position_9")] #[case::position_9("-----#####", 9, 10)]
fn render_scrollbar_simple( fn render_scrollbar_simple(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let mut buffer = Buffer::empty(Rect::new(0, 0, expected.width() as u16, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, expected.width() as u16, 1));
let mut state = ScrollbarState::new(content_length).position(position); let mut state = ScrollbarState::new(content_length).position(position);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}",); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
#[rstest] #[rstest]
#[case(" ", 0, 0, "position_0")] #[case::position_0(" ", 0, 0)]
fn render_scrollbar_nobar( fn render_scrollbar_nobar(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let size = expected.width(); let size = expected.width();
let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1));
let mut state = ScrollbarState::new(content_length).position(position); let mut state = ScrollbarState::new(content_length).position(position);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}",); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
#[rstest] #[rstest]
#[case("##########", 0, 1, "fullbar position 0")] #[case::fullbar_position_0("##########", 0, 1)]
#[case("#########-", 0, 2, "almost fullbar position 0")] #[case::almost_fullbar_position_0("#########-", 0, 2)]
#[case("-#########", 1, 2, "almost fullbar position 1")] #[case::almost_fullbar_position_1("-#########", 1, 2)]
fn render_scrollbar_fullbar( fn render_scrollbar_fullbar(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let size = expected.width(); let size = expected.width();
let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1));
let mut state = ScrollbarState::new(content_length).position(position); let mut state = ScrollbarState::new(content_length).position(position);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}",); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
#[rstest] #[rstest]
#[case("#########-", 0, 2, "position_0")] #[case::position_0("#########-", 0, 2)]
#[case("-#########", 1, 2, "position_1")] #[case::position_1("-#########", 1, 2)]
fn render_scrollbar_almost_fullbar( fn render_scrollbar_almost_fullbar(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let size = expected.width(); let size = expected.width();
let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size as u16, 1));
let mut state = ScrollbarState::new(content_length).position(position); let mut state = ScrollbarState::new(content_length).position(position);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}",); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
#[rstest] #[rstest]
#[case("█████═════", 0, 10, "position_0")] #[case::position_0("█████═════", 0, 10)]
#[case("═█████════", 1, 10, "position_1")] #[case::position_1("═█████════", 1, 10)]
#[case("═█████════", 2, 10, "position_2")] #[case::position_2("═█████════", 2, 10)]
#[case("══█████═══", 3, 10, "position_3")] #[case::position_3("══█████═══", 3, 10)]
#[case("══█████═══", 4, 10, "position_4")] #[case::position_4("══█████═══", 4, 10)]
#[case("═══█████══", 5, 10, "position_5")] #[case::position_5("═══█████══", 5, 10)]
#[case("═══█████══", 6, 10, "position_6")] #[case::position_6("═══█████══", 6, 10)]
#[case("════█████═", 7, 10, "position_7")] #[case::position_7("════█████═", 7, 10)]
#[case("════█████═", 8, 10, "position_8")] #[case::position_8("════█████═", 8, 10)]
#[case("═════█████", 9, 10, "position_9")] #[case::position_9("═════█████", 9, 10)]
#[case("═════█████", 100, 10, "position_out_of_bounds")] #[case::position_out_of_bounds("═════█████", 100, 10)]
fn render_scrollbar_without_symbols( fn render_scrollbar_without_symbols(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] assertion_message: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1));
@ -789,30 +783,25 @@ mod tests {
.begin_symbol(None) .begin_symbol(None)
.end_symbol(None) .end_symbol(None)
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([expected]));
buffer,
Buffer::with_lines(vec![expected]),
"{assertion_message}",
);
} }
#[rstest] #[rstest]
#[case("█████ ", 0, 10, "position_0")] #[case::position_0("█████ ", 0, 10)]
#[case(" █████ ", 1, 10, "position_1")] #[case::position_1(" █████ ", 1, 10)]
#[case(" █████ ", 2, 10, "position_2")] #[case::position_2(" █████ ", 2, 10)]
#[case(" █████ ", 3, 10, "position_3")] #[case::position_3(" █████ ", 3, 10)]
#[case(" █████ ", 4, 10, "position_4")] #[case::position_4(" █████ ", 4, 10)]
#[case(" █████ ", 5, 10, "position_5")] #[case::position_5(" █████ ", 5, 10)]
#[case(" █████ ", 6, 10, "position_6")] #[case::position_6(" █████ ", 6, 10)]
#[case(" █████ ", 7, 10, "position_7")] #[case::position_7(" █████ ", 7, 10)]
#[case(" █████ ", 8, 10, "position_8")] #[case::position_8(" █████ ", 8, 10)]
#[case(" █████", 9, 10, "position_9")] #[case::position_9(" █████", 9, 10)]
#[case(" █████", 100, 10, "position_out_of_bounds")] #[case::position_out_of_bounds(" █████", 100, 10)]
fn render_scrollbar_without_track_symbols( fn render_scrollbar_without_track_symbols(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] assertion_message: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1));
@ -822,30 +811,25 @@ mod tests {
.begin_symbol(None) .begin_symbol(None)
.end_symbol(None) .end_symbol(None)
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([expected]));
buffer,
Buffer::with_lines(vec![expected]),
"{assertion_message}",
);
} }
#[rstest] #[rstest]
#[case("█████-----", 0, 10, "position_0")] #[case::position_0("█████-----", 0, 10)]
#[case("-█████----", 1, 10, "position_1")] #[case::position_1("-█████----", 1, 10)]
#[case("-█████----", 2, 10, "position_2")] #[case::position_2("-█████----", 2, 10)]
#[case("--█████---", 3, 10, "position_3")] #[case::position_3("--█████---", 3, 10)]
#[case("--█████---", 4, 10, "position_4")] #[case::position_4("--█████---", 4, 10)]
#[case("---█████--", 5, 10, "position_5")] #[case::position_5("---█████--", 5, 10)]
#[case("---█████--", 6, 10, "position_6")] #[case::position_6("---█████--", 6, 10)]
#[case("----█████-", 7, 10, "position_7")] #[case::position_7("----█████-", 7, 10)]
#[case("----█████-", 8, 10, "position_8")] #[case::position_8("----█████-", 8, 10)]
#[case("-----█████", 9, 10, "position_9")] #[case::position_9("-----█████", 9, 10)]
#[case("-----█████", 100, 10, "position_out_of_bounds")] #[case::position_out_of_bounds("-----█████", 100, 10)]
fn render_scrollbar_without_track_symbols_over_content( fn render_scrollbar_without_track_symbols_over_content(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] assertion_message: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1));
@ -858,32 +842,27 @@ mod tests {
.begin_symbol(None) .begin_symbol(None)
.end_symbol(None) .end_symbol(None)
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([expected]));
buffer,
Buffer::with_lines(vec![expected]),
"{assertion_message}",
);
} }
#[rstest] #[rstest]
#[case("<####---->", 0, 10, "position_0")] #[case::position_0("<####---->", 0, 10)]
#[case("<#####--->", 1, 10, "position_1")] #[case::position_1("<#####--->", 1, 10)]
#[case("<-####--->", 2, 10, "position_2")] #[case::position_2("<-####--->", 2, 10)]
#[case("<-####--->", 3, 10, "position_3")] #[case::position_3("<-####--->", 3, 10)]
#[case("<--####-->", 4, 10, "position_4")] #[case::position_4("<--####-->", 4, 10)]
#[case("<--####-->", 5, 10, "position_5")] #[case::position_5("<--####-->", 5, 10)]
#[case("<---####->", 6, 10, "position_6")] #[case::position_6("<---####->", 6, 10)]
#[case("<---####->", 7, 10, "position_7")] #[case::position_7("<---####->", 7, 10)]
#[case("<---#####>", 8, 10, "position_8")] #[case::position_8("<---#####>", 8, 10)]
#[case("<----####>", 9, 10, "position_9")] #[case::position_9("<----####>", 9, 10)]
#[case("<----####>", 10, 10, "position_one_out_of_bounds")] #[case::position_one_out_of_bounds("<----####>", 10, 10)]
#[case("<----####>", 15, 10, "position_few_out_of_bounds")] #[case::position_few_out_of_bounds("<----####>", 15, 10)]
#[case("<----####>", 500, 10, "position_very_many_out_of_bounds")] #[case::position_very_many_out_of_bounds("<----####>", 500, 10)]
fn render_scrollbar_with_symbols( fn render_scrollbar_with_symbols(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] assertion_message: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 1));
@ -894,30 +873,25 @@ mod tests {
.track_symbol(Some("-")) .track_symbol(Some("-"))
.thumb_symbol("#") .thumb_symbol("#")
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([expected]));
buffer,
Buffer::with_lines(vec![expected]),
"{assertion_message}",
);
} }
#[rstest] #[rstest]
#[case("█████═════", 0, 10, "position_0")] #[case::position_0("█████═════", 0, 10)]
#[case("═█████════", 1, 10, "position_1")] #[case::position_1("═█████════", 1, 10)]
#[case("═█████════", 2, 10, "position_2")] #[case::position_2("═█████════", 2, 10)]
#[case("══█████═══", 3, 10, "position_3")] #[case::position_3("══█████═══", 3, 10)]
#[case("══█████═══", 4, 10, "position_4")] #[case::position_4("══█████═══", 4, 10)]
#[case("═══█████══", 5, 10, "position_5")] #[case::position_5("═══█████══", 5, 10)]
#[case("═══█████══", 6, 10, "position_6")] #[case::position_6("═══█████══", 6, 10)]
#[case("════█████═", 7, 10, "position_7")] #[case::position_7("════█████═", 7, 10)]
#[case("════█████═", 8, 10, "position_8")] #[case::position_8("════█████═", 8, 10)]
#[case("═════█████", 9, 10, "position_9")] #[case::position_9("═════█████", 9, 10)]
#[case("═════█████", 100, 10, "position_out_of_bounds")] #[case::position_out_of_bounds("═════█████", 100, 10)]
fn render_scrollbar_horizontal_bottom( fn render_scrollbar_horizontal_bottom(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 2)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 2));
@ -927,30 +901,25 @@ mod tests {
.end_symbol(None) .end_symbol(None)
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
let empty_string = " ".repeat(size as usize); let empty_string = " ".repeat(size as usize);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([&empty_string, expected]));
buffer,
Buffer::with_lines(vec![&empty_string, expected]),
"{description}",
);
} }
#[rstest] #[rstest]
#[case("█████═════", 0, 10, "position_0")] #[case::position_0("█████═════", 0, 10)]
#[case("═█████════", 1, 10, "position_1")] #[case::position_1("═█████════", 1, 10)]
#[case("═█████════", 2, 10, "position_2")] #[case::position_2("═█████════", 2, 10)]
#[case("══█████═══", 3, 10, "position_3")] #[case::position_3("══█████═══", 3, 10)]
#[case("══█████═══", 4, 10, "position_4")] #[case::position_4("══█████═══", 4, 10)]
#[case("═══█████══", 5, 10, "position_5")] #[case::position_5("═══█████══", 5, 10)]
#[case("═══█████══", 6, 10, "position_6")] #[case::position_6("═══█████══", 6, 10)]
#[case("════█████═", 7, 10, "position_7")] #[case::position_7("════█████═", 7, 10)]
#[case("════█████═", 8, 10, "position_8")] #[case::position_8("════█████═", 8, 10)]
#[case("═════█████", 9, 10, "position_9")] #[case::position_9("═════█████", 9, 10)]
#[case("═════█████", 100, 10, "position_out_of_bounds")] #[case::position_out_of_bounds("═════█████", 100, 10)]
fn render_scrollbar_horizontal_top( fn render_scrollbar_horizontal_top(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, size, 2)); let mut buffer = Buffer::empty(Rect::new(0, 0, size, 2));
@ -960,30 +929,25 @@ mod tests {
.end_symbol(None) .end_symbol(None)
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
let empty_string = " ".repeat(size as usize); let empty_string = " ".repeat(size as usize);
assert_eq!( assert_eq!(buffer, Buffer::with_lines([expected, &empty_string]));
buffer,
Buffer::with_lines(vec![expected, &empty_string]),
"{description}",
);
} }
#[rstest] #[rstest]
#[case("<####---->", 0, 10, "position_0")] #[case::position_0("<####---->", 0, 10)]
#[case("<#####--->", 1, 10, "position_1")] #[case::position_1("<#####--->", 1, 10)]
#[case("<-####--->", 2, 10, "position_2")] #[case::position_2("<-####--->", 2, 10)]
#[case("<-####--->", 3, 10, "position_3")] #[case::position_3("<-####--->", 3, 10)]
#[case("<--####-->", 4, 10, "position_4")] #[case::position_4("<--####-->", 4, 10)]
#[case("<--####-->", 5, 10, "position_5")] #[case::position_5("<--####-->", 5, 10)]
#[case("<---####->", 6, 10, "position_6")] #[case::position_6("<---####->", 6, 10)]
#[case("<---####->", 7, 10, "position_7")] #[case::position_7("<---####->", 7, 10)]
#[case("<---#####>", 8, 10, "position_8")] #[case::position_8("<---#####>", 8, 10)]
#[case("<----####>", 9, 10, "position_9")] #[case::position_9("<----####>", 9, 10)]
#[case("<----####>", 10, 10, "position_one_out_of_bounds")] #[case::position_one_out_of_bounds("<----####>", 10, 10)]
fn render_scrollbar_vertical_left( fn render_scrollbar_vertical_left(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, size)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, size));
@ -995,26 +959,25 @@ mod tests {
.thumb_symbol("#") .thumb_symbol("#")
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
let bar = expected.chars().map(|c| format!("{c} ")); let bar = expected.chars().map(|c| format!("{c} "));
assert_eq!(buffer, Buffer::with_lines(bar), "{description}"); assert_eq!(buffer, Buffer::with_lines(bar));
} }
#[rstest] #[rstest]
#[case("<####---->", 0, 10, "position_0")] #[case::position_0("<####---->", 0, 10)]
#[case("<#####--->", 1, 10, "position_1")] #[case::position_1("<#####--->", 1, 10)]
#[case("<-####--->", 2, 10, "position_2")] #[case::position_2("<-####--->", 2, 10)]
#[case("<-####--->", 3, 10, "position_3")] #[case::position_3("<-####--->", 3, 10)]
#[case("<--####-->", 4, 10, "position_4")] #[case::position_4("<--####-->", 4, 10)]
#[case("<--####-->", 5, 10, "position_5")] #[case::position_5("<--####-->", 5, 10)]
#[case("<---####->", 6, 10, "position_6")] #[case::position_6("<---####->", 6, 10)]
#[case("<---####->", 7, 10, "position_7")] #[case::position_7("<---####->", 7, 10)]
#[case("<---#####>", 8, 10, "position_8")] #[case::position_8("<---#####>", 8, 10)]
#[case("<----####>", 9, 10, "position_9")] #[case::position_9("<----####>", 9, 10)]
#[case("<----####>", 10, 10, "position_one_out_of_bounds")] #[case::position_one_out_of_bounds("<----####>", 10, 10)]
fn render_scrollbar_vertical_rightl( fn render_scrollbar_vertical_rightl(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
let mut buffer = Buffer::empty(Rect::new(0, 0, 5, size)); let mut buffer = Buffer::empty(Rect::new(0, 0, 5, size));
@ -1026,26 +989,25 @@ mod tests {
.thumb_symbol("#") .thumb_symbol("#")
.render(buffer.area, &mut buffer, &mut state); .render(buffer.area, &mut buffer, &mut state);
let bar = expected.chars().map(|c| format!(" {c}")); let bar = expected.chars().map(|c| format!(" {c}"));
assert_eq!(buffer, Buffer::with_lines(bar), "{description}"); assert_eq!(buffer, Buffer::with_lines(bar));
} }
#[rstest] #[rstest]
#[case("##--------", 0, 10, "position_0")] #[case::position_0("##--------", 0, 10)]
#[case("-##-------", 1, 10, "position_1")] #[case::position_1("-##-------", 1, 10)]
#[case("--##------", 2, 10, "position_2")] #[case::position_2("--##------", 2, 10)]
#[case("---##-----", 3, 10, "position_3")] #[case::position_3("---##-----", 3, 10)]
#[case("----#-----", 4, 10, "position_4")] #[case::position_4("----#-----", 4, 10)]
#[case("-----#----", 5, 10, "position_5")] #[case::position_5("-----#----", 5, 10)]
#[case("-----##---", 6, 10, "position_6")] #[case::position_6("-----##---", 6, 10)]
#[case("------##--", 7, 10, "position_7")] #[case::position_7("------##--", 7, 10)]
#[case("-------##-", 8, 10, "position_8")] #[case::position_8("-------##-", 8, 10)]
#[case("--------##", 9, 10, "position_9")] #[case::position_9("--------##", 9, 10)]
#[case("--------##", 10, 10, "position_one_out_of_bounds")] #[case::position_one_out_of_bounds("--------##", 10, 10)]
fn custom_viewport_length( fn custom_viewport_length(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
@ -1054,28 +1016,27 @@ mod tests {
.position(position) .position(position)
.viewport_content_length(2); .viewport_content_length(2);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}"); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
/// Fixes <https://github.com/ratatui-org/ratatui/pull/959> which was a bug that would not /// Fixes <https://github.com/ratatui-org/ratatui/pull/959> which was a bug that would not
/// render a thumb when the viewport was very small in comparison to the content length. /// render a thumb when the viewport was very small in comparison to the content length.
#[rstest] #[rstest]
#[case("#----", 0, 100, "position_0")] #[case::position_0("#----", 0, 100)]
#[case("#----", 10, 100, "position_10")] #[case::position_10("#----", 10, 100)]
#[case("-#---", 20, 100, "position_20")] #[case::position_20("-#---", 20, 100)]
#[case("-#---", 30, 100, "position_30")] #[case::position_30("-#---", 30, 100)]
#[case("--#--", 40, 100, "position_40")] #[case::position_40("--#--", 40, 100)]
#[case("--#--", 50, 100, "position_50")] #[case::position_50("--#--", 50, 100)]
#[case("---#-", 60, 100, "position_60")] #[case::position_60("---#-", 60, 100)]
#[case("---#-", 70, 100, "position_70")] #[case::position_70("---#-", 70, 100)]
#[case("----#", 80, 100, "position_80")] #[case::position_80("----#", 80, 100)]
#[case("----#", 90, 100, "position_90")] #[case::position_90("----#", 90, 100)]
#[case("----#", 100, 100, "position_one_out_of_bounds")] #[case::position_one_out_of_bounds("----#", 100, 100)]
fn thumb_visible_on_very_small_track( fn thumb_visible_on_very_small_track(
#[case] expected: &str, #[case] expected: &str,
#[case] position: usize, #[case] position: usize,
#[case] content_length: usize, #[case] content_length: usize,
#[case] description: &str,
scrollbar_no_arrows: Scrollbar, scrollbar_no_arrows: Scrollbar,
) { ) {
let size = expected.width() as u16; let size = expected.width() as u16;
@ -1084,6 +1045,6 @@ mod tests {
.position(position) .position(position)
.viewport_content_length(2); .viewport_content_length(2);
scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state); scrollbar_no_arrows.render(buffer.area, &mut buffer, &mut state);
assert_eq!(buffer, Buffer::with_lines(vec![expected]), "{description}"); assert_eq!(buffer, Buffer::with_lines([expected]));
} }
} }

View file

@ -225,7 +225,7 @@ mod tests {
use strum::ParseError; use strum::ParseError;
use super::*; use super::*;
use crate::{assert_buffer_eq, buffer::Cell}; use crate::buffer::Cell;
#[test] #[test]
fn render_direction_to_string() { fn render_direction_to_string() {
@ -264,21 +264,21 @@ mod tests {
fn it_does_not_panic_if_max_is_zero() { fn it_does_not_panic_if_max_is_zero() {
let widget = Sparkline::default().data(&[0, 0, 0]); let widget = Sparkline::default().data(&[0, 0, 0]);
let buffer = render(widget, 6); let buffer = render(widget, 6);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" xxx"])); assert_eq!(buffer, Buffer::with_lines([" xxx"]));
} }
#[test] #[test]
fn it_does_not_panic_if_max_is_set_to_zero() { fn it_does_not_panic_if_max_is_set_to_zero() {
let widget = Sparkline::default().data(&[0, 1, 2]).max(0); let widget = Sparkline::default().data(&[0, 1, 2]).max(0);
let buffer = render(widget, 6); let buffer = render(widget, 6);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" xxx"])); assert_eq!(buffer, Buffer::with_lines([" xxx"]));
} }
#[test] #[test]
fn it_draws() { fn it_draws() {
let widget = Sparkline::default().data(&[0, 1, 2, 3, 4, 5, 6, 7, 8]); let widget = Sparkline::default().data(&[0, 1, 2, 3, 4, 5, 6, 7, 8]);
let buffer = render(widget, 12); let buffer = render(widget, 12);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" ▁▂▃▄▅▆▇█xxx"])); assert_eq!(buffer, Buffer::with_lines([" ▁▂▃▄▅▆▇█xxx"]));
} }
#[test] #[test]
@ -287,7 +287,7 @@ mod tests {
.data(&[0, 1, 2, 3, 4, 5, 6, 7, 8]) .data(&[0, 1, 2, 3, 4, 5, 6, 7, 8])
.direction(RenderDirection::LeftToRight); .direction(RenderDirection::LeftToRight);
let buffer = render(widget, 12); let buffer = render(widget, 12);
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" ▁▂▃▄▅▆▇█xxx"])); assert_eq!(buffer, Buffer::with_lines([" ▁▂▃▄▅▆▇█xxx"]));
} }
#[test] #[test]
@ -296,7 +296,7 @@ mod tests {
.data(&[0, 1, 2, 3, 4, 5, 6, 7, 8]) .data(&[0, 1, 2, 3, 4, 5, 6, 7, 8])
.direction(RenderDirection::RightToLeft); .direction(RenderDirection::RightToLeft);
let buffer = render(widget, 12); let buffer = render(widget, 12);
assert_buffer_eq!(buffer, Buffer::with_lines(vec!["xxx█▇▆▅▄▃▂▁ "])); assert_eq!(buffer, Buffer::with_lines(["xxx█▇▆▅▄▃▂▁ "]));
} }
#[test] #[test]

View file

@ -1001,7 +1001,6 @@ mod tests {
#[cfg(test)] #[cfg(test)]
mod render { mod render {
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn render_empty_area() { fn render_empty_area() {
@ -1009,7 +1008,7 @@ mod tests {
let rows = vec![Row::new(vec!["Cell1", "Cell2"])]; let rows = vec![Row::new(vec!["Cell1", "Cell2"])];
let table = Table::new(rows, vec![Constraint::Length(5); 2]); let table = Table::new(rows, vec![Constraint::Length(5); 2]);
Widget::render(table, Rect::new(0, 0, 0, 0), &mut buf); Widget::render(table, Rect::new(0, 0, 0, 0), &mut buf);
assert_buffer_eq!(buf, Buffer::empty(Rect::new(0, 0, 15, 3))); assert_eq!(buf, Buffer::empty(Rect::new(0, 0, 15, 3)));
} }
#[test] #[test]
@ -1017,7 +1016,7 @@ mod tests {
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buf = Buffer::empty(Rect::new(0, 0, 15, 3));
let table = Table::default(); let table = Table::default();
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
assert_buffer_eq!(buf, Buffer::empty(Rect::new(0, 0, 15, 3))); assert_eq!(buf, Buffer::empty(Rect::new(0, 0, 15, 3)));
} }
#[test] #[test]
@ -1030,12 +1029,13 @@ mod tests {
let block = Block::bordered().title("Block"); let block = Block::bordered().title("Block");
let table = Table::new(rows, vec![Constraint::Length(5); 2]).block(block); let table = Table::new(rows, vec![Constraint::Length(5); 2]).block(block);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"┌Block────────┐", "┌Block────────┐",
"│Cell1 Cell2 │", "│Cell1 Cell2 │",
"└─────────────┘", "└─────────────┘",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1048,12 +1048,13 @@ mod tests {
]; ];
let table = Table::new(rows, [Constraint::Length(5); 2]).header(header); let table = Table::new(rows, [Constraint::Length(5); 2]).header(header);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Head1 Head2 ", "Head1 Head2 ",
"Cell1 Cell2 ", "Cell1 Cell2 ",
"Cell3 Cell4 ", "Cell3 Cell4 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1066,12 +1067,13 @@ mod tests {
]; ];
let table = Table::new(rows, [Constraint::Length(5); 2]).footer(footer); let table = Table::new(rows, [Constraint::Length(5); 2]).footer(footer);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Cell1 Cell2 ", "Cell1 Cell2 ",
"Cell3 Cell4 ", "Cell3 Cell4 ",
"Foot1 Foot2 ", "Foot1 Foot2 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1084,12 +1086,13 @@ mod tests {
.header(header) .header(header)
.footer(footer); .footer(footer);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Head1 Head2 ", "Head1 Head2 ",
"Cell1 Cell2 ", "Cell1 Cell2 ",
"Foot1 Foot2 ", "Foot1 Foot2 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1102,12 +1105,13 @@ mod tests {
]; ];
let table = Table::new(rows, [Constraint::Length(5); 2]).header(header); let table = Table::new(rows, [Constraint::Length(5); 2]).header(header);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Head1 Head2 ", "Head1 Head2 ",
" ", " ",
"Cell1 Cell2 ", "Cell1 Cell2 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1117,12 +1121,13 @@ mod tests {
let rows = vec![Row::new(vec!["Cell1", "Cell2"])]; let rows = vec![Row::new(vec!["Cell1", "Cell2"])];
let table = Table::new(rows, [Constraint::Length(5); 2]).footer(footer); let table = Table::new(rows, [Constraint::Length(5); 2]).footer(footer);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Cell1 Cell2 ", "Cell1 Cell2 ",
" ", " ",
"Foot1 Foot2 ", "Foot1 Foot2 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
@ -1134,30 +1139,27 @@ mod tests {
]; ];
let table = Table::new(rows, [Constraint::Length(5); 2]); let table = Table::new(rows, [Constraint::Length(5); 2]);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
let expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let expected = Buffer::with_lines([
"Cell1 Cell2 ", "Cell1 Cell2 ",
" ", " ",
"Cell3 Cell4 ", "Cell3 Cell4 ",
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
#[test] #[test]
fn render_with_alignment() { fn render_with_alignment() {
let mut buf = Buffer::empty(Rect::new(0, 0, 15, 3)); let mut buf = Buffer::empty(Rect::new(0, 0, 10, 3));
let rows = vec![ let rows = vec![
Row::new(vec![Line::from("Left").alignment(Alignment::Left)]), Row::new(vec![Line::from("Left").alignment(Alignment::Left)]),
Row::new(vec![Line::from("Center").alignment(Alignment::Center)]), Row::new(vec![Line::from("Center").alignment(Alignment::Center)]),
Row::new(vec![Line::from("Right").alignment(Alignment::Right)]), Row::new(vec![Line::from("Right").alignment(Alignment::Right)]),
]; ];
let table = Table::new(rows, [Percentage(100)]); let table = Table::new(rows, [Percentage(100)]);
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf); Widget::render(table, Rect::new(0, 0, 10, 3), &mut buf);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines(["Left ", " Center ", " Right"]);
"Left ", assert_eq!(buf, expected);
" Center ",
" Right",
]);
assert_buffer_eq!(buf, expected);
} }
#[test] #[test]
@ -1181,19 +1183,18 @@ mod tests {
.highlight_symbol(">>"); .highlight_symbol(">>");
let mut state = TableState::new().with_selected(0); let mut state = TableState::new().with_selected(0);
StatefulWidget::render(table, Rect::new(0, 0, 15, 3), &mut buf, &mut state); StatefulWidget::render(table, Rect::new(0, 0, 15, 3), &mut buf, &mut state);
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
">>Cell1 Cell2 ".red(), ">>Cell1 Cell2 ".red(),
" Cell3 Cell4 ".into(), " Cell3 Cell4 ".into(),
" ".into(), " ".into(),
]); ]);
assert_buffer_eq!(buf, expected); assert_eq!(buf, expected);
} }
} }
// test how constraints interact with table column width allocation // test how constraints interact with table column width allocation
mod column_widths { mod column_widths {
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn length_constraint() { fn length_constraint() {
@ -1387,12 +1388,17 @@ mod tests {
assert_eq!(table.get_columns_widths(10, 0), [(0, 5), (5, 5)]); assert_eq!(table.get_columns_widths(10, 0), [(0, 5), (5, 5)]);
} }
fn test_table_with_selection( #[track_caller]
fn test_table_with_selection<'line, Lines>(
highlight_spacing: HighlightSpacing, highlight_spacing: HighlightSpacing,
columns: u16, columns: u16,
spacing: u16, spacing: u16,
selection: Option<usize>, selection: Option<usize>,
) -> Buffer { expected: Lines,
) where
Lines: IntoIterator,
Lines::Item: Into<Line<'line>>,
{
let table = Table::default() let table = Table::default()
.rows(vec![Row::new(vec!["ABCDE", "12345"])]) .rows(vec![Row::new(vec!["ABCDE", "12345"])])
.highlight_spacing(highlight_spacing) .highlight_spacing(highlight_spacing)
@ -1402,26 +1408,24 @@ mod tests {
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
let mut state = TableState::default().with_selected(selection); let mut state = TableState::default().with_selected(selection);
StatefulWidget::render(table, area, &mut buf, &mut state); StatefulWidget::render(table, area, &mut buf, &mut state);
buf assert_eq!(buf, Buffer::with_lines(expected));
} }
#[test] #[test]
fn excess_area_highlight_symbol_and_column_spacing_allocation() { fn excess_area_highlight_symbol_and_column_spacing_allocation() {
// no highlight_symbol rendered ever // no highlight_symbol rendered ever
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 15, // width
15, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE 12345 ", /* default layout is Flex::Start but columns length "ABCDE 12345 ", /* default layout is Flex::Start but columns length
* constraints are calculated as `max_area / n_columns`, * constraints are calculated as `max_area / n_columns`,
* i.e. they are distributed amongst available space */ * i.e. they are distributed amongst available space */
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
let table = Table::default() let table = Table::default()
@ -1431,88 +1435,76 @@ mod tests {
let area = Rect::new(0, 0, 15, 3); let area = Rect::new(0, 0, 15, 3);
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
Widget::render(table, area, &mut buf); Widget::render(table, area, &mut buf);
assert_buffer_eq!( let expected = Buffer::with_lines([
buf, "ABCDE12345 ", /* As reference, this is what happens when you manually
Buffer::with_lines(vec![ * specify widths */
"ABCDE12345 ", /* As reference, this is what happens when you manually " ", // row 2
* specify widths */ " ", // row 3
" ", // row 2 ]);
" ", // row 3 assert_eq!(buf, expected);
])
);
// no highlight_symbol rendered ever // no highlight_symbol rendered ever
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 15, // width
15, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
"ABCDE 12345 ", // row 1 "ABCDE 12345 ", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// no highlight_symbol rendered because no selection is made // no highlight_symbol rendered because no selection is made
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 15, // width
15, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE 12345 ", // row 1 "ABCDE 12345 ", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// highlight_symbol rendered because selection is made // highlight_symbol rendered because selection is made
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 15, // width
15, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABCDE 12345 ", // row 1 ">>>ABCDE 12345 ", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// highlight_symbol always rendered even no selection is made // highlight_symbol always rendered even no selection is made
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 15, // width
15, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" ABCDE 12345 ", // row 1 " ABCDE 12345 ", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// no highlight_symbol rendered because no selection is made // no highlight_symbol rendered because no selection is made
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 15, // width
15, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABCDE 12345 ", // row 1 ">>>ABCDE 12345 ", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
} }
@ -1520,31 +1512,27 @@ mod tests {
#[test] #[test]
fn insufficient_area_highlight_symbol_and_column_spacing_allocation() { fn insufficient_area_highlight_symbol_and_column_spacing_allocation() {
// column spacing is prioritized over every other constraint // column spacing is prioritized over every other constraint
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 10, // width
10, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE 1234", // spacing is prioritized and column is cut "ABCDE 1234", // spacing is prioritized and column is cut
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 10, // width
10, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE 1234", // spacing is prioritized and column is cut "ABCDE 1234", // spacing is prioritized and column is cut
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// this test checks that space for highlight_symbol space is always allocated. // this test checks that space for highlight_symbol space is always allocated.
@ -1555,59 +1543,51 @@ mod tests {
// Then in a separate step, column widths are calculated. // Then in a separate step, column widths are calculated.
// column spacing is prioritized when column widths are calculated and last column here // column spacing is prioritized when column widths are calculated and last column here
// ends up with just 1 wide // ends up with just 1 wide
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 10, // width
10, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" ABC 123", // highlight_symbol and spacing are prioritized " ABC 123", // highlight_symbol and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// the following are specification tests // the following are specification tests
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 9, // width
9, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" ABC 12", // highlight_symbol and spacing are prioritized " ABC 12", // highlight_symbol and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 8, // width
8, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" AB 12", // highlight_symbol and spacing are prioritized " AB 12", // highlight_symbol and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 7, // width
7, // width 1, // spacing
1, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" AB 1", // highlight_symbol and spacing are prioritized " AB 1", // highlight_symbol and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
let table = Table::default() let table = Table::default()
@ -1620,10 +1600,13 @@ mod tests {
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
Widget::render(table, area, &mut buf); Widget::render(table, area, &mut buf);
// highlight_symbol and spacing are prioritized but columns are evenly distributed // highlight_symbol and spacing are prioritized but columns are evenly distributed
assert_buffer_eq!( #[rustfmt::skip]
buf, let expected = Buffer::with_lines([
Buffer::with_lines(vec![" ABCDE 1", " ", " ",]) " ABCDE 1",
); " ",
" ",
]);
assert_eq!(buf, expected);
let table = Table::default() let table = Table::default()
.rows(vec![Row::new(vec!["ABCDE", "12345"])]) .rows(vec![Row::new(vec!["ABCDE", "12345"])])
@ -1635,137 +1618,122 @@ mod tests {
let mut buf = Buffer::empty(area); let mut buf = Buffer::empty(area);
Widget::render(table, area, &mut buf); Widget::render(table, area, &mut buf);
// highlight_symbol and spacing are prioritized but columns are evenly distributed // highlight_symbol and spacing are prioritized but columns are evenly distributed
assert_buffer_eq!( #[rustfmt::skip]
buf, let expected = Buffer::with_lines([
Buffer::with_lines(vec![" ABC 123", " ", " ",]) " ABC 123",
); " ",
" ",
]);
assert_eq!(buf, expected);
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 10, // width
10, // width 1, // spacing
1, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
"ABCDE 1234", // spacing is prioritized "ABCDE 1234", // spacing is prioritized
" ", " ",
" ", " ",
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 10, // width
10, // width 1, // spacing
1, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABC 123", // row 1 ">>>ABC 123", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 10, // width
10, // width 1, // spacing
1, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABC 123", // highlight column and spacing are prioritized ">>>ABC 123", // highlight column and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
} }
#[test] #[test]
fn insufficient_area_highlight_symbol_allocation_with_no_column_spacing() { fn insufficient_area_highlight_symbol_allocation_with_no_column_spacing() {
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 10, // width
10, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE12345", // row 1 "ABCDE12345", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 10, // width
10, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
"ABCDE12345", // row 1 "ABCDE12345", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
// highlight symbol spacing is prioritized over all constraints // highlight symbol spacing is prioritized over all constraints
// even if the constraints are fixed length // even if the constraints are fixed length
// this is because highlight_symbol column is separated _before_ any of the constraint // this is because highlight_symbol column is separated _before_ any of the constraint
// widths are calculated // widths are calculated
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 10, // width
10, // width 0, // spacing
0, // spacing None, // selection
None, // selection [
),
Buffer::with_lines(vec![
" ABCD123", // highlight column and spacing are prioritized " ABCD123", // highlight column and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Never,
HighlightSpacing::Never, 10, // width
10, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
"ABCDE12345", // row 1 "ABCDE12345", // row 1
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::WhenSelected,
HighlightSpacing::WhenSelected, 10, // width
10, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABCD123", // highlight column and spacing are prioritized ">>>ABCD123", // highlight column and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
assert_buffer_eq!( test_table_with_selection(
test_table_with_selection( HighlightSpacing::Always,
HighlightSpacing::Always, 10, // width
10, // width 0, // spacing
0, // spacing Some(0), // selection
Some(0), // selection [
),
Buffer::with_lines(vec![
">>>ABCD123", // highlight column and spacing are prioritized ">>>ABCD123", // highlight column and spacing are prioritized
" ", // row 2 " ", // row 2
" ", // row 3 " ", // row 3
]) ],
); );
} }
} }

View file

@ -333,7 +333,6 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::assert_buffer_eq;
#[test] #[test]
fn new() { fn new() {
@ -379,60 +378,61 @@ mod tests {
); );
} }
fn render(tabs: Tabs, area: Rect) -> Buffer { #[track_caller]
fn test_case(tabs: Tabs, area: Rect, expected: &Buffer) {
let mut buffer = Buffer::empty(area); let mut buffer = Buffer::empty(area);
tabs.render(area, &mut buffer); tabs.render(area, &mut buffer);
buffer assert_eq!(&buffer, expected);
} }
#[test] #[test]
fn render_default() { fn render_default() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]); let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]);
let mut expected = Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 "]); let mut expected = Buffer::with_lines([" Tab1 │ Tab2 │ Tab3 │ Tab4 "]);
// first tab selected // first tab selected
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE); expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected); test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
} }
#[test] #[test]
fn render_no_padding() { fn render_no_padding() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).padding("", ""); let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).padding("", "");
let mut expected = Buffer::with_lines(vec!["Tab1│Tab2│Tab3│Tab4 "]); let mut expected = Buffer::with_lines(["Tab1│Tab2│Tab3│Tab4 "]);
// first tab selected // first tab selected
expected.set_style(Rect::new(0, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE); expected.set_style(Rect::new(0, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected); test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
} }
#[test] #[test]
fn render_more_padding() { fn render_more_padding() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).padding("---", "++"); let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).padding("---", "++");
let mut expected = Buffer::with_lines(vec!["---Tab1++│---Tab2++│---Tab3++│"]); let mut expected = Buffer::with_lines(["---Tab1++│---Tab2++│---Tab3++│"]);
// first tab selected // first tab selected
expected.set_style(Rect::new(3, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE); expected.set_style(Rect::new(3, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected); test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
} }
#[test] #[test]
fn render_with_block() { fn render_with_block() {
let tabs = let tabs =
Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).block(Block::bordered().title("Tabs")); Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).block(Block::bordered().title("Tabs"));
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"┌Tabs────────────────────────┐", "┌Tabs────────────────────────┐",
"│ Tab1 │ Tab2 │ Tab3 │ Tab4 │", "│ Tab1 │ Tab2 │ Tab3 │ Tab4 │",
"└────────────────────────────┘", "└────────────────────────────┘",
]); ]);
// first tab selected // first tab selected
expected.set_style(Rect::new(2, 1, 4, 1), DEFAULT_HIGHLIGHT_STYLE); expected.set_style(Rect::new(2, 1, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 3)), expected); test_case(tabs, Rect::new(0, 0, 30, 3), &expected);
} }
#[test] #[test]
fn render_style() { fn render_style() {
let tabs = let tabs =
Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).style(Style::default().fg(Color::Red)); Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).style(Style::default().fg(Color::Red));
let mut expected = Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 ".red()]); let mut expected = Buffer::with_lines([" Tab1 │ Tab2 │ Tab3 │ Tab4 ".red()]);
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE.red()); expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE.red());
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected); test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
} }
#[test] #[test]
@ -440,40 +440,32 @@ mod tests {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]); let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]);
// first tab selected // first tab selected
assert_buffer_eq!( let expected = Buffer::with_lines([Line::from(vec![
render(tabs.clone().select(0), Rect::new(0, 0, 30, 1)), " ".into(),
Buffer::with_lines(vec![Line::from(vec![ "Tab1".reversed(),
" ".into(), " │ Tab2 │ Tab3 │ Tab4 ".into(),
"Tab1".reversed(), ])]);
" │ Tab2 │ Tab3 │ Tab4 ".into(), test_case(tabs.clone().select(0), Rect::new(0, 0, 30, 1), &expected);
])])
);
// second tab selected // second tab selected
assert_buffer_eq!( let expected = Buffer::with_lines([Line::from(vec![
render(tabs.clone().select(1), Rect::new(0, 0, 30, 1)), " Tab1 │ ".into(),
Buffer::with_lines(vec![Line::from(vec![ "Tab2".reversed(),
" Tab1 │ ".into(), " │ Tab3 │ Tab4 ".into(),
"Tab2".reversed(), ])]);
" │ Tab3 │ Tab4 ".into(), test_case(tabs.clone().select(1), Rect::new(0, 0, 30, 1), &expected);
])])
);
// last tab selected // last tab selected
assert_buffer_eq!( let expected = Buffer::with_lines([Line::from(vec![
render(tabs.clone().select(3), Rect::new(0, 0, 30, 1)), " Tab1 │ Tab2 │ Tab3 │ ".into(),
Buffer::with_lines(vec![Line::from(vec![ "Tab4".reversed(),
" Tab1 │ Tab2 │ Tab3 │ ".into(), " ".into(),
"Tab4".reversed(), ])]);
" ".into(), test_case(tabs.clone().select(3), Rect::new(0, 0, 30, 1), &expected);
])])
);
// out of bounds selects no tab // out of bounds selects no tab
assert_buffer_eq!( let expected = Buffer::with_lines([" Tab1 │ Tab2 │ Tab3 │ Tab4 "]);
render(tabs.clone().select(4), Rect::new(0, 0, 30, 1)), test_case(tabs.clone().select(4), Rect::new(0, 0, 30, 1), &expected);
Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 "])
);
} }
#[test] #[test]
@ -482,23 +474,21 @@ mod tests {
.style(Style::new().red()) .style(Style::new().red())
.highlight_style(Style::new().underlined()) .highlight_style(Style::new().underlined())
.select(0); .select(0);
assert_buffer_eq!( let expected = Buffer::with_lines([Line::from(vec![
render(tabs, Rect::new(0, 0, 30, 1)), " ".red(),
Buffer::with_lines(vec![Line::from(vec![ "Tab1".red().underlined(),
" ".red(), " │ Tab2 │ Tab3 │ Tab4 ".red(),
"Tab1".red().underlined(), ])]);
" │ Tab2 │ Tab3 │ Tab4 ".red(), test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
])])
);
} }
#[test] #[test]
fn render_divider() { fn render_divider() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).divider("--"); let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).divider("--");
let mut expected = Buffer::with_lines(vec![" Tab1 -- Tab2 -- Tab3 -- Tab4 "]); let mut expected = Buffer::with_lines([" Tab1 -- Tab2 -- Tab3 -- Tab4 "]);
// first tab selected // first tab selected
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE); expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected); test_case(tabs, Rect::new(0, 0, 30, 1), &expected);
} }
#[test] #[test]

View file

@ -42,7 +42,11 @@ impl AppState {
/// Renders the list to a `TestBackend` and asserts that the result matches the expected buffer. /// Renders the list to a `TestBackend` and asserts that the result matches the expected buffer.
#[track_caller] #[track_caller]
fn assert_buffer(state: &mut AppState, expected: &Buffer) { fn assert_buffer<'line, Lines>(state: &mut AppState, expected: Lines)
where
Lines: IntoIterator,
Lines::Item: Into<Line<'line>>,
{
let backend = TestBackend::new(21, 5); let backend = TestBackend::new(21, 5);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
terminal terminal
@ -76,7 +80,7 @@ fn assert_buffer(state: &mut AppState, expected: &Buffer) {
f.render_stateful_widget(scrollbar, layout[2], &mut state.scrollbar); f.render_stateful_widget(scrollbar, layout[2], &mut state.scrollbar);
}) })
.unwrap(); .unwrap();
terminal.backend().assert_buffer(expected); terminal.backend().assert_buffer_lines(expected);
} }
const DEFAULT_STATE_BUFFER: [&str; 5] = [ const DEFAULT_STATE_BUFFER: [&str; 5] = [
@ -106,19 +110,15 @@ const DEFAULT_STATE_REPR: &str = r#"{
#[test] #[test]
fn default_state_serialize() { fn default_state_serialize() {
let mut state = AppState::default(); let mut state = AppState::default();
assert_buffer(&mut state, DEFAULT_STATE_BUFFER);
let expected = Buffer::with_lines(DEFAULT_STATE_BUFFER);
assert_buffer(&mut state, &expected);
let state = serde_json::to_string_pretty(&state).unwrap(); let state = serde_json::to_string_pretty(&state).unwrap();
assert_eq!(state, DEFAULT_STATE_REPR); assert_eq!(state, DEFAULT_STATE_REPR);
} }
#[test] #[test]
fn default_state_deserialize() { fn default_state_deserialize() {
let expected = Buffer::with_lines(DEFAULT_STATE_BUFFER);
let mut state: AppState = serde_json::from_str(DEFAULT_STATE_REPR).unwrap(); let mut state: AppState = serde_json::from_str(DEFAULT_STATE_REPR).unwrap();
assert_buffer(&mut state, &expected); assert_buffer(&mut state, DEFAULT_STATE_BUFFER);
} }
const SELECTED_STATE_BUFFER: [&str; 5] = [ const SELECTED_STATE_BUFFER: [&str; 5] = [
@ -148,19 +148,15 @@ const SELECTED_STATE_REPR: &str = r#"{
fn selected_state_serialize() { fn selected_state_serialize() {
let mut state = AppState::default(); let mut state = AppState::default();
state.select(1); state.select(1);
assert_buffer(&mut state, SELECTED_STATE_BUFFER);
let expected = Buffer::with_lines(SELECTED_STATE_BUFFER);
assert_buffer(&mut state, &expected);
let state = serde_json::to_string_pretty(&state).unwrap(); let state = serde_json::to_string_pretty(&state).unwrap();
assert_eq!(state, SELECTED_STATE_REPR); assert_eq!(state, SELECTED_STATE_REPR);
} }
#[test] #[test]
fn selected_state_deserialize() { fn selected_state_deserialize() {
let expected = Buffer::with_lines(SELECTED_STATE_BUFFER);
let mut state: AppState = serde_json::from_str(SELECTED_STATE_REPR).unwrap(); let mut state: AppState = serde_json::from_str(SELECTED_STATE_REPR).unwrap();
assert_buffer(&mut state, &expected); assert_buffer(&mut state, SELECTED_STATE_BUFFER);
} }
const SCROLLED_STATE_BUFFER: [&str; 5] = [ const SCROLLED_STATE_BUFFER: [&str; 5] = [
@ -191,17 +187,13 @@ const SCROLLED_STATE_REPR: &str = r#"{
fn scrolled_state_serialize() { fn scrolled_state_serialize() {
let mut state = AppState::default(); let mut state = AppState::default();
state.select(8); state.select(8);
assert_buffer(&mut state, SCROLLED_STATE_BUFFER);
let expected = Buffer::with_lines(SCROLLED_STATE_BUFFER);
assert_buffer(&mut state, &expected);
let state = serde_json::to_string_pretty(&state).unwrap(); let state = serde_json::to_string_pretty(&state).unwrap();
assert_eq!(state, SCROLLED_STATE_REPR); assert_eq!(state, SCROLLED_STATE_REPR);
} }
#[test] #[test]
fn scrolled_state_deserialize() { fn scrolled_state_deserialize() {
let expected = Buffer::with_lines(SCROLLED_STATE_BUFFER);
let mut state: AppState = serde_json::from_str(SCROLLED_STATE_REPR).unwrap(); let mut state: AppState = serde_json::from_str(SCROLLED_STATE_REPR).unwrap();
assert_buffer(&mut state, &expected); assert_buffer(&mut state, SCROLLED_STATE_BUFFER);
} }

View file

@ -28,7 +28,7 @@ fn barchart_can_be_stylized() {
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
" ██ ", " ██ ",
" ▅▅ ██ ", " ▅▅ ██ ",
"▂▂ ██ ██ ", "▂▂ ██ ██ ",
@ -55,7 +55,6 @@ fn barchart_can_be_stylized() {
expected.get_mut(x * 3, 4).set_fg(Color::Blue); expected.get_mut(x * 3, 4).set_fg(Color::Blue);
expected.get_mut(x * 3 + 1, 4).set_fg(Color::Reset); expected.get_mut(x * 3 + 1, 4).set_fg(Color::Reset);
} }
terminal.backend().assert_buffer(&expected); terminal.backend().assert_buffer(&expected);
} }
@ -72,7 +71,8 @@ fn block_can_be_stylized() -> io::Result<()> {
f.render_widget(block, area); f.render_widget(block, area);
})?; })?;
let mut expected = Buffer::with_lines(vec![ #[rustfmt::skip]
let mut expected = Buffer::with_lines([
"┌Title─┐ ", "┌Title─┐ ",
"│ │ ", "│ │ ",
"└──────┘ ", "└──────┘ ",
@ -89,7 +89,6 @@ fn block_can_be_stylized() -> io::Result<()> {
for x in 1..=5 { for x in 1..=5 {
expected.get_mut(x, 0).set_fg(Color::LightBlue); expected.get_mut(x, 0).set_fg(Color::LightBlue);
} }
terminal.backend().assert_buffer(&expected); terminal.backend().assert_buffer(&expected);
Ok(()) Ok(())
} }
@ -104,7 +103,7 @@ fn paragraph_can_be_stylized() -> io::Result<()> {
f.render_widget(paragraph, area); f.render_widget(paragraph, area);
})?; })?;
let mut expected = Buffer::with_lines(vec!["Text "]); let mut expected = Buffer::with_lines(["Text "]);
for x in 0..4 { for x in 0..4 {
expected.get_mut(x, 0).set_fg(Color::Cyan); expected.get_mut(x, 0).set_fg(Color::Cyan);
} }

View file

@ -1,10 +1,8 @@
use std::error::Error; use std::error::Error;
use ratatui::{ use ratatui::{
assert_buffer_eq,
backend::{Backend, TestBackend}, backend::{Backend, TestBackend},
layout::Rect, layout::Rect,
prelude::Buffer,
widgets::{Paragraph, Widget}, widgets::{Paragraph, Widget},
Terminal, TerminalOptions, Viewport, Terminal, TerminalOptions, Viewport,
}; };
@ -105,16 +103,13 @@ fn terminal_insert_before_moves_viewport() -> Result<(), Box<dyn Error>> {
f.render_widget(paragraph, f.size()); f.render_widget(paragraph, f.size());
})?; })?;
assert_buffer_eq!( terminal.backend().assert_buffer_lines([
terminal.backend().buffer().clone(), "------ Line 1 ------",
Buffer::with_lines(vec![ "------ Line 2 ------",
"------ Line 1 ------", "[---- Viewport ----]",
"------ Line 2 ------", " ",
"[---- Viewport ----]", " ",
" ", ]);
" ",
])
);
Ok(()) Ok(())
} }
@ -150,16 +145,13 @@ fn terminal_insert_before_scrolls_on_large_input() -> Result<(), Box<dyn Error>>
f.render_widget(paragraph, f.size()); f.render_widget(paragraph, f.size());
})?; })?;
assert_buffer_eq!( terminal.backend().assert_buffer_lines([
terminal.backend().buffer().clone(), "------ Line 2 ------",
Buffer::with_lines(vec![ "------ Line 3 ------",
"------ Line 2 ------", "------ Line 4 ------",
"------ Line 3 ------", "------ Line 5 ------",
"------ Line 4 ------", "[---- Viewport ----]",
"------ Line 5 ------", ]);
"[---- Viewport ----]",
])
);
Ok(()) Ok(())
} }
@ -205,16 +197,13 @@ fn terminal_insert_before_scrolls_on_many_inserts() -> Result<(), Box<dyn Error>
f.render_widget(paragraph, f.size()); f.render_widget(paragraph, f.size());
})?; })?;
assert_buffer_eq!( terminal.backend().assert_buffer_lines([
terminal.backend().buffer().clone(), "------ Line 2 ------",
Buffer::with_lines(vec![ "------ Line 3 ------",
"------ Line 2 ------", "------ Line 4 ------",
"------ Line 3 ------", "------ Line 5 ------",
"------ Line 4 ------", "[---- Viewport ----]",
"------ Line 5 ------", ]);
"[---- Viewport ----]",
])
);
Ok(()) Ok(())
} }

View file

@ -6,29 +6,24 @@ use ratatui::{
Terminal, Terminal,
}; };
// check that bars fill up correctly up to max value
#[test] #[test]
fn widgets_barchart_not_full_below_max_value() { fn widgets_barchart_not_full_below_max_value() {
let test_case = |expected| { let backend = TestBackend::new(30, 10);
let backend = TestBackend::new(30, 10); let mut terminal = Terminal::new(backend).unwrap();
let mut terminal = Terminal::new(backend).unwrap(); terminal
.draw(|f| {
terminal let size = f.size();
.draw(|f| { let barchart = BarChart::default()
let size = f.size(); .block(Block::bordered())
let barchart = BarChart::default() .data(&[("empty", 0), ("half", 50), ("almost", 99), ("full", 100)])
.block(Block::bordered()) .max(100)
.data(&[("empty", 0), ("half", 50), ("almost", 99), ("full", 100)]) .bar_width(7)
.max(100) .bar_gap(0);
.bar_width(7) f.render_widget(barchart, size);
.bar_gap(0); })
f.render_widget(barchart, size); .unwrap();
}) terminal.backend().assert_buffer_lines([
.unwrap();
terminal.backend().assert_buffer(&expected);
};
// check that bars fill up correctly up to max value
test_case(Buffer::with_lines(vec![
"┌────────────────────────────┐", "┌────────────────────────────┐",
"│ ▇▇▇▇▇▇▇███████│", "│ ▇▇▇▇▇▇▇███████│",
"│ ██████████████│", "│ ██████████████│",
@ -39,47 +34,43 @@ fn widgets_barchart_not_full_below_max_value() {
"│ ██50█████99█████100██│", "│ ██50█████99█████100██│",
"│ empty half almost full │", "│ empty half almost full │",
"└────────────────────────────┘", "└────────────────────────────┘",
])); ]);
} }
#[test] #[test]
fn widgets_barchart_group() { fn widgets_barchart_group() {
const TERMINAL_HEIGHT: u16 = 11; const TERMINAL_HEIGHT: u16 = 11;
let test_case = |expected| { let backend = TestBackend::new(35, TERMINAL_HEIGHT);
let backend = TestBackend::new(35, TERMINAL_HEIGHT); let mut terminal = Terminal::new(backend).unwrap();
let mut terminal = Terminal::new(backend).unwrap(); terminal
.draw(|f| {
let size = f.size();
let barchart = BarChart::default()
.block(Block::bordered())
.data(
BarGroup::default().label("Mar".into()).bars(&[
Bar::default()
.value(10)
.label("C1".into())
.style(Style::default().fg(Color::Red))
.value_style(Style::default().fg(Color::Blue)),
Bar::default()
.value(20)
.style(Style::default().fg(Color::Green))
.text_value("20M".to_string()),
]),
)
.data(&vec![("C1", 50), ("C2", 40)])
.data(&[("C1", 60), ("C2", 90)])
.data(&[("xx", 10), ("xx", 10)])
.group_gap(2)
.bar_width(4)
.bar_gap(1);
f.render_widget(barchart, size);
})
.unwrap();
terminal let mut expected = Buffer::with_lines([
.draw(|f| {
let size = f.size();
let barchart = BarChart::default()
.block(Block::bordered())
.data(
BarGroup::default().label("Mar".into()).bars(&[
Bar::default()
.value(10)
.label("C1".into())
.style(Style::default().fg(Color::Red))
.value_style(Style::default().fg(Color::Blue)),
Bar::default()
.value(20)
.style(Style::default().fg(Color::Green))
.text_value("20M".to_string()),
]),
)
.data(&vec![("C1", 50), ("C2", 40)])
.data(&[("C1", 60), ("C2", 90)])
.data(&[("xx", 10), ("xx", 10)])
.group_gap(2)
.bar_width(4)
.bar_gap(1);
f.render_widget(barchart, size);
})
.unwrap();
terminal.backend().assert_buffer(&expected);
};
let mut expected = Buffer::with_lines(vec![
"┌─────────────────────────────────┐", "┌─────────────────────────────────┐",
"│ ████│", "│ ████│",
"│ ████│", "│ ████│",
@ -92,16 +83,13 @@ fn widgets_barchart_group() {
"│Mar │", "│Mar │",
"└─────────────────────────────────┘", "└─────────────────────────────────┘",
]); ]);
for y in 1..(TERMINAL_HEIGHT - 3) { for y in 1..(TERMINAL_HEIGHT - 3) {
for x in 1..5 { for x in 1..5 {
expected.get_mut(x, y).set_fg(Color::Red); expected.get_mut(x, y).set_fg(Color::Red);
expected.get_mut(x + 5, y).set_fg(Color::Green); expected.get_mut(x + 5, y).set_fg(Color::Green);
} }
} }
expected.get_mut(2, 7).set_fg(Color::Blue); expected.get_mut(2, 7).set_fg(Color::Blue);
expected.get_mut(3, 7).set_fg(Color::Blue); expected.get_mut(3, 7).set_fg(Color::Blue);
terminal.backend().assert_buffer(&expected);
test_case(expected);
} }

File diff suppressed because it is too large Load diff

View file

@ -12,10 +12,9 @@ use ratatui::{
use time::{Date, Month}; use time::{Date, Month};
#[track_caller] #[track_caller]
fn test_render<W: Widget>(widget: W, expected: &Buffer, width: u16, height: u16) { fn test_render<W: Widget>(widget: W, width: u16, height: u16, expected: &Buffer) {
let backend = TestBackend::new(width, height); let backend = TestBackend::new(width, height);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
terminal terminal
.draw(|f| f.render_widget(widget, f.size())) .draw(|f| f.render_widget(widget, f.size()))
.unwrap(); .unwrap();
@ -28,14 +27,14 @@ fn days_layout() {
Date::from_calendar_date(2023, Month::January, 1).unwrap(), Date::from_calendar_date(2023, Month::January, 1).unwrap(),
CalendarEventStore::default(), CalendarEventStore::default(),
); );
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" 1 2 3 4 5 6 7", " 1 2 3 4 5 6 7",
" 8 9 10 11 12 13 14", " 8 9 10 11 12 13 14",
" 15 16 17 18 19 20 21", " 15 16 17 18 19 20 21",
" 22 23 24 25 26 27 28", " 22 23 24 25 26 27 28",
" 29 30 31", " 29 30 31",
]); ]);
test_render(c, &expected, 21, 5); test_render(c, 21, 5, &expected);
} }
#[test] #[test]
@ -45,7 +44,7 @@ fn days_layout_show_surrounding() {
CalendarEventStore::default(), CalendarEventStore::default(),
) )
.show_surrounding(Style::default()); .show_surrounding(Style::default());
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" 26 27 28 29 30 1 2", " 26 27 28 29 30 1 2",
" 3 4 5 6 7 8 9", " 3 4 5 6 7 8 9",
" 10 11 12 13 14 15 16", " 10 11 12 13 14 15 16",
@ -53,7 +52,7 @@ fn days_layout_show_surrounding() {
" 24 25 26 27 28 29 30", " 24 25 26 27 28 29 30",
" 31 1 2 3 4 5 6", " 31 1 2 3 4 5 6",
]); ]);
test_render(c, &expected, 21, 6); test_render(c, 21, 6, &expected);
} }
#[test] #[test]
@ -63,7 +62,7 @@ fn show_month_header() {
CalendarEventStore::default(), CalendarEventStore::default(),
) )
.show_month_header(Style::default()); .show_month_header(Style::default());
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" January 2023 ", " January 2023 ",
" 1 2 3 4 5 6 7", " 1 2 3 4 5 6 7",
" 8 9 10 11 12 13 14", " 8 9 10 11 12 13 14",
@ -71,7 +70,7 @@ fn show_month_header() {
" 22 23 24 25 26 27 28", " 22 23 24 25 26 27 28",
" 29 30 31", " 29 30 31",
]); ]);
test_render(c, &expected, 21, 6); test_render(c, 21, 6, &expected);
} }
#[test] #[test]
@ -81,7 +80,7 @@ fn show_weekdays_header() {
CalendarEventStore::default(), CalendarEventStore::default(),
) )
.show_weekdays_header(Style::default()); .show_weekdays_header(Style::default());
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" Su Mo Tu We Th Fr Sa", " Su Mo Tu We Th Fr Sa",
" 1 2 3 4 5 6 7", " 1 2 3 4 5 6 7",
" 8 9 10 11 12 13 14", " 8 9 10 11 12 13 14",
@ -89,7 +88,7 @@ fn show_weekdays_header() {
" 22 23 24 25 26 27 28", " 22 23 24 25 26 27 28",
" 29 30 31", " 29 30 31",
]); ]);
test_render(c, &expected, 21, 6); test_render(c, 21, 6, &expected);
} }
#[test] #[test]
@ -101,7 +100,7 @@ fn show_combo() {
.show_weekdays_header(Style::default()) .show_weekdays_header(Style::default())
.show_month_header(Style::default()) .show_month_header(Style::default())
.show_surrounding(Style::default()); .show_surrounding(Style::default());
let expected = Buffer::with_lines(vec![ let expected = Buffer::with_lines([
" January 2023 ", " January 2023 ",
" Su Mo Tu We Th Fr Sa", " Su Mo Tu We Th Fr Sa",
" 1 2 3 4 5 6 7", " 1 2 3 4 5 6 7",
@ -110,5 +109,5 @@ fn show_combo() {
" 22 23 24 25 26 27 28", " 22 23 24 25 26 27 28",
" 29 30 31 1 2 3 4", " 29 30 31 1 2 3 4",
]); ]);
test_render(c, &expected, 21, 7); test_render(c, 21, 7, &expected);
} }

View file

@ -29,7 +29,7 @@ fn widgets_canvas_draw_labels() {
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![" ", " ", " ", " ", "test "]); let mut expected = Buffer::with_lines(["", "", "", "", "test "]);
for row in 0..5 { for row in 0..5 {
for col in 0..5 { for col in 0..5 {
expected.get_mut(col, row).set_bg(Color::Yellow); expected.get_mut(col, row).set_bg(Color::Yellow);

View file

@ -14,9 +14,16 @@ fn create_labels<'a>(labels: &'a [&'a str]) -> Vec<Span<'a>> {
labels.iter().map(|l| Span::from(*l)).collect() labels.iter().map(|l| Span::from(*l)).collect()
} }
fn axis_test_case<'a, S>(width: u16, height: u16, x_axis: Axis, y_axis: Axis, lines: Vec<S>) #[track_caller]
where fn axis_test_case<'line, Lines>(
S: Into<text::Line<'a>>, width: u16,
height: u16,
x_axis: Axis,
y_axis: Axis,
expected: Lines,
) where
Lines: IntoIterator,
Lines::Item: Into<text::Line<'line>>,
{ {
let backend = TestBackend::new(width, height); let backend = TestBackend::new(width, height);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
@ -26,8 +33,7 @@ where
f.render_widget(chart, f.size()); f.render_widget(chart, f.size());
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(lines); terminal.backend().assert_buffer_lines(expected);
terminal.backend().assert_buffer(&expected);
} }
#[rstest] #[rstest]
@ -62,195 +68,192 @@ fn widgets_chart_can_render_on_small_areas(#[case] width: u16, #[case] height: u
.unwrap(); .unwrap();
} }
#[test] #[rstest]
fn widgets_chart_handles_long_labels() { #[case(
let test_case = |x_labels, y_labels, x_alignment, lines| { Some(("AAAA", "B")),
let mut x_axis = Axis::default().bounds([0.0, 1.0]); None,
if let Some((left_label, right_label)) = x_labels { Alignment::Left,
x_axis = x_axis vec![
.labels(vec![Span::from(left_label), Span::from(right_label)]) " ",
.labels_alignment(x_alignment); " ",
} " ",
" ───────",
let mut y_axis = Axis::default().bounds([0.0, 1.0]); "AAA B",
if let Some((left_label, right_label)) = y_labels { ],
y_axis = y_axis.labels(vec![Span::from(left_label), Span::from(right_label)]); )]
} #[case(
Some(("A", "BBBB")),
axis_test_case(10, 5, x_axis, y_axis, lines); None,
}; Alignment::Left,
vec![
test_case( " ",
Some(("AAAA", "B")), " ",
None, " ",
Alignment::Left, " ─────────",
vec![ "A BBBB",
" ", ],
" ", )]
" ", #[case(
" ───────", Some(("AAAAAAAAAAA", "B")),
"AAA B", None,
], Alignment::Left,
); vec![
test_case( " ",
Some(("A", "BBBB")), " ",
None, " ",
Alignment::Left, " ───────",
vec![ "AAA B",
" ", ],
" ", )]
" ", #[case(
" ─────────", Some(("A", "B")),
"A BBBB", Some(("CCCCCCC", "D")),
], Alignment::Left,
); vec![
test_case( "D │ ",
Some(("AAAAAAAAAAA", "B")), "",
None, "CCC│ ",
Alignment::Left, " └──────",
vec![ " A B",
" ", ],
" ", )]
" ", #[case(
" ───────", Some(("AAAAAAAAAA", "B")),
"AAA B", Some(("C", "D")),
], Alignment::Center,
); vec![
test_case( "D │ ",
Some(("A", "B")), "",
Some(("CCCCCCC", "D")), "C │ ",
Alignment::Left, " └──────",
vec![ "AAAAAAA B",
"D │ ", ],
"", )]
"CCC│ ", #[case(
" └──────", Some(("AAAAAAA", "B")),
" A B", Some(("C", "D")),
], Alignment::Right,
); vec![
test_case( "D│ ",
Some(("AAAAAAAAAA", "B")), "",
Some(("C", "D")), "C│ ",
Alignment::Center, " └────────",
vec![ " AAAAA B",
"D │ ", ],
"", )]
"C │ ", #[case(
" └──────", Some(("AAAAAAA", "BBBBBBB")),
"AAAAAAA B", Some(("C", "D")),
], Alignment::Right,
); vec![
test_case( "D│ ",
Some(("AAAAAAA", "B")), "",
Some(("C", "D")), "C│ ",
Alignment::Right, " └────────",
vec![ " AAAAABBBB",
"D│ ", ],
"", )]
"C│ ", fn widgets_chart_handles_long_labels<'line, Lines>(
" └────────", #[case] x_labels: Option<(&str, &str)>,
" AAAAA B", #[case] y_labels: Option<(&str, &str)>,
], #[case] x_alignment: Alignment,
); #[case] expected: Lines,
test_case( ) where
Some(("AAAAAAA", "BBBBBBB")), Lines: IntoIterator,
Some(("C", "D")), Lines::Item: Into<text::Line<'line>>,
Alignment::Right, {
vec![ let mut x_axis = Axis::default().bounds([0.0, 1.0]);
"D│ ", if let Some((left_label, right_label)) = x_labels {
"", x_axis = x_axis
"C│ ", .labels(vec![Span::from(left_label), Span::from(right_label)])
" └────────", .labels_alignment(x_alignment);
" AAAAABBBB", }
], let mut y_axis = Axis::default().bounds([0.0, 1.0]);
); if let Some((left_label, right_label)) = y_labels {
y_axis = y_axis.labels(vec![Span::from(left_label), Span::from(right_label)]);
}
axis_test_case(10, 5, x_axis, y_axis, expected);
} }
#[test] #[rstest]
fn widgets_chart_handles_x_axis_labels_alignments() { #[case::left(
let test_case = |y_alignment, lines| { Alignment::Left,
let x_axis = Axis::default() vec![
.labels(vec![Span::from("AAAA"), Span::from("B"), Span::from("C")]) " ",
.labels_alignment(y_alignment); " ",
" ",
let y_axis = Axis::default(); " ───────",
"AAA B C",
axis_test_case(10, 5, x_axis, y_axis, lines); ],
}; )]
#[case::center(
test_case( Alignment::Center,
Alignment::Left, vec![
vec![ " ",
" ", " ",
" ", " ",
" ", " ────────",
" ───────", "AAAA B C",
"AAA B C", ],
], )]
); #[case::right(
test_case( Alignment::Right,
Alignment::Center, vec![
vec![ " ",
" ", " ",
" ", " ",
" ", "──────────",
" ────────", "AAA B C",
"AAAA B C", ],
], )]
); fn widgets_chart_handles_x_axis_labels_alignments<'line, Lines>(
test_case( #[case] y_alignment: Alignment,
Alignment::Right, #[case] expected: Lines,
vec![ ) where
" ", Lines: IntoIterator,
" ", Lines::Item: Into<text::Line<'line>>,
" ", {
"──────────", let x_axis = Axis::default()
"AAA B C", .labels(vec![Span::from("AAAA"), Span::from("B"), Span::from("C")])
], .labels_alignment(y_alignment);
); let y_axis = Axis::default();
axis_test_case(10, 5, x_axis, y_axis, expected);
} }
#[test] #[rstest]
fn widgets_chart_handles_y_axis_labels_alignments() { #[case::left(Alignment::Left, [
let test_case = |y_alignment, lines| { "D │ ",
let x_axis = Axis::default().labels(create_labels(&["AAAAA", "B"])); "",
"C │ ",
let y_axis = Axis::default() " └───────────────",
.labels(create_labels(&["C", "D"])) "AAAAA B",
.labels_alignment(y_alignment); ])]
#[case::center(Alignment::Center, [
axis_test_case(20, 5, x_axis, y_axis, lines); " D │ ",
}; "",
test_case( " C │ ",
Alignment::Left, " └───────────────",
vec![ "AAAAA B",
"D │ ", ])]
"", #[case::right(Alignment::Right, [
"C │ ", " D│ ",
" └───────────────", "",
"AAAAA B", " C│ ",
], " └───────────────",
); "AAAAA B",
test_case( ])]
Alignment::Center, fn widgets_chart_handles_y_axis_labels_alignments<'line, Lines>(
vec![ #[case] y_alignment: Alignment,
" D │ ", #[case] expected: Lines,
"", ) where
" C │ ", Lines: IntoIterator,
" └───────────────", Lines::Item: Into<text::Line<'line>>,
"AAAAA B", {
], let x_axis = Axis::default().labels(create_labels(&["AAAAA", "B"]));
); let y_axis = Axis::default()
test_case( .labels(create_labels(&["C", "D"]))
Alignment::Right, .labels_alignment(y_alignment);
vec![ axis_test_case(20, 5, x_axis, y_axis, expected);
" D│ ",
"",
" C│ ",
" └───────────────",
"AAAAA B",
],
);
} }
#[test] #[test]
@ -431,7 +434,7 @@ fn widgets_chart_can_have_a_legend() {
); );
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"┌Chart Test────────────────────────────────────────────────┐", "┌Chart Test────────────────────────────────────────────────┐",
"│10.0│Y Axis ┌─────────┐│", "│10.0│Y Axis ┌─────────┐│",
"│ │ •• │Dataset 1││", "│ │ •• │Dataset 1││",
@ -611,7 +614,6 @@ fn widgets_chart_can_have_a_legend() {
for (col, row) in x_axis_title { for (col, row) in x_axis_title {
expected.get_mut(col, row).set_fg(Color::Yellow); expected.get_mut(col, row).set_fg(Color::Yellow);
} }
terminal.backend().assert_buffer(&expected); terminal.backend().assert_buffer(&expected);
} }
@ -641,7 +643,7 @@ fn widgets_chart_top_line_styling_is_correct() {
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"b│abc••••", "b│abc••••",
"", "",
"", "",

View file

@ -35,7 +35,7 @@ fn widgets_gauge_renders() {
f.render_widget(gauge, chunks[1]); f.render_widget(gauge, chunks[1]);
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
" ", " ",
" ", " ",
" ┌Percentage────────────────────────┐ ", " ┌Percentage────────────────────────┐ ",
@ -82,7 +82,7 @@ fn widgets_gauge_renders_no_unicode() {
f.render_widget(gauge, chunks[1]); f.render_widget(gauge, chunks[1]);
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(vec![ terminal.backend().assert_buffer_lines([
" ", " ",
" ", " ",
" ┌Percentage────────────────────────┐ ", " ┌Percentage────────────────────────┐ ",
@ -94,7 +94,6 @@ fn widgets_gauge_renders_no_unicode() {
" ", " ",
" ", " ",
]); ]);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
@ -119,7 +118,7 @@ fn widgets_gauge_applies_styles() {
f.render_widget(gauge, f.size()); f.render_widget(gauge, f.size());
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"┌Test──────┐", "┌Test──────┐",
"│████ │", "│████ │",
"│███43% │", "│███43% │",
@ -171,8 +170,7 @@ fn widgets_gauge_supports_large_labels() {
f.render_widget(gauge, f.size()); f.render_widget(gauge, f.size());
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(vec!["4333333333"]); terminal.backend().assert_buffer_lines(["4333333333"]);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
@ -209,7 +207,7 @@ fn widgets_line_gauge_renders() {
); );
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
"43% ────────────────", "43% ────────────────",
"┌Gauge 2───────────┐", "┌Gauge 2───────────┐",
"│21% ━━━━━━━━━━━━━━│", "│21% ━━━━━━━━━━━━━━│",

View file

@ -8,6 +8,7 @@ use ratatui::{
widgets::{Block, Borders, HighlightSpacing, List, ListItem, ListState}, widgets::{Block, Borders, HighlightSpacing, List, ListItem, ListState},
Terminal, Terminal,
}; };
use rstest::rstest;
#[test] #[test]
fn list_should_shows_the_length() { fn list_should_shows_the_length() {
@ -45,7 +46,12 @@ fn widgets_list_should_highlight_the_selected_item() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![" Item 1 ", ">> Item 2 ", " Item 3 "]); #[rustfmt::skip]
let mut expected = Buffer::with_lines([
" Item 1 ",
">> Item 2 ",
" Item 3 ",
]);
for x in 0..10 { for x in 0..10 {
expected.get_mut(x, 1).set_bg(Color::Yellow); expected.get_mut(x, 1).set_bg(Color::Yellow);
} }
@ -75,9 +81,12 @@ fn widgets_list_should_highlight_the_selected_item_wide_symbol() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
#[rustfmt::skip]
let mut expected = Buffer::with_lines(vec![" Item 1 ", "▶ Item 2 ", " Item 3 "]); let mut expected = Buffer::with_lines([
" Item 1 ",
"▶ Item 2 ",
" Item 3 ",
]);
for x in 0..10 { for x in 0..10 {
expected.get_mut(x, 1).set_bg(Color::Yellow); expected.get_mut(x, 1).set_bg(Color::Yellow);
} }
@ -95,7 +104,7 @@ fn widgets_list_should_truncate_items() {
let backend = TestBackend::new(10, 2); let backend = TestBackend::new(10, 2);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
let cases = vec![ let cases = [
// An item is selected // An item is selected
TruncateTestCase { TruncateTestCase {
selected: Some(0), selected: Some(0),
@ -103,7 +112,7 @@ fn widgets_list_should_truncate_items() {
ListItem::new("A very long line"), ListItem::new("A very long line"),
ListItem::new("A very long line"), ListItem::new("A very long line"),
], ],
expected: Buffer::with_lines(vec![ expected: Buffer::with_lines([
format!(">> A ve{} ", symbols::line::VERTICAL), format!(">> A ve{} ", symbols::line::VERTICAL),
format!(" A ve{} ", symbols::line::VERTICAL), format!(" A ve{} ", symbols::line::VERTICAL),
]), ]),
@ -115,7 +124,7 @@ fn widgets_list_should_truncate_items() {
ListItem::new("A very long line"), ListItem::new("A very long line"),
ListItem::new("A very long line"), ListItem::new("A very long line"),
], ],
expected: Buffer::with_lines(vec![ expected: Buffer::with_lines([
format!("A very {} ", symbols::line::VERTICAL), format!("A very {} ", symbols::line::VERTICAL),
format!("A very {} ", symbols::line::VERTICAL), format!("A very {} ", symbols::line::VERTICAL),
]), ]),
@ -159,8 +168,12 @@ fn widgets_list_should_clamp_offset_if_items_are_removed() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(vec![" Item 2 ", " Item 3 ", " Item 4 ", ">> Item 5 "]); terminal.backend().assert_buffer_lines([
terminal.backend().assert_buffer(&expected); " Item 2 ",
" Item 3 ",
" Item 4 ",
">> Item 5 ",
]);
// render again with 1 items => check offset is clamped to 1 // render again with 1 items => check offset is clamped to 1
state.select(Some(1)); state.select(Some(1));
@ -172,8 +185,12 @@ fn widgets_list_should_clamp_offset_if_items_are_removed() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(vec![" Item 3 ", " ", " ", " "]); terminal.backend().assert_buffer_lines([
terminal.backend().assert_buffer(&expected); " Item 3 ",
" ",
" ",
" ",
]);
} }
#[test] #[test]
@ -196,7 +213,7 @@ fn widgets_list_should_display_multiline_items() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
" Item 1 ", " Item 1 ",
" Item 1a", " Item 1a",
">> Item 2 ", ">> Item 2 ",
@ -232,7 +249,7 @@ fn widgets_list_should_repeat_highlight_symbol() {
f.render_stateful_widget(list, size, &mut state); f.render_stateful_widget(list, size, &mut state);
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![ let mut expected = Buffer::with_lines([
" Item 1 ", " Item 1 ",
" Item 1a", " Item 1a",
">> Item 2 ", ">> Item 2 ",
@ -251,7 +268,6 @@ fn widgets_list_should_repeat_highlight_symbol() {
fn widget_list_should_not_ignore_empty_string_items() { fn widget_list_should_not_ignore_empty_string_items() {
let backend = TestBackend::new(6, 4); let backend = TestBackend::new(6, 4);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
terminal terminal
.draw(|f| { .draw(|f| {
let items = vec![ let items = vec![
@ -268,134 +284,98 @@ fn widget_list_should_not_ignore_empty_string_items() {
f.render_widget(list, f.size()); f.render_widget(list, f.size());
}) })
.unwrap(); .unwrap();
terminal
let expected = Buffer::with_lines(vec!["Item 1", "", "", "Item 4"]); .backend()
.assert_buffer_lines(["Item 1", "", "", "Item 4"]);
terminal.backend().assert_buffer(&expected);
} }
#[allow(clippy::too_many_lines)] #[rstest]
#[test] #[case::none_when_selected(None, HighlightSpacing::WhenSelected, [
fn widgets_list_enable_always_highlight_spacing() { "┌─────────────┐",
let test_case = |state: &mut ListState, space: HighlightSpacing, expected: Buffer| { "│Item 1 │",
let backend = TestBackend::new(30, 8); "│Item 1a │",
let mut terminal = Terminal::new(backend).unwrap(); "│Item 2 │",
terminal "│Item 2b │",
.draw(|f| { "│Item 3 │",
let size = f.size(); "│Item 3c │",
let table = List::new(vec![ "└─────────────┘",
ListItem::new(vec![Line::from("Item 1"), Line::from("Item 1a")]), ])]
ListItem::new(vec![Line::from("Item 2"), Line::from("Item 2b")]), #[case::none_always(None, HighlightSpacing::Always, [
ListItem::new(vec![Line::from("Item 3"), Line::from("Item 3c")]), "┌─────────────┐",
]) "│ Item 1 │",
.block(Block::bordered()) "│ Item 1a │",
.highlight_symbol(">> ") "│ Item 2 │",
.highlight_spacing(space); "│ Item 2b │",
f.render_stateful_widget(table, size, state); "│ Item 3 │",
}) "│ Item 3c │",
.unwrap(); "└─────────────┘",
terminal.backend().assert_buffer(&expected); ])]
}; #[case::none_never(None, HighlightSpacing::Never, [
"┌─────────────┐",
assert_eq!(HighlightSpacing::default(), HighlightSpacing::WhenSelected); "│Item 1 │",
"│Item 1a │",
let mut state = ListState::default(); "│Item 2 │",
// no selection, "WhenSelected" should only allocate if selected "│Item 2b │",
test_case( "│Item 3 │",
&mut state, "│Item 3c │",
HighlightSpacing::default(), "└─────────────┘",
Buffer::with_lines(vec![ ])]
"┌────────────────────────────┐", #[case::first_when_selected(Some(0), HighlightSpacing::WhenSelected, [
"│Item 1 │", "┌─────────────┐",
"│Item 1a │", "│>> Item 1 │",
"│Item 2 │", "│ Item 1a │",
"│Item 2b │", "│ Item 2 │",
"│Item 3 │", "│ Item 2b │",
"│Item 3c │", "│ Item 3 │",
"└────────────────────────────┘", "│ Item 3c │",
]), "└─────────────┘",
); ])]
#[case::first_always(Some(0), HighlightSpacing::Always, [
// no selection, "Always" should allocate regardless if selected or not "┌─────────────┐",
test_case( "│>> Item 1 │",
&mut state, "│ Item 1a │",
HighlightSpacing::Always, "│ Item 2 │",
Buffer::with_lines(vec![ "│ Item 2b │",
"┌────────────────────────────┐", "│ Item 3 │",
"│ Item 1 │", "│ Item 3c │",
"│ Item 1a │", "└─────────────┘",
"│ Item 2 │", ])]
"│ Item 2b │", #[case::first_never(Some(0), HighlightSpacing::Never, [
"│ Item 3 │", "┌─────────────┐",
"│ Item 3c │", "│Item 1 │",
"└────────────────────────────┘", "│Item 1a │",
]), "│Item 2 │",
); "│Item 2b │",
"│Item 3 │",
// no selection, "Never" should never allocate regadless if selected or not "│Item 3c │",
test_case( "└─────────────┘",
&mut state, ])]
HighlightSpacing::Never, fn widgets_list_enable_always_highlight_spacing<'line, Lines>(
Buffer::with_lines(vec![ #[case] selected: Option<usize>,
"┌────────────────────────────┐", #[case] space: HighlightSpacing,
"│Item 1 │", #[case] expected: Lines,
"│Item 1a │", ) where
"│Item 2 │", Lines: IntoIterator,
"│Item 2b │", Lines::Item: Into<Line<'line>>,
"│Item 3 │", {
"│Item 3c │", let mut state = ListState::default().with_selected(selected);
"└────────────────────────────┘", let backend = TestBackend::new(15, 8);
]), let mut terminal = Terminal::new(backend).unwrap();
); terminal
.draw(|f| {
// select first, "WhenSelected" should only allocate if selected let size = f.size();
state.select(Some(0)); let table = List::new(vec![
test_case( ListItem::new(vec![Line::from("Item 1"), Line::from("Item 1a")]),
&mut state, ListItem::new(vec![Line::from("Item 2"), Line::from("Item 2b")]),
HighlightSpacing::default(), ListItem::new(vec![Line::from("Item 3"), Line::from("Item 3c")]),
Buffer::with_lines(vec![ ])
"┌────────────────────────────┐", .block(Block::bordered())
"│>> Item 1 │", .highlight_symbol(">> ")
"│ Item 1a │", .highlight_spacing(space);
"│ Item 2 │", f.render_stateful_widget(table, size, &mut state);
"│ Item 2b │", })
"│ Item 3 │", .unwrap();
"│ Item 3c │", terminal
"└────────────────────────────┘", .backend()
]), .assert_buffer(&Buffer::with_lines(expected));
);
// select first, "Always" should allocate regardless if selected or not
state.select(Some(0));
test_case(
&mut state,
HighlightSpacing::Always,
Buffer::with_lines(vec![
"┌────────────────────────────┐",
"│>> Item 1 │",
"│ Item 1a │",
"│ Item 2 │",
"│ Item 2b │",
"│ Item 3 │",
"│ Item 3c │",
"└────────────────────────────┘",
]),
);
// select first, "Never" should never allocate regadless if selected or not
state.select(Some(0));
test_case(
&mut state,
HighlightSpacing::Never,
Buffer::with_lines(vec![
"┌────────────────────────────┐",
"│Item 1 │",
"│Item 1a │",
"│Item 2 │",
"│Item 2b │",
"│Item 3 │",
"│Item 3c │",
"└────────────────────────────┘",
]),
);
} }

View file

@ -9,19 +9,17 @@ use ratatui::{
/// Tests the [`Paragraph`] widget against the expected [`Buffer`] by rendering it onto an equal /// Tests the [`Paragraph`] widget against the expected [`Buffer`] by rendering it onto an equal
/// area and comparing the rendered and expected content. /// area and comparing the rendered and expected content.
#[allow(clippy::needless_pass_by_value)] #[track_caller]
fn test_case(paragraph: Paragraph, expected: Buffer) { fn test_case(paragraph: Paragraph, expected: &Buffer) {
let backend = TestBackend::new(expected.area.width, expected.area.height); let backend = TestBackend::new(expected.area.width, expected.area.height);
let mut terminal = Terminal::new(backend).unwrap(); let mut terminal = Terminal::new(backend).unwrap();
terminal terminal
.draw(|f| { .draw(|f| {
let size = f.size(); let size = f.size();
f.render_widget(paragraph, size); f.render_widget(paragraph, size);
}) })
.unwrap(); .unwrap();
terminal.backend().assert_buffer(expected);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
@ -35,7 +33,7 @@ fn widgets_paragraph_renders_double_width_graphemes() {
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌────────┐", "┌────────┐",
"│コンピュ│", "│コンピュ│",
"│ータ上で│", "│ータ上で│",
@ -66,8 +64,7 @@ fn widgets_paragraph_renders_mixed_width_graphemes() {
f.render_widget(paragraph, size); f.render_widget(paragraph, size);
}) })
.unwrap(); .unwrap();
terminal.backend().assert_buffer_lines([
let expected = Buffer::with_lines(vec![
// The internal width is 8 so only 4 slots for double-width characters. // The internal width is 8 so only 4 slots for double-width characters.
"┌────────┐", "┌────────┐",
"│aコンピ │", // Here we have 1 latin character so only 3 double-width ones can fit. "│aコンピ │", // Here we have 1 latin character so only 3 double-width ones can fit.
@ -77,7 +74,6 @@ fn widgets_paragraph_renders_mixed_width_graphemes() {
"│、 │", "│、 │",
"└────────┘", "└────────┘",
]); ]);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
@ -88,7 +84,7 @@ fn widgets_paragraph_can_wrap_with_a_trailing_nbsp() {
test_case( test_case(
paragraph, paragraph,
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│NBSP\u{00a0}", "│NBSP\u{00a0}",
"└──────────────────┘", "└──────────────────┘",
@ -104,7 +100,7 @@ fn widgets_paragraph_can_scroll_horizontally() {
test_case( test_case(
paragraph.clone().alignment(Alignment::Left).scroll((0, 7)), paragraph.clone().alignment(Alignment::Left).scroll((0, 7)),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│在可以水平滚动了!│", "│在可以水平滚动了!│",
"│ph can scroll hori│", "│ph can scroll hori│",
@ -120,7 +116,7 @@ fn widgets_paragraph_can_scroll_horizontally() {
// only support Alignment::Left // only support Alignment::Left
test_case( test_case(
paragraph.clone().alignment(Alignment::Right).scroll((0, 7)), paragraph.clone().alignment(Alignment::Right).scroll((0, 7)),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│段落现在可以水平滚│", "│段落现在可以水平滚│",
"│Paragraph can scro│", "│Paragraph can scro│",
@ -149,7 +145,7 @@ fn widgets_paragraph_can_wrap_its_content() {
test_case( test_case(
paragraph.clone().alignment(Alignment::Left), paragraph.clone().alignment(Alignment::Left),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│The library is │", "│The library is │",
"│based on the │", "│based on the │",
@ -164,7 +160,7 @@ fn widgets_paragraph_can_wrap_its_content() {
); );
test_case( test_case(
paragraph.clone().alignment(Alignment::Center), paragraph.clone().alignment(Alignment::Center),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│ The library is │", "│ The library is │",
"│ based on the │", "│ based on the │",
@ -179,7 +175,7 @@ fn widgets_paragraph_can_wrap_its_content() {
); );
test_case( test_case(
paragraph.clone().alignment(Alignment::Right), paragraph.clone().alignment(Alignment::Right),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│ The library is│", "│ The library is│",
"│ based on the│", "│ based on the│",
@ -208,7 +204,7 @@ fn widgets_paragraph_works_with_padding() {
test_case( test_case(
paragraph.clone().alignment(Alignment::Left), paragraph.clone().alignment(Alignment::Left),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌────────────────────┐", "┌────────────────────┐",
"│ │", "│ │",
"│ The library is │", "│ The library is │",
@ -224,8 +220,8 @@ fn widgets_paragraph_works_with_padding() {
]), ]),
); );
test_case( test_case(
paragraph.alignment(Alignment::Right), paragraph.clone().alignment(Alignment::Right),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌────────────────────┐", "┌────────────────────┐",
"│ │", "│ │",
"│ The library is │", "│ The library is │",
@ -250,7 +246,7 @@ fn widgets_paragraph_works_with_padding() {
test_case( test_case(
paragraph.alignment(Alignment::Right), paragraph.alignment(Alignment::Right),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌────────────────────┐", "┌────────────────────┐",
"│ │", "│ │",
"│ This is always │", "│ This is always │",
@ -284,7 +280,7 @@ fn widgets_paragraph_can_align_spans() {
test_case( test_case(
paragraph.clone().alignment(Alignment::Left), paragraph.clone().alignment(Alignment::Left),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│ This string will│", "│ This string will│",
"│ override the│", "│ override the│",
@ -299,7 +295,7 @@ fn widgets_paragraph_can_align_spans() {
); );
test_case( test_case(
paragraph.alignment(Alignment::Center), paragraph.alignment(Alignment::Center),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│ This string will│", "│ This string will│",
"│ override the│", "│ override the│",
@ -333,7 +329,7 @@ fn widgets_paragraph_can_align_spans() {
test_case( test_case(
paragraph.clone().alignment(Alignment::Right), paragraph.clone().alignment(Alignment::Right),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│This string │", "│This string │",
"│will override the │", "│will override the │",
@ -348,7 +344,7 @@ fn widgets_paragraph_can_align_spans() {
); );
test_case( test_case(
paragraph.alignment(Alignment::Left), paragraph.alignment(Alignment::Left),
Buffer::with_lines(vec![ &Buffer::with_lines([
"┌──────────────────┐", "┌──────────────────┐",
"│This string │", "│This string │",
"│will override the │", "│will override the │",

File diff suppressed because it is too large Load diff

View file

@ -26,8 +26,7 @@ fn widgets_tabs_should_not_panic_on_narrow_areas() {
); );
}) })
.unwrap(); .unwrap();
let expected = Buffer::with_lines(vec![" "]); terminal.backend().assert_buffer_lines([" "]);
terminal.backend().assert_buffer(&expected);
} }
#[test] #[test]
@ -48,7 +47,7 @@ fn widgets_tabs_should_truncate_the_last_item() {
); );
}) })
.unwrap(); .unwrap();
let mut expected = Buffer::with_lines(vec![format!(" Tab1 {} T ", symbols::line::VERTICAL)]); let mut expected = Buffer::with_lines([format!(" Tab1 {} T ", symbols::line::VERTICAL)]);
expected.set_style(Rect::new(1, 0, 4, 1), Style::new().reversed()); expected.set_style(Rect::new(1, 0, 4, 1), Style::new().reversed());
terminal.backend().assert_buffer(&expected); terminal.backend().assert_buffer(&expected);
} }