use super::*;
#[test]
fn precomputed_file_spans_match_a_full_scan() {
let mut app = app_with(TWO_FILES);
for toggled in [false, true] {
if toggled {
app.toggle_view();
}
let len = app.active_len();
for fi in 0..app.changeset.files.len() {
app.current_file = fi;
app.recompute_file_span();
let (mut s, mut e) = (len, len);
for i in 0..len {
if app.row_file_idx(i) == Some(fi) {
if s == len {
s = i;
}
e = i + 1;
}
}
assert_eq!(
app.file_span,
(s, e),
"file {fi} span mismatch (toggled={toggled})"
);
}
}
}
#[test]
fn navigation_clamps_within_the_file() {
let mut app = app_with(DIFF);
let first = app.first_selectable().unwrap();
let last = app.last_selectable().unwrap();
app.selected = first;
app.move_by(-1, 5);
assert_eq!(app.selected, first);
app.move_by(1, 100);
assert_eq!(app.selected, last);
}
#[test]
fn ensure_visible_keeps_cursor_in_viewport() {
let mut app = app_with(DIFF);
let (start, end) = app.file_range();
app.selected = app.last_selectable().unwrap();
app.ensure_visible();
let h = app.height;
assert!(app.scroll <= app.selected, "cursor above viewport");
assert!(app.selected < app.scroll + h, "cursor below viewport");
assert!(app.scroll >= start && app.scroll < end);
}
#[test]
fn visual_selection_spans_a_multi_line_range() {
let mut app = app_with(DIFF);
goto(&mut app, Side::New, 2);
app.toggle_visual();
assert!(app.visual && app.sel_anchor.is_some());
goto(&mut app, Side::New, 5);
let (fi, side, lo, hi) = app.selection_range().unwrap();
assert_eq!((fi, side, lo, hi), (app.current_file, Side::New, 2, 5));
app.toggle_visual();
assert!(!app.visual && app.sel_anchor.is_none());
}
#[test]
fn shift_arrows_extend_a_line_selection() {
let mut app = app_with(DIFF);
goto(&mut app, Side::New, 2);
assert!(!app.visual && app.sel_anchor.is_none());
app.on_key_diff(KeyCode::Down, false, true);
app.on_key_diff(KeyCode::Down, false, true);
assert!(!app.visual && app.sel_anchor.is_some());
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 4)
);
app.on_key_diff(KeyCode::Up, false, true);
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 3)
);
}
#[test]
fn unmodified_move_collapses_a_shift_selection() {
let mut app = app_with(DIFF);
goto(&mut app, Side::New, 2);
app.on_key_diff(KeyCode::Down, false, true);
app.on_key_diff(KeyCode::Down, false, true);
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 4),
"shift extended the range"
);
app.on_key_diff(KeyCode::Down, false, false);
assert!(app.sel_anchor.is_none(), "plain move must drop the anchor");
let (_, side, lo, hi) = app.selection_range().unwrap();
assert_eq!(
(side, lo, hi),
(Side::New, 5, 5),
"range collapsed to one line"
);
app.on_key_diff(KeyCode::Down, false, true);
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 5, 6)
);
}
#[test]
fn shift_arrows_skip_comment_rows_and_keep_a_valid_line_range() {
let (mut app, _tid, _reply) = app_with_thread(3);
goto(&mut app, Side::New, 2);
for _ in 0..3 {
app.on_key_diff(KeyCode::Down, false, true);
assert!(
app.is_selectable_at(app.selected),
"cursor landed on a non-diff row"
);
assert!(
app.selection_range().is_some(),
"selection range went None mid-extend"
);
}
let (_, side, lo, hi) = app.selection_range().unwrap();
assert_eq!((side, lo), (Side::New, 2));
assert!(hi > lo, "selection should have grown past the anchor line");
}
#[test]
fn toggling_view_preserves_a_multi_line_selection() {
let mut app = app_with(DIFF);
goto(&mut app, Side::New, 2);
app.toggle_visual();
goto(&mut app, Side::New, 5);
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 5)
);
app.toggle_view(); assert!(app.visual && app.sel_anchor.is_some());
assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 5),
"selection collapsed after toggling to split"
);
app.toggle_view(); assert_eq!(
app.selection_range().unwrap(),
(app.current_file, Side::New, 2, 5),
"selection collapsed after toggling back to unified"
);
}
#[test]
fn selection_range_is_single_line_without_an_anchor() {
let mut app = app_with(DIFF);
goto(&mut app, Side::New, 3);
let (_, side, lo, hi) = app.selection_range().unwrap();
assert_eq!((side, lo, hi), (Side::New, 3, 3));
}
#[test]
fn jumping_files_moves_the_cursor_into_the_new_file() {
let mut app = app_with(TWO_FILES);
assert_eq!(app.current_file, 0);
app.jump_file(1);
assert_eq!(app.current_file, 1);
assert!(app.is_selectable_at(app.selected));
assert_eq!(app.row_file_idx(app.selected), Some(1));
app.jump_file(-1);
assert_eq!(app.current_file, 0);
assert_eq!(app.row_file_idx(app.selected), Some(0));
}