ratatrix/tests/components/backlog.rs

681 lines
19 KiB
Rust

/*
* Copyright (C) 2023 Valentin Lorentz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::path::PathBuf;
use std::sync::Arc;
use color_eyre::eyre::WrapErr;
use pretty_assertions::assert_eq;
use ratatui::prelude::*;
use ratatrix::buffers::{BufferItem, BufferItemContent};
use ratatrix::components::Backlog;
use ratatrix::config::Config;
use ratatrix::widgets::Prerender;
fn config() -> Arc<Config> {
std::env::set_var("RATATRIX_CONFIG", PathBuf::from(".config/"));
let c = Config::new();
std::env::remove_var("RATATRIX_CONFIG");
Arc::new(c.unwrap())
}
fn rect(x: u16, y: u16, width: u16, height: u16) -> Rect {
Rect {
x,
y,
width,
height,
}
}
macro_rules! items_iter {
[ $($item: expr),* ] => {
|| vec![
$(
{
let BufferItem { content, prerender, unique_id } = &$item;
BufferItem {
content: content.clone(),
prerender,
unique_id: *unique_id,
}
},
)*
].into_iter()
}
}
#[test]
fn test_single_item() {
let mut bl = Backlog::new(config());
let prerender = Prerender::new();
let item = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
bl.draw_items(&mut buf, rect(3, 2, 12, 4), items_iter![item])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ",
" ┌──────────┐ ",
" │ │ ",
" │hello │ ",
" └──────────┘ ",
" ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_single_item_cached() {
let mut bl = Backlog::new(config());
let prerender = Prerender::new();
let item = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
let area = rect(3, 2, 12, 4);
bl.draw_items(&mut buf, area, items_iter![item])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ",
" ┌──────────┐ ",
" │ │ ",
" │hello │ ",
" └──────────┘ ",
" ",
" ",
]);
assert_eq!(buf, expected);
assert_eq!(prerender.key(), Some(10));
let item = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
bl.draw_items(&mut buf, area, items_iter![item])
.context("Failed to draw")
.unwrap();
assert_eq!(buf, expected);
}
/// Checks that the prerender cache does not store empty columns to the right
#[test]
fn test_only_necessary_width() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let prerender2 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw(":)")),
prerender: &prerender2,
unique_id: None,
};
let mut cell = ratatui::buffer::Cell::default();
cell.set_char('.');
let mut buf = Buffer::filled(rect(0, 0, 18, 7), &cell); // poisoned buffer
let area = rect(3, 1, 12, 5);
bl.draw_items(&mut buf, area, items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
"..................",
"...┌──────────┐...",
"...│hi........│...",
"...│world.....│...",
"...│:)........│...",
"...└──────────┘...",
"..................",
]);
assert_eq!(buf, expected);
assert_eq!(prerender1.key(), Some(10));
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw(":)")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 7));
bl.draw_items(&mut buf, area, items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │hi... │ ", // dots are leftover from the poisoned buffer above
" │world │ ",
" │:) │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_single_item_tight() {
let mut bl = Backlog::new(config());
let prerender = Prerender::new();
let item = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 13, 7));
bl.draw_items(&mut buf, rect(3, 2, 7, 3), items_iter![item])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ",
" ┌─────┐ ",
" │hello│ ",
" └─────┘ ",
" ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_two_items() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │hi │ ",
" │world │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_two_items_scroll() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let prerender2 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │hi │ ",
" │world │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │ │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_two_items_multiline() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world\n!")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │hi │ ",
" │world │ ",
" │! │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_two_items_tight() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 9, 6));
bl.draw_items(&mut buf, rect(1, 1, 7, 4), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌─────┐ ",
" │hi │ ",
" │world│ ",
" └─────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_cache_moved() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
// Draw once
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
// New item added at bottom
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │hi │ ",
" │world │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_overflow_and_scroll() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let prerender2 = Prerender::new();
let prerender3 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │line3 y │ ",
" │line4 y │ ",
" │line5 z │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │line2 y │ ",
" │line3 y │ ",
" │line4 y │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │line1 x │ ",
" │line2 y │ ",
" │line3 y │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │line1 x │ ",
" │line2 y │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}
#[test]
fn test_scrolledup_new_line() {
let mut bl = Backlog::new(config());
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
// Draw once
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │hi │ ",
" │world │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
// Scroll up one line
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
// New item added at bottom, displayed paragraph should not move up
let item1 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::SimpleText(Text::raw("!")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}