use super::*;
fn setup(ctx: TestContext) -> TestContext {
commit(&ctx.dir, "firstfile", "");
commit(&ctx.dir, "secondfile", "");
commit(&ctx.dir, "thirdfile", "");
ctx
}
#[test]
fn the_search_prompt_is_a_slash() {
let mut ctx = setup_clone!();
let mut app = ctx.init_app();
ctx.update(&mut app, keys("/"));
assert_eq!(ctx.prompt_line(), "/|");
}
#[test]
fn up_brings_back_earlier_searches() {
let mut ctx = setup(setup_clone!());
let mut app = ctx.init_app();
ctx.update(&mut app, keys("/first<enter>/second<enter>"));
drop(app);
let mut app = ctx.init_app();
ctx.update(&mut app, keys("/<up>"));
assert_eq!(ctx.prompt_line(), "/second|");
ctx.update(&mut app, keys("/<up><up>"));
assert_eq!(ctx.prompt_line(), "/first|");
}
#[test]
fn the_cursor_moves_to_a_match_while_typing() {
let mut ctx = setup(setup_clone!());
let mut app = ctx.init_app();
let start = cursor_row(&ctx);
ctx.update(&mut app, keys("/second"));
assert!(
cursor_row(&ctx).contains("add secondfile"),
"{}",
ctx.redact_buffer()
);
ctx.update(&mut app, keys("/second<esc>"));
assert_eq!(cursor_row(&ctx), start);
}
#[test]
fn enter_keeps_the_match_found_while_typing() {
let mut ctx = setup(setup_clone!());
let mut app = ctx.init_app();
ctx.update(&mut app, keys("/file<enter>"));
assert!(
cursor_row(&ctx).contains("add thirdfile"),
"{}",
ctx.redact_buffer()
);
}
fn cursor_row(ctx: &TestContext) -> String {
ctx.redact_buffer()
.lines()
.find(|row| row.starts_with('▌'))
.unwrap_or_default()
.to_string()
}
#[test]
fn search_prompt() {
snapshot!(setup(setup_clone!()), "/");
}
#[test]
fn search_forward() {
snapshot!(setup(setup_clone!()), "/second<enter>");
}
#[test]
fn search_next_and_previous() {
snapshot!(setup(setup_clone!()), "/file<enter>nnN");
}
#[test]
fn search_aborted() {
snapshot!(setup(setup_clone!()), "/second<esc>");
}
#[test]
fn search_without_match() {
snapshot!(setup(setup_clone!()), "/nonesuch<enter>");
}
#[test]
fn search_repeat_without_a_previous_search() {
snapshot!(setup(setup_clone!()), "n");
}
fn marked(ctx: TestContext, input: &str) -> Vec<String> {
let mut ctx = setup(ctx);
let mut app = ctx.init_app();
ctx.update(&mut app, keys(input));
ctx.highlighted()
}
#[test]
fn every_match_on_screen_is_marked() {
assert_eq!(
vec!["file", "file", "file", "file"],
marked(setup_clone!(), "/file<enter>")
);
}
#[test]
fn repeating_a_search_leaves_the_marks_alone() {
assert_eq!(
vec!["file", "file", "file", "file"],
marked(setup_clone!(), "/file<enter>nn")
);
}
#[test]
fn a_lowercase_query_matches_whatever_the_case() {
assert_eq!(
vec!["Author", "Author", "Author", "Author"],
marked(setup_clone!(), "/author<enter>")
);
}
#[test]
fn an_uppercase_query_matches_that_case_only() {
assert!(marked(setup_clone!(), "/Add<enter>").is_empty());
assert_eq!(
vec!["add", "add", "add", "add"],
marked(setup_clone!(), "/add<enter>")
);
}
#[test]
fn a_match_running_from_one_span_into_the_next_is_marked_whole() {
assert_eq!(
vec!["main add", "main add"],
marked(setup_clone!(), "/main add<enter>")
);
}
#[test]
fn text_either_side_of_a_layout_break_is_not_one_match() {
assert!(marked(setup_clone!(), "/thirdfileAuthor<enter>").is_empty());
}
#[test]
fn nothing_is_marked_without_a_match() {
assert!(marked(setup_clone!(), "/nonesuch<enter>").is_empty());
}
#[test]
fn aborting_the_prompt_clears_the_marks() {
assert!(marked(setup_clone!(), "/file<enter>/<esc>").is_empty());
}
#[test]
fn an_empty_query_clears_the_marks() {
assert!(marked(setup_clone!(), "/file<enter>/<enter>").is_empty());
}
#[test]
fn a_cleared_search_is_not_repeatable() {
snapshot!(setup(setup_clone!()), "/file<enter>/<esc>n");
}
#[test]
fn a_search_cleared_by_an_empty_query_is_not_repeatable() {
snapshot!(setup(setup_clone!()), "/file<enter>/<enter>n");
}
#[test]
fn only_the_items_on_screen_are_marked() {
assert_eq!(
vec!["file", "file", "file", "file"],
marked(setup_clone!(), "/file<enter>c")
);
}
#[test]
fn search_hunk_line() {
let ctx = setup_clone!();
commit(&ctx.dir, "testfile", "one\ntwo\nthree\n");
std::fs::write(ctx.dir.join("testfile"), "one\ntwo\nfour\n").unwrap();
snapshot!(ctx, "/four<enter>");
}
#[test]
fn search_context_line() {
let ctx = setup_clone!();
commit(&ctx.dir, "testfile", "one\ntwo\nthree\n");
std::fs::write(ctx.dir.join("testfile"), "one\ntwo\nfour\n").unwrap();
snapshot!(ctx, "jj<tab>/two<enter>");
}
#[test]
fn a_context_line_is_marked() {
let ctx = setup_clone!();
commit(&ctx.dir, "testfile", "one\ntwo\nthree\n");
std::fs::write(ctx.dir.join("testfile"), "one\ntwo\nfour\n").unwrap();
let mut ctx = ctx;
let mut app = ctx.init_app();
ctx.update(&mut app, keys("jj<tab>/two<enter>"));
assert_eq!(vec!["two"], ctx.highlighted());
}