test: use new util function to test ranges of html tags and their names

pull/12055/head
Nikita Revenco 2 weeks ago
parent b78a777e2b
commit 89fe2ffa3e

@ -541,147 +541,6 @@ mod test {
); );
} }
#[test]
fn test_find_next_tag() {
let doc = Rope::from("<tag>hello</tag>");
assert_eq!(
find_next_tag(doc.slice(..), 7, 1).unwrap(),
(
Range::new(12, 14),
String::from("tag"),
doc.to_string().len()
)
);
}
#[test]
fn test_find_next_tag_broken() {
let doc = Rope::from("<tag>hello</tag </Hello.World>");
assert_eq!(
find_next_tag(doc.slice(..), 7, 1).unwrap(),
(
Range::new(18, 28),
String::from("Hello.World"),
doc.to_string().len()
)
);
}
#[test]
fn test_find_prev_tag() {
let doc = Rope::from("<tag>hello</tag>");
assert_eq!(
find_prev_tag(doc.slice(..), 7, 1).unwrap(),
(Range::new(1, 3), String::from("tag"), 0)
);
}
#[test]
fn test_find_prev_tag_broken() {
let doc = Rope::from("<Hello.World div={true}> <tag hello</tag>");
assert_eq!(
find_prev_tag(doc.slice(..), 32, 1).unwrap(),
(Range::new(1, 11), String::from("Hello.World"), 0)
);
}
#[test]
fn test_find_surrounding_tag_simple() {
#[rustfmt::skip]
let (doc, selection, _expectations) =
rope_with_selections_and_expectations_tags(
"<html> simple example </html>",
" ____ ^ ____ "
);
assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 1),
Ok(vec![(
(Range::new(1, 4), Range::new(24, 27)),
String::from("html")
)])
);
}
// #[test]
// fn test_find_surrounding_tag_with_imposter() {
// #[rustfmt::skip]
// let (doc, selection, expectations) =
// rope_with_selections_and_expectations_tags(
// "<div> simple example </html> </div>",
// " ___ ^ ___ "
// );
// assert_eq!(
// get_surround_pos_tag(doc.slice(..), &selection, 1),
// Ok(expectations)
// );
// }
// #[test]
// fn test_find_surrounding_tag_with_many_tags() {
// #[rustfmt::skip]
// let (doc, selection, _expectations) =
// rope_with_selections_and_expectations_tags(
// "<span> <div> simple example </span> </html> </div>",
// " ___ ^ ____ "
// );
// assert_eq!(
// get_surround_pos_tag(doc.slice(..), &selection, 1),
// Err(Error::PairNotFound)
// );
// }
// #[test]
// fn test_find_surrounding_tag_with_many_many_tags() {
// #[rustfmt::skip]
// let (doc, selection, expectations) =
// rope_with_selections_and_expectations_tags(
// "<span> <div><html> simple example </div> </html> </span>",
// " ____ ^ ____ "
// );
// assert_eq!(
// get_surround_pos_tag(doc.slice(..), &selection, 1),
// Ok(expectations)
// );
// }
// #[test]
// fn test_find_surrounding_tag_with_nth_tag() {
// #[rustfmt::skip]
// let (doc, selection, expectations) =
// rope_with_selections_and_expectations_tags(
// "<span> <div> </div> </span>",
// " ____ ^ ____ "
// );
// assert_eq!(
// get_surround_pos_tag(doc.slice(..), &selection, 2),
// Ok(expectations)
// );
// }
// #[test]
// fn test_find_surrounding_tag_multiple_cursor() {
// #[rustfmt::skip]
// let (doc, selection, expectations) =
// rope_with_selections_and_expectations_tags(
// "<span> <div> </div> </span>\n\n <b> <a> </a> </b>",
// " ____ ^ ____ \n\n _ ^^^ _ "
// );
// assert_eq!(
// get_surround_pos_tag(doc.slice(..), &selection, 2),
// Ok(expectations)
// );
// }
#[test] #[test]
fn test_get_surround_pos_bail_different_surround_chars() { fn test_get_surround_pos_bail_different_surround_chars() {
#[rustfmt::skip] #[rustfmt::skip]
@ -791,65 +650,167 @@ mod test {
) )
} }
/// Create a Rope and a matching Selection using a specification language. #[test]
/// ^ is a single-point selection. fn test_find_surrounding_tag_simple() {
/// _ is an expected index. These are returned as a Vec<usize> for use in assertions. let (doc, selection, expectations) = rope_with_selections_and_expectations_tags(
fn rope_with_selections_and_expectations( "<html> test </html>",
text: &str, " ____ ^ ____ ",
spec: &str, vec!["html"],
) -> (Rope, Selection, Vec<usize>) { );
if text.len() != spec.len() {
panic!("specification must match text length -- are newlines aligned?");
}
let rope = Rope::from(text); assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 1),
expectations
);
}
let selections: SmallVec<[Range; 1]> = spec #[test]
.match_indices('^') fn test_find_surrounding_tag_with_imposter() {
.map(|(i, _)| Range::point(i)) let (doc, selection, expectations) = rope_with_selections_and_expectations_tags(
.collect(); "<div> test </html> </div>",
" ___ ^ ___ ",
vec!["div"],
);
let expectations: Vec<usize> = spec.match_indices('_').map(|(i, _)| i).collect(); assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 1),
expectations
);
}
(rope, Selection::new(selections, 0), expectations) #[test]
fn test_find_surrounding_tag_with_many_tags() {
let (doc, selection, _) = rope_with_selections_and_expectations_tags(
"<span> <div> simple example </span> </html> </div>",
" ^ ",
vec!["span"],
);
assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 1),
Err(Error::PairNotFound)
);
}
#[test]
fn test_find_surrounding_tag_with_many_many_tags() {
let (doc, selection, expectations) = rope_with_selections_and_expectations_tags(
"<span> <div><html> simple example </div> </html> </span>",
" ____ ^ ____ ",
vec!["span"],
);
assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 1),
expectations
);
}
#[test]
fn test_find_surrounding_tag_with_nth_tag() {
let (doc, selection, expectations) = rope_with_selections_and_expectations_tags(
"<span> <div> test </div> </span>",
" ____ ^ ____ ",
vec!["span"],
);
assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 2),
expectations
);
}
#[test]
fn test_find_surrounding_tag_multiple_cursor() {
let (doc, selection, expectations) = rope_with_selections_and_expectations_tags(
"<span> <div> </div> </span>\n\n <b> <a> </a> </b>",
" ____ ^ ____ \n\n _ ^ _ ",
vec!["span", "b"],
);
assert_eq!(
get_surround_pos_tag(doc.slice(..), &selection, 2),
expectations
);
} }
/// Create a Rope and a matching Selection using a specification language.
/// ^ is a cursor position.
/// Continuous _ denote start and end of ranges. These are returned as (Range, Range)
/// for use within assertions.
fn rope_with_selections_and_expectations_tags( fn rope_with_selections_and_expectations_tags(
text: &str, text: &str,
spec: &str, spec: &str,
) -> (Rope, Selection, Vec<(usize, usize)>) { tag_names: Vec<&str>,
) -> (Rope, Selection, Result<Vec<((Range, Range), String)>>) {
if text.len() != spec.len() { if text.len() != spec.len() {
panic!("specification must match text length -- are newlines aligned?"); panic!("specification must match text length -- are newlines aligned?");
} }
let rope = Rope::from(text);
let selections: SmallVec<[Range; 1]> = spec let selections: SmallVec<[Range; 1]> = spec
.match_indices('^') .match_indices('^')
.map(|(i, _)| Range::point(i)) .map(|(i, _)| Range::point(i))
.collect(); .collect();
let expectations: Vec<(usize, usize)> = spec let mut tag_names = tag_names.into_iter();
let mut raw_ranges = spec
.char_indices() .char_indices()
.chain(std::iter::once((spec.len(), ' '))) // Add sentinel to capture trailing groups .chain(std::iter::once((spec.len(), ' ')))
.fold(Vec::new(), |mut groups, (i, c)| { .fold(Vec::new(), |mut groups, (i, c)| {
match (groups.last_mut(), c) { match (groups.last_mut(), c) {
// Current character is an underscore, and the previous index is one lower than the current index, so extend the current group.
(Some((_start, end)), '_') if *end + 1 == i => { (Some((_start, end)), '_') if *end + 1 == i => {
// Extend current group
*end = i; *end = i;
} }
// There is a gap of more than 1 between the current underscore's index and the previous underscore's index
(Some((_start, end)), '_') if *end < i => { (Some((_start, end)), '_') if *end < i => {
// Start a new group after a gap
groups.push((i, i)); groups.push((i, i));
} }
// There hasn't been a group yet, so we are going to start it.
(None, '_') => { (None, '_') => {
// Start the first group
groups.push((i, i)); groups.push((i, i));
} }
_non_underscore => {} _ => {} // Ignore non-underscore characters
} }
groups groups
}); })
.into_iter();
let range_and_tags = std::iter::from_fn(|| Some((raw_ranges.next()?, raw_ranges.next()?)))
.map(|((anchor1, head1), (anchor2, head2))| {
let range1 = Range::new(anchor1, head1);
let range2 = Range::new(anchor2, head2);
let next_tag_name = tag_names.next().unwrap();
((range1, range2), String::from(next_tag_name))
})
.collect();
(
Rope::from(text),
Selection::new(selections, 0),
Ok(range_and_tags),
)
}
/// Create a Rope and a matching Selection using a specification language.
/// ^ is a single-point selection.
/// _ is an expected index. These are returned as a Vec<usize> for use in assertions.
fn rope_with_selections_and_expectations(
text: &str,
spec: &str,
) -> (Rope, Selection, Vec<usize>) {
if text.len() != spec.len() {
panic!("specification must match text length -- are newlines aligned?");
}
let rope = Rope::from(text);
let selections: SmallVec<[Range; 1]> = spec
.match_indices('^')
.map(|(i, _)| Range::point(i))
.collect();
let expectations: Vec<usize> = spec.match_indices('_').map(|(i, _)| i).collect();
(rope, Selection::new(selections, 0), expectations) (rope, Selection::new(selections, 0), expectations)
} }

Loading…
Cancel
Save