use tess::line_index::LineIndex;
use tess::render::Cell;
use tess::source::{MockSource, Source};
use tess::viewport::Viewport;
fn wrapping_source() -> MockSource {
let s = MockSource::new();
for ch in ['a', 'b', 'c', 'd', 'e'] {
let mut line: String = std::iter::repeat(ch).take(15).collect();
line.push('\n');
s.append(line.as_bytes());
}
s.finish();
s
}
fn body_text(viewport: &mut Viewport, src: &dyn Source) -> Vec<String> {
let mut idx = LineIndex::new();
let frame = viewport.frame(src, &mut idx);
frame
.body
.iter()
.map(|row| {
let mut s = String::new();
for c in row {
match c {
Cell::Char { ch, .. } => s.push(*ch),
Cell::Continuation => {}
Cell::Empty => s.push(' '),
}
}
s.trim_end().to_string()
})
.collect()
}
#[test]
fn goto_bottom_shows_last_line_when_lines_wrap() {
let src = wrapping_source();
let mut idx = LineIndex::new();
let mut v = Viewport::new(10, 4, "mock".to_string());
v.goto_bottom(&src, &mut idx);
let body = body_text(&mut v, &src);
assert_eq!(body, vec!["ddddd", "eeeeeeeeee", "eeeee"]);
assert!(
body.last().unwrap().starts_with('e'),
"last body row must be the final line's tail, got {body:?}"
);
}
#[test]
fn is_at_bottom_false_when_wrapped_tail_is_offscreen() {
let src = wrapping_source();
let mut idx = LineIndex::new();
idx.notice_new_bytes(&src);
let mut v = Viewport::new(10, 4, "mock".to_string());
v.goto_line(2, &src, &mut idx);
assert!(
!v.is_at_bottom(&src, &idx),
"viewport whose tail is still off-screen must not report at-bottom"
);
}
#[test]
fn cannot_scroll_below_the_bottom_anchor() {
let src = wrapping_source();
let mut idx = LineIndex::new();
let mut v = Viewport::new(10, 4, "mock".to_string());
v.scroll_lines(100, &src, &mut idx);
let body = body_text(&mut v, &src);
assert_eq!(
body,
vec!["ddddd", "eeeeeeeeee", "eeeee"],
"scrolling past the end must clamp with the last line at the bottom row"
);
assert!(v.is_at_bottom(&src, &idx));
}