use super::*;
fn at(line: u32, character: u32) -> Position {
Position { line, character }
}
fn edit(start: (u32, u32), end: (u32, u32), text: &str) -> Change {
Change { range: Some(Range { start: at(start.0, start.1), end: at(end.0, end.1) }), text: text.to_owned() }
}
#[test]
fn test20072_positions_are_utf16_code_units() {
let text = "a😀b\næ¼¢å—x\n";
assert_eq!(offset(text, at(0, 3)).unwrap(), "a😀".len(), "after the emoji is unit 3");
assert_eq!(offset(text, at(1, 2)).unwrap(), "a😀b\næ¼¢å—".len());
assert_eq!(apply(text, &[edit((0, 3), (0, 4), "B")]).unwrap(), "a😀B\næ¼¢å—x\n");
assert!(offset(text, at(0, 2)).unwrap_err().contains("inside a character"), "unit 2 splits the emoji");
for o in [0, 1, "a😀".len(), "a😀b\n漢".len(), text.len()] {
assert_eq!(offset(text, position(text, o).unwrap()).unwrap(), o, "round trip at byte {o}");
}
}
#[test]
fn test20073_every_line_ending_ends_a_line() {
let text = "one\r\ntwo\rthree\nfour";
assert_eq!(offset(text, at(1, 0)).unwrap(), 5);
assert_eq!(offset(text, at(2, 0)).unwrap(), 9);
assert_eq!(offset(text, at(3, 4)).unwrap(), text.len());
assert_eq!(offset(text, at(0, 3)).unwrap(), 3);
assert!(offset(text, at(0, 4)).is_err(), "the \\r\\n of line 0 is not part of it");
assert_eq!(apply(text, &[edit((1, 3), (2, 0), " ")]).unwrap(), "one\r\ntwo three\nfour");
}
#[test]
fn test20074_a_change_outside_the_text_is_refused() {
let text = "ab\ncd";
assert!(apply(text, &[edit((2, 0), (2, 0), "x")]).unwrap_err().contains("past the end"));
assert!(apply(text, &[edit((0, 5), (0, 5), "x")]).unwrap_err().contains("past the end of line 0"));
assert!(apply(text, &[edit((1, 1), (0, 1), "x")]).unwrap_err().contains("ends before it starts"));
}
#[test]
fn test20075_changes_apply_in_order() {
let text = "ab\ncd";
let changes = [edit((1, 1), (1, 1), "Y"), edit((0, 1), (0, 1), "X")];
assert_eq!(apply(text, &changes).unwrap(), "aXb\ncYd");
let changes = [Change { range: None, text: "new".into() }, edit((0, 3), (0, 3), "!")];
assert_eq!(apply(text, &changes).unwrap(), "new!");
}