use super::*;
#[test]
fn test_delete_bindings_not_empty() {
let bindings = delete_bindings();
assert!(!bindings.is_empty());
}
#[test]
fn test_yank_bindings_not_empty() {
let bindings = yank_bindings();
assert!(!bindings.is_empty());
}
#[test]
fn test_change_bindings_not_empty() {
let bindings = change_bindings();
assert!(!bindings.is_empty());
}
#[test]
fn test_all_operator_bindings_count() {
let all = all_operator_bindings();
let delete = delete_bindings();
let yank = yank_bindings();
let change = change_bindings();
let lowercase = lowercase_bindings();
let uppercase = uppercase_bindings();
let toggle_case = toggle_case_bindings();
assert_eq!(
all.len(),
delete.len()
+ yank.len()
+ change.len()
+ lowercase.len()
+ uppercase.len()
+ toggle_case.len()
);
}
#[test]
fn test_delete_mode_specific() {
let bindings = delete_bindings();
for b in &bindings {
assert!(
b.modes.contains(&DELETE_MODE),
"binding {} should be for vim:delete mode",
b.keys
);
}
}
#[test]
fn test_yank_mode_specific() {
let bindings = yank_bindings();
for b in &bindings {
assert!(b.modes.contains(&YANK_MODE), "binding {} should be for vim:yank mode", b.keys);
}
}
#[test]
fn test_change_mode_specific() {
let bindings = change_bindings();
for b in &bindings {
assert!(
b.modes.contains(&CHANGE_MODE),
"binding {} should be for vim:change mode",
b.keys
);
}
}
#[test]
fn test_line_operator_keys() {
let delete = delete_bindings();
assert!(delete.iter().any(|b| b.keys == "d"), "delete should have 'd' for dd");
let yank = yank_bindings();
assert!(yank.iter().any(|b| b.keys == "y"), "yank should have 'y' for yy");
let change = change_bindings();
assert!(change.iter().any(|b| b.keys == "c"), "change should have 'c' for cc");
}
#[test]
fn test_escape_bindings_in_all_modes() {
let delete = delete_bindings();
assert!(delete.iter().any(|b| b.keys == "<Esc>"), "delete mode should have <Esc>");
let yank = yank_bindings();
assert!(yank.iter().any(|b| b.keys == "<Esc>"), "yank mode should have <Esc>");
let change = change_bindings();
assert!(change.iter().any(|b| b.keys == "<Esc>"), "change mode should have <Esc>");
}
#[test]
fn test_ctrl_c_bindings_in_all_modes() {
let delete = delete_bindings();
assert!(delete.iter().any(|b| b.keys == "<C-c>"), "delete mode should have <C-c>");
let yank = yank_bindings();
assert!(yank.iter().any(|b| b.keys == "<C-c>"), "yank mode should have <C-c>");
let change = change_bindings();
assert!(change.iter().any(|b| b.keys == "<C-c>"), "change mode should have <C-c>");
}
#[test]
fn test_motion_bindings_present_in_delete() {
let delete = delete_bindings();
let keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"h"), "delete mode missing 'h' motion");
assert!(keys.contains(&"j"), "delete mode missing 'j' motion");
assert!(keys.contains(&"k"), "delete mode missing 'k' motion");
assert!(keys.contains(&"l"), "delete mode missing 'l' motion");
assert!(keys.contains(&"w"), "delete mode missing 'w' motion");
assert!(keys.contains(&"b"), "delete mode missing 'b' motion");
assert!(keys.contains(&"e"), "delete mode missing 'e' motion");
assert!(keys.contains(&"0"), "delete mode missing '0' motion");
assert!(keys.contains(&"$"), "delete mode missing '$' motion");
assert!(keys.contains(&"gg"), "delete mode missing 'gg' motion");
assert!(keys.contains(&"G"), "delete mode missing 'G' motion");
}
#[test]
fn test_textobject_bindings_present_in_delete() {
let delete = delete_bindings();
let keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"iw"), "delete mode missing 'iw' textobj");
assert!(keys.contains(&"aw"), "delete mode missing 'aw' textobj");
assert!(keys.contains(&"i\""), "delete mode missing 'i\"' textobj");
assert!(keys.contains(&"a\""), "delete mode missing 'a\"' textobj");
assert!(keys.contains(&"i("), "delete mode missing 'i(' textobj");
assert!(keys.contains(&"a("), "delete mode missing 'a(' textobj");
}
#[test]
fn test_motion_bindings_present_in_yank() {
let yank = yank_bindings();
let keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"w"), "yank mode missing 'w' motion");
assert!(keys.contains(&"b"), "yank mode missing 'b' motion");
assert!(keys.contains(&"$"), "yank mode missing '$' motion");
assert!(keys.contains(&"gg"), "yank mode missing 'gg' motion");
assert!(keys.contains(&"G"), "yank mode missing 'G' motion");
}
#[test]
fn test_motion_bindings_present_in_change() {
let change = change_bindings();
let keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"w"), "change mode missing 'w' motion");
assert!(keys.contains(&"b"), "change mode missing 'b' motion");
assert!(keys.contains(&"$"), "change mode missing '$' motion");
assert!(keys.contains(&"gg"), "change mode missing 'gg' motion");
assert!(keys.contains(&"G"), "change mode missing 'G' motion");
}
#[test]
fn test_textobject_bindings_consistent_across_modes() {
let delete_count = delete_bindings()
.iter()
.filter(|b| b.category == Some("textobj"))
.count();
let yank_count = yank_bindings()
.iter()
.filter(|b| b.category == Some("textobj"))
.count();
let change_count = change_bindings()
.iter()
.filter(|b| b.category == Some("textobj"))
.count();
assert_eq!(
delete_count, yank_count,
"delete and yank should have same number of textobj bindings"
);
assert_eq!(
yank_count, change_count,
"yank and change should have same number of textobj bindings"
);
}
#[test]
fn test_all_bindings_have_description() {
for binding in all_operator_bindings() {
assert!(
!binding.description.is_empty(),
"Binding '{}' should have a description",
binding.keys
);
}
}
#[test]
fn test_all_bindings_have_category() {
for binding in all_operator_bindings() {
assert!(binding.category.is_some(), "Binding '{}' should have a category", binding.keys);
}
}
#[test]
fn test_big_word_motions_in_operator_modes() {
let delete = delete_bindings();
let keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"W"), "delete mode missing 'W' motion");
assert!(keys.contains(&"B"), "delete mode missing 'B' motion");
assert!(keys.contains(&"E"), "delete mode missing 'E' motion");
assert!(keys.contains(&"ge"), "delete mode missing 'ge' motion");
assert!(keys.contains(&"gE"), "delete mode missing 'gE' motion");
}
#[test]
fn test_first_non_blank_in_operator_modes() {
let delete = delete_bindings();
assert!(delete.iter().any(|b| b.keys == "^"), "delete mode missing '^' motion");
let yank = yank_bindings();
assert!(yank.iter().any(|b| b.keys == "^"), "yank mode missing '^' motion");
let change = change_bindings();
assert!(change.iter().any(|b| b.keys == "^"), "change mode missing '^' motion");
}
#[test]
fn test_motion_bindings_consistent_across_modes() {
let delete_count = delete_bindings()
.iter()
.filter(|b| b.category == Some("motion"))
.count();
let yank_count = yank_bindings()
.iter()
.filter(|b| b.category == Some("motion"))
.count();
let change_count = change_bindings()
.iter()
.filter(|b| b.category == Some("motion"))
.count();
assert_eq!(
delete_count, yank_count,
"delete and yank should have same number of motion bindings"
);
assert_eq!(
yank_count, change_count,
"yank and change should have same number of motion bindings"
);
}
#[test]
fn test_textobject_bindings_in_yank() {
let yank = yank_bindings();
let keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"iw"), "yank mode missing 'iw' textobj");
assert!(keys.contains(&"aw"), "yank mode missing 'aw' textobj");
assert!(keys.contains(&"i\""), "yank mode missing 'i\"' textobj");
assert!(keys.contains(&"a\""), "yank mode missing 'a\"' textobj");
assert!(keys.contains(&"i("), "yank mode missing 'i(' textobj");
assert!(keys.contains(&"a("), "yank mode missing 'a(' textobj");
}
#[test]
fn test_textobject_bindings_in_change() {
let change = change_bindings();
let keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"iw"), "change mode missing 'iw' textobj");
assert!(keys.contains(&"aw"), "change mode missing 'aw' textobj");
assert!(keys.contains(&"i\""), "change mode missing 'i\"' textobj");
assert!(keys.contains(&"a\""), "change mode missing 'a\"' textobj");
assert!(keys.contains(&"i("), "change mode missing 'i(' textobj");
assert!(keys.contains(&"a("), "change mode missing 'a(' textobj");
}
#[test]
fn test_backtick_textobjects_in_all_modes() {
let delete = delete_bindings();
let delete_keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(delete_keys.contains(&"i`"), "delete mode missing 'i`' textobj");
assert!(delete_keys.contains(&"a`"), "delete mode missing 'a`' textobj");
let yank = yank_bindings();
let yank_keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(yank_keys.contains(&"i`"), "yank mode missing 'i`' textobj");
assert!(yank_keys.contains(&"a`"), "yank mode missing 'a`' textobj");
let change = change_bindings();
let change_keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(change_keys.contains(&"i`"), "change mode missing 'i`' textobj");
assert!(change_keys.contains(&"a`"), "change mode missing 'a`' textobj");
}
#[test]
fn test_tag_textobjects_in_all_modes() {
let delete = delete_bindings();
let delete_keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(delete_keys.contains(&"it"), "delete mode missing 'it' textobj");
assert!(delete_keys.contains(&"at"), "delete mode missing 'at' textobj");
let yank = yank_bindings();
let yank_keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(yank_keys.contains(&"it"), "yank mode missing 'it' textobj");
assert!(yank_keys.contains(&"at"), "yank mode missing 'at' textobj");
let change = change_bindings();
let change_keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(change_keys.contains(&"it"), "change mode missing 'it' textobj");
assert!(change_keys.contains(&"at"), "change mode missing 'at' textobj");
}
#[test]
fn test_sentence_textobjects_in_all_modes() {
let delete = delete_bindings();
let delete_keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(delete_keys.contains(&"is"), "delete mode missing 'is' textobj");
assert!(delete_keys.contains(&"as"), "delete mode missing 'as' textobj");
let yank = yank_bindings();
let yank_keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(yank_keys.contains(&"is"), "yank mode missing 'is' textobj");
assert!(yank_keys.contains(&"as"), "yank mode missing 'as' textobj");
let change = change_bindings();
let change_keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(change_keys.contains(&"is"), "change mode missing 'is' textobj");
assert!(change_keys.contains(&"as"), "change mode missing 'as' textobj");
}
#[test]
fn test_paragraph_textobjects_in_all_modes() {
let delete = delete_bindings();
let delete_keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(delete_keys.contains(&"ip"), "delete mode missing 'ip' textobj");
assert!(delete_keys.contains(&"ap"), "delete mode missing 'ap' textobj");
let yank = yank_bindings();
let yank_keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(yank_keys.contains(&"ip"), "yank mode missing 'ip' textobj");
assert!(yank_keys.contains(&"ap"), "yank mode missing 'ap' textobj");
let change = change_bindings();
let change_keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(change_keys.contains(&"ip"), "change mode missing 'ip' textobj");
assert!(change_keys.contains(&"ap"), "change mode missing 'ap' textobj");
}
#[test]
fn test_big_word_motions_in_yank() {
let yank = yank_bindings();
let keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"W"), "yank mode missing 'W' motion");
assert!(keys.contains(&"B"), "yank mode missing 'B' motion");
assert!(keys.contains(&"E"), "yank mode missing 'E' motion");
assert!(keys.contains(&"ge"), "yank mode missing 'ge' motion");
assert!(keys.contains(&"gE"), "yank mode missing 'gE' motion");
}
#[test]
fn test_big_word_motions_in_change() {
let change = change_bindings();
let keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"W"), "change mode missing 'W' motion");
assert!(keys.contains(&"B"), "change mode missing 'B' motion");
assert!(keys.contains(&"E"), "change mode missing 'E' motion");
assert!(keys.contains(&"ge"), "change mode missing 'ge' motion");
assert!(keys.contains(&"gE"), "change mode missing 'gE' motion");
}
#[test]
fn test_all_operator_bindings_not_empty_description() {
for binding in all_operator_bindings() {
assert!(
!binding.description.is_empty(),
"Binding '{}' should have a non-empty description",
binding.keys
);
}
}
#[test]
fn test_angle_bracket_textobjects_in_all_modes() {
let delete = delete_bindings();
let delete_keys: Vec<_> = delete.iter().map(|b| b.keys).collect();
assert!(delete_keys.contains(&"i<lt>"), "delete mode missing 'i<lt>' textobj");
assert!(delete_keys.contains(&"i<gt>"), "delete mode missing 'i<gt>' textobj");
assert!(delete_keys.contains(&"a<lt>"), "delete mode missing 'a<lt>' textobj");
assert!(delete_keys.contains(&"a<gt>"), "delete mode missing 'a<gt>' textobj");
let yank = yank_bindings();
let yank_keys: Vec<_> = yank.iter().map(|b| b.keys).collect();
assert!(yank_keys.contains(&"i<lt>"), "yank mode missing 'i<lt>' textobj");
assert!(yank_keys.contains(&"a<gt>"), "yank mode missing 'a<gt>' textobj");
let change = change_bindings();
let change_keys: Vec<_> = change.iter().map(|b| b.keys).collect();
assert!(change_keys.contains(&"i<lt>"), "change mode missing 'i<lt>' textobj");
assert!(change_keys.contains(&"a<gt>"), "change mode missing 'a<gt>' textobj");
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_brace_textobjects_in_all_modes() {
for mode_name in ["delete", "yank", "change"] {
let bindings = match mode_name {
"delete" => delete_bindings(),
"yank" => yank_bindings(),
"change" => change_bindings(),
_ => unreachable!(),
};
let keys: Vec<_> = bindings.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"i{"), "{mode_name} mode missing 'i{{' textobj");
assert!(keys.contains(&"i}"), "{mode_name} mode missing 'i}}' textobj");
assert!(keys.contains(&"iB"), "{mode_name} mode missing 'iB' textobj");
assert!(keys.contains(&"a{"), "{mode_name} mode missing 'a{{' textobj");
assert!(keys.contains(&"a}"), "{mode_name} mode missing 'a}}' textobj");
assert!(keys.contains(&"aB"), "{mode_name} mode missing 'aB' textobj");
}
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_bracket_textobjects_in_all_modes() {
for mode_name in ["delete", "yank", "change"] {
let bindings = match mode_name {
"delete" => delete_bindings(),
"yank" => yank_bindings(),
"change" => change_bindings(),
_ => unreachable!(),
};
let keys: Vec<_> = bindings.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"i["), "{mode_name} mode missing 'i[' textobj");
assert!(keys.contains(&"i]"), "{mode_name} mode missing 'i]' textobj");
assert!(keys.contains(&"a["), "{mode_name} mode missing 'a[' textobj");
assert!(keys.contains(&"a]"), "{mode_name} mode missing 'a]' textobj");
}
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_paren_textobjects_with_aliases_in_all_modes() {
for mode_name in ["delete", "yank", "change"] {
let bindings = match mode_name {
"delete" => delete_bindings(),
"yank" => yank_bindings(),
"change" => change_bindings(),
_ => unreachable!(),
};
let keys: Vec<_> = bindings.iter().map(|b| b.keys).collect();
assert!(keys.contains(&"i("), "{mode_name} mode missing 'i(' textobj");
assert!(keys.contains(&"i)"), "{mode_name} mode missing 'i)' textobj");
assert!(keys.contains(&"ib"), "{mode_name} mode missing 'ib' textobj");
assert!(keys.contains(&"a("), "{mode_name} mode missing 'a(' textobj");
assert!(keys.contains(&"a)"), "{mode_name} mode missing 'a)' textobj");
assert!(keys.contains(&"ab"), "{mode_name} mode missing 'ab' textobj");
}
}
#[test]
fn test_find_char_keys_in_all_operator_modes() {
let modes: Vec<(&str, Vec<KeybindingRegistration>)> = vec![
("delete", delete_bindings()),
("yank", yank_bindings()),
("change", change_bindings()),
];
for (mode_name, bindings) in &modes {
let keys: Vec<_> = bindings.iter().map(|kb| kb.keys).collect();
assert!(keys.contains(&"f"), "{mode_name} mode missing 'f' binding");
assert!(keys.contains(&"F"), "{mode_name} mode missing 'F' binding");
assert!(keys.contains(&"t"), "{mode_name} mode missing 't' binding");
assert!(keys.contains(&"T"), "{mode_name} mode missing 'T' binding");
}
}