use text_document::{MoveMode, TextDocument};
fn new_doc_with_text(text: &str) -> TextDocument {
let doc = TextDocument::new();
doc.set_plain_text(text).unwrap();
doc
}
fn expected_text_before(doc: &TextDocument, position: usize, max_len: usize) -> String {
let full = doc.to_plain_text().unwrap();
let prefix: String = full.chars().take(position).collect();
let total = prefix.chars().count();
let skip = total.saturating_sub(max_len);
prefix.chars().skip(skip).collect()
}
#[test]
fn empty_at_document_start() {
let doc = new_doc_with_text("Hello world");
let cursor = doc.cursor_at(0);
assert_eq!(cursor.text_before(10).unwrap(), "");
}
#[test]
fn max_len_zero_returns_empty_even_mid_document() {
let doc = new_doc_with_text("Hello world");
let cursor = doc.cursor_at(5);
assert_eq!(cursor.text_before(0).unwrap(), "");
}
#[test]
fn exact_window_within_one_block() {
let doc = new_doc_with_text("Hello world");
let cursor = doc.cursor_at(11);
assert_eq!(cursor.text_before(5).unwrap(), "world");
}
#[test]
fn window_larger_than_available_text_clamps_to_document_start() {
let doc = new_doc_with_text("Hello");
let cursor = doc.cursor_at(5);
assert_eq!(cursor.text_before(1000).unwrap(), "Hello");
}
#[test]
fn window_exactly_at_document_start_boundary() {
let doc = new_doc_with_text("Hello world");
let cursor = doc.cursor_at(5);
assert_eq!(cursor.text_before(5).unwrap(), "Hello");
}
#[test]
fn crosses_a_single_block_boundary_with_newline_separator() {
let doc = new_doc_with_text("HelloWorld");
let cursor_split = doc.cursor_at(5);
cursor_split.insert_block().unwrap();
assert_eq!(doc.block_count(), 2);
assert_eq!(doc.to_plain_text().unwrap(), "Hello\nWorld");
let cursor = doc.cursor_at(11);
assert_eq!(cursor.text_before(11).unwrap(), "Hello\nWorld");
assert_eq!(cursor.text_before(6).unwrap(), "\nWorld");
assert_eq!(cursor.text_before(1).unwrap(), "d");
}
#[test]
fn reading_right_at_the_second_blocks_own_start_excludes_it_entirely() {
let doc = new_doc_with_text("HelloWorld");
let cursor_split = doc.cursor_at(5);
cursor_split.insert_block().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello\nWorld");
let cursor = doc.cursor_at(6);
assert_eq!(cursor.text_before(10).unwrap(), "Hello\n");
}
#[test]
fn reading_right_at_the_separator_itself_excludes_the_separator() {
let doc = new_doc_with_text("HelloWorld");
let cursor_split = doc.cursor_at(5);
cursor_split.insert_block().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello\nWorld");
let cursor = doc.cursor_at(5);
assert_eq!(cursor.text_before(10).unwrap(), "Hello");
}
#[test]
fn crosses_multiple_block_boundaries() {
let doc = new_doc_with_text("OneTwoThree");
doc.cursor_at(3).insert_block().unwrap(); doc.cursor_at(7).insert_block().unwrap(); assert_eq!(doc.block_count(), 3);
assert_eq!(doc.to_plain_text().unwrap(), "One\nTwo\nThree");
let cursor = doc.cursor_at(13);
assert_eq!(cursor.text_before(13).unwrap(), "One\nTwo\nThree");
assert_eq!(cursor.text_before(6).unwrap(), "\nThree");
assert_eq!(cursor.text_before(4).unwrap(), "hree");
}
#[test]
fn matches_full_plain_text_slice_across_every_position_and_window() {
let doc = new_doc_with_text("AliceBobCarolDaveEve");
doc.cursor_at(5).insert_block().unwrap(); doc.cursor_at(9).insert_block().unwrap(); doc.cursor_at(15).insert_block().unwrap(); doc.cursor_at(20).insert_block().unwrap(); assert_eq!(doc.block_count(), 5);
let full = doc.to_plain_text().unwrap();
let total = full.chars().count();
assert_eq!(full, "Alice\nBob\nCarol\nDave\nEve");
for position in 0..=total {
let cursor = doc.cursor_at(position);
for max_len in [0usize, 1, 2, 3, 5, 8, total, total + 5] {
let got = cursor.text_before(max_len).unwrap();
let want = expected_text_before(&doc, position, max_len);
assert_eq!(
got, want,
"position={position} max_len={max_len}: got {got:?}, want {want:?}"
);
}
}
}
#[test]
fn uses_the_primary_position_not_the_anchor() {
let doc = new_doc_with_text("Hello world");
let cursor = doc.cursor();
cursor.set_position(0, MoveMode::MoveAnchor);
cursor.set_position(5, MoveMode::KeepAnchor);
assert!(cursor.has_selection());
assert_eq!(cursor.text_before(5).unwrap(), "Hello");
}