use text_document::{
Alignment, BlockFormat, CharVerticalAlignment, FindOptions, ListStyle, MarkerType, MoveMode,
MoveOperation, SelectionType, TextDocument, TextFormat, UnderlineStyle,
};
fn new_doc(text: &str) -> TextDocument {
let doc = TextDocument::new();
doc.set_plain_text(text).unwrap();
doc
}
#[test]
fn undo_redo_insert_text() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_text(" world").unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello world");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello world");
}
#[test]
fn undo_redo_delete_text() {
let doc = new_doc("Hello world");
let c = doc.cursor();
c.move_position(MoveOperation::NextCharacter, MoveMode::KeepAnchor, 5);
c.remove_selected_text().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), " world");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello world");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), " world");
}
#[test]
fn undo_redo_insert_block() {
let doc = new_doc("Hello world");
let c = doc.cursor_at(5);
c.insert_block().unwrap();
assert_eq!(doc.block_count(), 2);
doc.undo().unwrap();
assert_eq!(doc.block_count(), 1);
doc.redo().unwrap();
assert_eq!(doc.block_count(), 2);
}
#[test]
fn undo_redo_insert_image() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_image("test.png", 100, 50).unwrap();
assert_eq!(doc.stats().image_count, 1);
let char_count_after = doc.character_count();
doc.undo().unwrap();
assert_eq!(doc.stats().image_count, 0);
assert_eq!(doc.character_count(), 5);
doc.redo().unwrap();
assert_eq!(doc.stats().image_count, 1);
assert_eq!(doc.character_count(), char_count_after);
}
#[test]
fn insert_image_into_empty_doc() {
let doc = TextDocument::new();
let c = doc.cursor();
c.insert_image("img.png", 200, 100).unwrap();
assert_eq!(doc.stats().image_count, 1);
}
#[test]
fn insert_image_after_image() {
let doc = TextDocument::new();
let c = doc.cursor();
c.insert_image("img1.png", 100, 100).unwrap();
c.insert_image("img2.png", 200, 200).unwrap();
assert_eq!(doc.stats().image_count, 2);
}
#[test]
fn undo_redo_insert_formatted_text() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
let fmt = TextFormat {
font_bold: Some(true),
font_italic: Some(true),
font_family: Some("Arial".into()),
font_point_size: Some(14),
..Default::default()
};
c.insert_formatted_text(" bold", &fmt).unwrap();
assert!(doc.to_plain_text().unwrap().contains("bold"));
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
assert!(doc.to_plain_text().unwrap().contains("bold"));
}
#[test]
fn undo_redo_insert_frame() {
let doc = new_doc("Hello");
let frames_before = doc.stats().frame_count;
let c = doc.cursor();
c.insert_frame().unwrap();
assert!(doc.stats().frame_count > frames_before);
doc.undo().unwrap();
assert_eq!(doc.stats().frame_count, frames_before);
doc.redo().unwrap();
assert!(doc.stats().frame_count > frames_before);
}
#[test]
fn undo_redo_insert_fragment() {
let source = new_doc("Fragment text");
let frag = text_document::DocumentFragment::from_document(&source).unwrap();
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_fragment(&frag).unwrap();
let after_insert = doc.to_plain_text().unwrap();
assert!(after_insert.contains("Fragment"));
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
let after_redo = doc.to_plain_text().unwrap();
assert!(after_redo.contains("Fragment"));
}
#[test]
fn undo_redo_insert_html() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_html("<b>World</b>").unwrap();
assert!(doc.to_plain_text().unwrap().contains("World"));
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
assert!(doc.to_plain_text().unwrap().contains("World"));
}
#[test]
fn undo_redo_insert_markdown() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_markdown(" **World**").unwrap();
assert!(doc.to_plain_text().unwrap().contains("World"));
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
assert!(doc.to_plain_text().unwrap().contains("World"));
}
#[test]
fn undo_redo_create_list() {
let doc = new_doc("Item 1\nItem 2");
let c = doc.cursor();
c.select(SelectionType::Document);
c.create_list(ListStyle::Disc).unwrap();
assert!(doc.stats().list_count >= 1);
doc.undo().unwrap();
assert_eq!(doc.stats().list_count, 0);
doc.redo().unwrap();
assert!(doc.stats().list_count >= 1);
}
#[test]
fn undo_redo_insert_list() {
let doc = new_doc("Before");
let c = doc.cursor_at(6);
c.insert_list(ListStyle::Decimal).unwrap();
let lists_after = doc.stats().list_count;
assert!(lists_after >= 1);
doc.undo().unwrap();
assert_eq!(doc.stats().list_count, 0);
doc.redo().unwrap();
assert_eq!(doc.stats().list_count, lists_after);
}
#[test]
fn undo_redo_set_text_format() {
let doc = new_doc("Hello world");
let c = doc.cursor();
c.move_position(MoveOperation::NextCharacter, MoveMode::KeepAnchor, 5);
let fmt = TextFormat {
font_bold: Some(true),
font_italic: Some(true),
font_underline: Some(true),
font_overline: Some(true),
font_strikeout: Some(true),
font_weight: Some(700),
font_point_size: Some(24),
font_family: Some("Courier".into()),
letter_spacing: Some(5),
word_spacing: Some(10),
underline_style: Some(UnderlineStyle::DashUnderline),
vertical_alignment: Some(CharVerticalAlignment::SuperScript),
..Default::default()
};
c.set_char_format(&fmt).unwrap();
let read_c = doc.cursor_at(0);
let applied = read_c.char_format().unwrap();
assert_eq!(applied.font_bold, Some(true));
doc.undo().unwrap();
let read_c = doc.cursor_at(0);
let reverted = read_c.char_format().unwrap();
assert_ne!(reverted.font_bold, Some(true));
doc.redo().unwrap();
let read_c = doc.cursor_at(0);
let reapplied = read_c.char_format().unwrap();
assert_eq!(reapplied.font_bold, Some(true));
}
#[test]
fn undo_redo_merge_text_format() {
let doc = new_doc("Hello world");
let c = doc.cursor();
c.move_position(MoveOperation::NextCharacter, MoveMode::KeepAnchor, 5);
let fmt1 = TextFormat {
font_bold: Some(true),
..Default::default()
};
c.set_char_format(&fmt1).unwrap();
let fmt2 = TextFormat {
font_italic: Some(true),
font_underline: Some(true),
font_family: Some("Monospace".into()),
..Default::default()
};
c.merge_char_format(&fmt2).unwrap();
let read_c = doc.cursor_at(0);
let merged = read_c.char_format().unwrap();
assert_eq!(merged.font_bold, Some(true));
assert_eq!(merged.font_italic, Some(true));
doc.undo().unwrap();
let read_c = doc.cursor_at(0);
let after_undo = read_c.char_format().unwrap();
assert_eq!(after_undo.font_bold, Some(true));
assert_ne!(after_undo.font_italic, Some(true));
doc.redo().unwrap();
let read_c = doc.cursor_at(0);
let after_redo = read_c.char_format().unwrap();
assert_eq!(after_redo.font_bold, Some(true));
assert_eq!(after_redo.font_italic, Some(true));
}
#[test]
fn undo_redo_set_block_format() {
let doc = new_doc("Hello");
let c = doc.cursor();
let fmt = BlockFormat {
alignment: Some(Alignment::Center),
heading_level: Some(1),
indent: Some(2),
marker: Some(MarkerType::Checked),
..Default::default()
};
c.set_block_format(&fmt).unwrap();
let read_c = doc.cursor_at(0);
let applied = read_c.block_format().unwrap();
assert_eq!(applied.alignment, Some(Alignment::Center));
assert_eq!(applied.heading_level, Some(1));
doc.undo().unwrap();
let read_c = doc.cursor_at(0);
let reverted = read_c.block_format().unwrap();
assert_ne!(reverted.alignment, Some(Alignment::Center));
doc.redo().unwrap();
let read_c = doc.cursor_at(0);
let reapplied = read_c.block_format().unwrap();
assert_eq!(reapplied.alignment, Some(Alignment::Center));
}
#[test]
fn undo_redo_set_frame_format() {
let doc = new_doc("Hello");
let c = doc.cursor();
let frame_id = {
let stats = doc.stats();
assert!(stats.frame_count >= 1);
2
};
let fmt = text_document::FrameFormat {
width: Some(500),
height: Some(300),
top_margin: Some(10),
bottom_margin: Some(10),
left_margin: Some(20),
right_margin: Some(20),
padding: Some(5),
border: Some(1),
..Default::default()
};
c.set_frame_format(frame_id, &fmt).unwrap();
doc.undo().unwrap();
assert!(doc.can_redo());
doc.redo().unwrap();
assert!(doc.can_undo());
}
#[test]
fn undo_redo_replace_text() {
let doc = new_doc("foo bar foo baz");
let opts = FindOptions::default();
let count = doc.replace_text("foo", "XXX", true, &opts).unwrap();
assert_eq!(count, 2);
assert_eq!(doc.to_plain_text().unwrap(), "XXX bar XXX baz");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "foo bar foo baz");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "XXX bar XXX baz");
}
#[test]
fn multiple_undo_redo_sequence() {
let doc = new_doc("A");
let c = doc.cursor_at(1);
c.begin_edit_block();
c.insert_text("B").unwrap();
c.end_edit_block();
assert_eq!(doc.to_plain_text().unwrap(), "AB");
let c = doc.cursor_at(2);
c.begin_edit_block();
c.insert_text("C").unwrap();
c.end_edit_block();
assert_eq!(doc.to_plain_text().unwrap(), "ABC");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "AB");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "A");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "AB");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "ABC");
}
#[test]
fn undo_redo_delete_char_with_selection() {
let doc = new_doc("Hello world");
let c = doc.cursor();
c.move_position(MoveOperation::NextCharacter, MoveMode::KeepAnchor, 5);
c.delete_char().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), " world");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello world");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), " world");
}
#[test]
fn undo_redo_delete_previous_char() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.delete_previous_char().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hell");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
doc.redo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hell");
}
#[test]
fn undo_edit_block_groups_operations() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.begin_edit_block();
c.insert_text(" ").unwrap();
c.insert_text("world").unwrap();
c.end_edit_block();
assert_eq!(doc.to_plain_text().unwrap(), "Hello world");
doc.undo().unwrap();
assert_eq!(doc.to_plain_text().unwrap(), "Hello");
}
#[test]
fn no_undo_after_set_plain_text() {
let doc = new_doc("Hello");
assert!(!doc.can_undo());
}
#[test]
fn clear_undo_redo_stack() {
let doc = new_doc("Hello");
let c = doc.cursor_at(5);
c.insert_text(" world").unwrap();
assert!(doc.can_undo());
doc.clear_undo_redo();
assert!(!doc.can_undo());
assert!(!doc.can_redo());
}