Add tests for backlog rendering
This commit is contained in:
@ -25,6 +25,7 @@ use crate::widgets::prerender::{PrerenderInner, PrerenderValue};
|
|||||||
use crate::widgets::{BottomAlignedParagraph, OverlappableWidget};
|
use crate::widgets::{BottomAlignedParagraph, OverlappableWidget};
|
||||||
|
|
||||||
use super::Component;
|
use super::Component;
|
||||||
|
use crate::buffers::BufferItem;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Backlog {
|
pub struct Backlog {
|
||||||
@ -40,7 +41,7 @@ impl Component for Backlog {
|
|||||||
kind: KeyEventKind::Press,
|
kind: KeyEventKind::Press,
|
||||||
state: _,
|
state: _,
|
||||||
} => {
|
} => {
|
||||||
self.scroll += 20; // TODO: use the component height
|
self.scroll_up(20); // TODO: use the component height
|
||||||
},
|
},
|
||||||
KeyEvent {
|
KeyEvent {
|
||||||
code: KeyCode::PageDown,
|
code: KeyCode::PageDown,
|
||||||
@ -48,7 +49,7 @@ impl Component for Backlog {
|
|||||||
kind: KeyEventKind::Press,
|
kind: KeyEventKind::Press,
|
||||||
state: _,
|
state: _,
|
||||||
} => {
|
} => {
|
||||||
self.scroll = self.scroll.saturating_sub(20); // TODO: use the component height
|
self.scroll_down(20) // TODO: use the component height
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -62,12 +63,37 @@ impl Component for Backlog {
|
|||||||
area: Rect,
|
area: Rect,
|
||||||
buffers: &crate::buffers::Buffers,
|
buffers: &crate::buffers::Buffers,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let active_buffer = buffers.active_buffer();
|
||||||
|
let items = active_buffer.content();
|
||||||
|
let unused_top_lines = self.draw_items(frame.buffer_mut(), area, items)?;
|
||||||
|
|
||||||
|
// There is empty room on screen, ask the buffer to fetch more backlog if it can
|
||||||
|
if unused_top_lines > 0 {
|
||||||
|
active_buffer.request_back_pagination(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backlog {
|
||||||
|
pub fn scroll_up(&mut self, lines: u64) {
|
||||||
|
self.scroll = self.scroll.saturating_add(lines);
|
||||||
|
}
|
||||||
|
pub fn scroll_down(&mut self, lines: u64) {
|
||||||
|
self.scroll = self.scroll.saturating_sub(20);
|
||||||
|
}
|
||||||
|
/// Returns how many lines are unused at the top of the area.
|
||||||
|
pub fn draw_items<'a>(
|
||||||
|
&mut self,
|
||||||
|
frame_buffer: &mut Buffer,
|
||||||
|
area: Rect,
|
||||||
|
mut items: impl Iterator<Item = BufferItem<'a>>,
|
||||||
|
) -> Result<u16> {
|
||||||
let block = Block::new().borders(Borders::ALL);
|
let block = Block::new().borders(Borders::ALL);
|
||||||
let mut text_area = block.inner(area);
|
let mut text_area = block.inner(area);
|
||||||
block.render(area, frame.buffer_mut());
|
block.render(area, frame_buffer);
|
||||||
|
|
||||||
let active_buffer = buffers.active_buffer();
|
|
||||||
let mut items = active_buffer.content();
|
|
||||||
let mut scroll = self.scroll;
|
let mut scroll = self.scroll;
|
||||||
|
|
||||||
// Skip widgets at the bottom (if scrolled up), and render the first visible one
|
// Skip widgets at the bottom (if scrolled up), and render the first visible one
|
||||||
@ -103,7 +129,7 @@ impl Component for Backlog {
|
|||||||
|
|
||||||
// TODO: cache this
|
// TODO: cache this
|
||||||
let widget = BottomAlignedParagraph::new(item.text).scroll(scroll);
|
let widget = BottomAlignedParagraph::new(item.text).scroll(scroll);
|
||||||
let height = widget.render_overlap(text_area, frame.buffer_mut());
|
let height = widget.render_overlap(text_area, frame_buffer);
|
||||||
text_area.height = text_area.height.saturating_sub(height);
|
text_area.height = text_area.height.saturating_sub(height);
|
||||||
|
|
||||||
scroll = scroll.saturating_sub(expected_height);
|
scroll = scroll.saturating_sub(expected_height);
|
||||||
@ -113,7 +139,7 @@ impl Component for Backlog {
|
|||||||
}
|
}
|
||||||
if text_area.height == 0 {
|
if text_area.height == 0 {
|
||||||
// No more room to display other paragraphs, stop now
|
// No more room to display other paragraphs, stop now
|
||||||
return Ok(());
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render other widgets
|
// Render other widgets
|
||||||
@ -135,7 +161,7 @@ impl Component for Backlog {
|
|||||||
width: text_area.width,
|
width: text_area.width,
|
||||||
height: buf.area.height - skip_top_lines,
|
height: buf.area.height - skip_top_lines,
|
||||||
},
|
},
|
||||||
frame.buffer_mut(),
|
frame_buffer,
|
||||||
Rect {
|
Rect {
|
||||||
y: text_area.y + top_padding,
|
y: text_area.y + top_padding,
|
||||||
height: text_area.height - top_padding,
|
height: text_area.height - top_padding,
|
||||||
@ -147,7 +173,7 @@ impl Component for Backlog {
|
|||||||
},
|
},
|
||||||
prerender => {
|
prerender => {
|
||||||
let widget = BottomAlignedParagraph::new(item.text);
|
let widget = BottomAlignedParagraph::new(item.text);
|
||||||
let height = widget.render_overlap(text_area, frame.buffer_mut());
|
let height = widget.render_overlap(text_area, frame_buffer);
|
||||||
|
|
||||||
// If the whole widget fits in the text_area, copy the drawn result to a buffer
|
// If the whole widget fits in the text_area, copy the drawn result to a buffer
|
||||||
// for caching
|
// for caching
|
||||||
@ -160,7 +186,7 @@ impl Component for Backlog {
|
|||||||
});
|
});
|
||||||
let top_padding = text_area.height.saturating_sub(buf.area.height);
|
let top_padding = text_area.height.saturating_sub(buf.area.height);
|
||||||
copy_buffer(
|
copy_buffer(
|
||||||
frame.buffer_mut(),
|
frame_buffer,
|
||||||
Rect {
|
Rect {
|
||||||
y: text_area.y + top_padding,
|
y: text_area.y + top_padding,
|
||||||
height: text_area.height - top_padding,
|
height: text_area.height - top_padding,
|
||||||
@ -188,14 +214,11 @@ impl Component for Backlog {
|
|||||||
text_area.height = text_area.height.saturating_sub(height); // Remove lines at the bottom used by this paragraph
|
text_area.height = text_area.height.saturating_sub(height); // Remove lines at the bottom used by this paragraph
|
||||||
if text_area.height == 0 {
|
if text_area.height == 0 {
|
||||||
// No more room to display other paragraphs, stop now
|
// No more room to display other paragraphs, stop now
|
||||||
return Ok(());
|
return Ok(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is empty room on screen, ask the buffer to fetch more backlog if it can
|
Ok(text_area.height)
|
||||||
active_buffer.request_back_pagination(100);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
src/lib.rs
Normal file
23
src/lib.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
pub mod action;
|
||||||
|
pub mod app;
|
||||||
|
pub mod buffers;
|
||||||
|
pub mod cli;
|
||||||
|
pub mod commands;
|
||||||
|
pub mod components;
|
||||||
|
pub mod config;
|
||||||
|
pub mod log;
|
||||||
|
pub mod mode;
|
||||||
|
pub mod plugins;
|
||||||
|
pub mod tui;
|
||||||
|
pub mod utils;
|
||||||
|
pub mod widgets;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
app::App,
|
||||||
|
log::initialize_logging,
|
||||||
|
utils::{initialize_panic_handler, version},
|
||||||
|
};
|
25
src/main.rs
25
src/main.rs
@ -1,30 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
pub mod action;
|
|
||||||
pub mod app;
|
|
||||||
pub mod buffers;
|
|
||||||
pub mod cli;
|
|
||||||
pub mod commands;
|
|
||||||
pub mod components;
|
|
||||||
pub mod config;
|
|
||||||
pub mod log;
|
|
||||||
pub mod mode;
|
|
||||||
pub mod plugins;
|
|
||||||
pub mod tui;
|
|
||||||
pub mod utils;
|
|
||||||
pub mod widgets;
|
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::Cli;
|
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
|
|
||||||
use crate::{
|
use ratatrix::{app::App, cli::Cli, log::initialize_logging, utils::initialize_panic_handler};
|
||||||
app::App,
|
|
||||||
log::initialize_logging,
|
|
||||||
utils::{initialize_panic_handler, version},
|
|
||||||
};
|
|
||||||
|
|
||||||
async fn tokio_main() -> Result<()> {
|
async fn tokio_main() -> Result<()> {
|
||||||
let mem_log = initialize_logging()?;
|
let mem_log = initialize_logging()?;
|
||||||
|
@ -36,4 +36,11 @@ impl Prerender {
|
|||||||
pub fn new() -> Prerender {
|
pub fn new() -> Prerender {
|
||||||
Prerender(Arc::new(Mutex::new(None)))
|
Prerender(Arc::new(Mutex::new(None)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this cache contains anything, returns its key
|
||||||
|
///
|
||||||
|
/// This is only meant for testing
|
||||||
|
pub fn key(&self) -> Option<u16> {
|
||||||
|
self.0.lock().unwrap().as_ref().map(|inner| inner.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
344
tests/components/backlog.rs
Normal file
344
tests/components/backlog.rs
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
/*
|
||||||
|
* 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 color_eyre::eyre::WrapErr;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use ratatui::prelude::*;
|
||||||
|
|
||||||
|
use ratatrix::buffers::BufferItem;
|
||||||
|
use ratatrix::components::Backlog;
|
||||||
|
use ratatrix::widgets::Prerender;
|
||||||
|
|
||||||
|
fn rect(x: u16, y: u16, width: u16, height: u16) -> Rect {
|
||||||
|
Rect {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_item() {
|
||||||
|
let mut bl = Backlog::default();
|
||||||
|
let prerender = Prerender::new();
|
||||||
|
let item = BufferItem {
|
||||||
|
text: Text::raw("hello"),
|
||||||
|
prerender: &prerender,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
|
||||||
|
bl.draw_items(&mut buf, rect(3, 2, 12, 4), vec![item].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender = Prerender::new();
|
||||||
|
let item = BufferItem {
|
||||||
|
text: Text::raw("hello"),
|
||||||
|
prerender: &prerender,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
|
||||||
|
let area = rect(3, 2, 12, 4);
|
||||||
|
bl.draw_items(&mut buf, area, vec![item].into_iter())
|
||||||
|
.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 {
|
||||||
|
text: Text::raw("hello"),
|
||||||
|
prerender: &prerender,
|
||||||
|
};
|
||||||
|
bl.draw_items(&mut buf, area, vec![item].into_iter())
|
||||||
|
.context("Failed to draw")
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(buf, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_item_tight() {
|
||||||
|
let mut bl = Backlog::default();
|
||||||
|
let prerender = Prerender::new();
|
||||||
|
let item = BufferItem {
|
||||||
|
text: Text::raw("hello"),
|
||||||
|
prerender: &prerender,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 13, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(3, 2, 7, 3), vec![item].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender1 = Prerender::new();
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let prerender2 = Prerender::new();
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender1 = Prerender::new();
|
||||||
|
let prerender2 = Prerender::new();
|
||||||
|
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.context("Failed to draw")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let expected = Buffer::with_lines(vec![
|
||||||
|
" ",
|
||||||
|
" ┌──────────┐ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │hi │ ",
|
||||||
|
" │world │ ",
|
||||||
|
" └──────────┘ ",
|
||||||
|
" ",
|
||||||
|
]);
|
||||||
|
assert_eq!(buf, expected);
|
||||||
|
|
||||||
|
bl.scroll_up(1);
|
||||||
|
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.context("Failed to draw")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let expected = Buffer::with_lines(vec![
|
||||||
|
" ",
|
||||||
|
" ┌──────────┐ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │hi │ ",
|
||||||
|
" └──────────┘ ",
|
||||||
|
" ",
|
||||||
|
]);
|
||||||
|
assert_eq!(buf, expected);
|
||||||
|
|
||||||
|
bl.scroll_up(1);
|
||||||
|
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender1 = Prerender::new();
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let prerender2 = Prerender::new();
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world\n!"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender1 = Prerender::new();
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let prerender2 = Prerender::new();
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 9, 6));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 7, 4), vec![item2, item1].into_iter())
|
||||||
|
.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::default();
|
||||||
|
let prerender1 = Prerender::new();
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw once
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item1].into_iter())
|
||||||
|
.context("Failed to draw")
|
||||||
|
.unwrap();
|
||||||
|
let expected = Buffer::with_lines(vec![
|
||||||
|
" ",
|
||||||
|
" ┌──────────┐ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │hi │ ",
|
||||||
|
" └──────────┘ ",
|
||||||
|
" ",
|
||||||
|
]);
|
||||||
|
assert_eq!(buf, expected);
|
||||||
|
|
||||||
|
// New item added at bottom
|
||||||
|
let item1 = BufferItem {
|
||||||
|
text: Text::raw("hi"),
|
||||||
|
prerender: &prerender1,
|
||||||
|
};
|
||||||
|
let prerender2 = Prerender::new();
|
||||||
|
let item2 = BufferItem {
|
||||||
|
text: Text::raw("world"),
|
||||||
|
prerender: &prerender2,
|
||||||
|
};
|
||||||
|
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
|
||||||
|
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
|
||||||
|
.context("Failed to draw")
|
||||||
|
.unwrap();
|
||||||
|
let expected = Buffer::with_lines(vec![
|
||||||
|
" ",
|
||||||
|
" ┌──────────┐ ",
|
||||||
|
" │ │ ",
|
||||||
|
" │hi │ ",
|
||||||
|
" │world │ ",
|
||||||
|
" └──────────┘ ",
|
||||||
|
" ",
|
||||||
|
]);
|
||||||
|
assert_eq!(buf, expected);
|
||||||
|
}
|
1
tests/components/main.rs
Normal file
1
tests/components/main.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod backlog;
|
Reference in New Issue
Block a user