extern crate text_document_formatting as document_formatting;
use anyhow::Result;
use common::database::db_context::DbContext;
use common::types::EntityId;
use test_harness::{
BlockRelationshipField, block_controller, frame_controller, get_block_ids, get_frame_id,
inline_element_controller, setup_with_text,
};
use document_formatting::document_formatting_controller;
use document_formatting::{
Alignment, CharVerticalAlignment, MarkerType, MergeTextFormatDto, SetBlockFormatDto,
SetFrameFormatDto, SetTextFormatDto, UnderlineStyle,
};
fn get_first_block_id(db_context: &DbContext) -> Result<EntityId> {
let block_ids = get_block_ids(db_context)?;
Ok(block_ids[0])
}
fn get_all_block_ids(db_context: &DbContext) -> Result<Vec<EntityId>> {
get_block_ids(db_context)
}
#[test]
fn test_set_block_format_single_block() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello World")?;
document_formatting_controller::set_block_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetBlockFormatDto {
position: 0,
anchor: 5,
alignment: Some(Alignment::Center),
heading_level: Some(2),
indent: Some(1),
marker: Some(MarkerType::Checked),
..Default::default()
},
)?;
let block_id = get_first_block_id(&db_context)?;
let block = block_controller::get(&db_context, &block_id)?.unwrap();
assert_eq!(
block.fmt_alignment,
Some(common::entities::Alignment::Center)
);
assert_eq!(block.fmt_heading_level, Some(2));
assert_eq!(block.fmt_indent, Some(1));
assert_eq!(
block.fmt_marker,
Some(common::entities::MarkerType::Checked)
);
Ok(())
}
#[test]
fn test_set_block_format_multiple_blocks() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello\nWorld")?;
document_formatting_controller::set_block_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetBlockFormatDto {
position: 0,
anchor: 11,
alignment: Some(Alignment::Right),
heading_level: Some(1),
indent: Some(3),
marker: Some(MarkerType::Unchecked),
..Default::default()
},
)?;
let block_ids = get_all_block_ids(&db_context)?;
assert!(block_ids.len() >= 2);
for block_id in &block_ids {
let block = block_controller::get(&db_context, block_id)?.unwrap();
assert_eq!(
block.fmt_alignment,
Some(common::entities::Alignment::Right)
);
assert_eq!(block.fmt_heading_level, Some(1));
assert_eq!(block.fmt_indent, Some(3));
assert_eq!(
block.fmt_marker,
Some(common::entities::MarkerType::Unchecked)
);
}
Ok(())
}
#[test]
fn test_set_block_format_undo() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello World")?;
let block_id = get_first_block_id(&db_context)?;
let block_before = block_controller::get(&db_context, &block_id)?.unwrap();
assert_eq!(block_before.fmt_alignment, None);
assert_eq!(block_before.fmt_heading_level, None);
document_formatting_controller::set_block_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetBlockFormatDto {
position: 0,
anchor: 5,
alignment: Some(Alignment::Justify),
heading_level: Some(3),
indent: Some(2),
marker: Some(MarkerType::NoMarker),
..Default::default()
},
)?;
let block_after = block_controller::get(&db_context, &block_id)?.unwrap();
assert_eq!(
block_after.fmt_alignment,
Some(common::entities::Alignment::Justify)
);
assert_eq!(block_after.fmt_heading_level, Some(3));
undo_redo_manager.undo(None)?;
let block_undone = block_controller::get(&db_context, &block_id)?.unwrap();
assert_eq!(block_undone.fmt_alignment, None);
assert_eq!(block_undone.fmt_heading_level, None);
Ok(())
}
#[test]
fn test_set_frame_format() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
let frame_id = get_frame_id(&db_context)?;
document_formatting_controller::set_frame_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetFrameFormatDto {
position: 0,
anchor: 0,
frame_id: frame_id as i64,
height: Some(100),
width: Some(200),
top_margin: Some(10),
bottom_margin: Some(20),
left_margin: Some(30),
right_margin: Some(40),
padding: Some(5),
border: Some(2),
is_blockquote: None,
},
)?;
let frame = frame_controller::get(&db_context, &frame_id)?.unwrap();
assert_eq!(frame.fmt_height, Some(100));
assert_eq!(frame.fmt_width, Some(200));
assert_eq!(frame.fmt_top_margin, Some(10));
assert_eq!(frame.fmt_bottom_margin, Some(20));
assert_eq!(frame.fmt_left_margin, Some(30));
assert_eq!(frame.fmt_right_margin, Some(40));
assert_eq!(frame.fmt_padding, Some(5));
assert_eq!(frame.fmt_border, Some(2));
Ok(())
}
#[test]
fn test_set_frame_format_undo() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
let frame_id = get_frame_id(&db_context)?;
let frame_before = frame_controller::get(&db_context, &frame_id)?.unwrap();
assert_eq!(frame_before.fmt_height, None);
document_formatting_controller::set_frame_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetFrameFormatDto {
position: 0,
anchor: 0,
frame_id: frame_id as i64,
height: Some(500),
width: Some(300),
top_margin: Some(15),
bottom_margin: Some(25),
left_margin: Some(35),
right_margin: Some(45),
padding: Some(8),
border: Some(3),
is_blockquote: None,
},
)?;
let frame_after = frame_controller::get(&db_context, &frame_id)?.unwrap();
assert_eq!(frame_after.fmt_height, Some(500));
undo_redo_manager.undo(None)?;
let frame_undone = frame_controller::get(&db_context, &frame_id)?.unwrap();
assert_eq!(frame_undone.fmt_height, None);
Ok(())
}
#[test]
fn test_set_text_format_whole_element() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 0,
anchor: 5,
font_family: Some("Arial".into()),
font_point_size: Some(14),
font_weight: Some(700),
font_bold: Some(true),
font_italic: Some(false),
font_underline: Some(true),
font_overline: Some(false),
font_strikeout: Some(false),
letter_spacing: Some(2),
word_spacing: Some(4),
underline_style: Some(UnderlineStyle::SingleUnderline),
vertical_alignment: Some(CharVerticalAlignment::Normal),
},
)?;
let block_id = get_first_block_id(&db_context)?;
let element_ids = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem = inline_element_controller::get(&db_context, &element_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_family, Some("Arial".to_string()));
assert_eq!(elem.fmt_font_point_size, Some(14));
assert_eq!(elem.fmt_font_weight, Some(700));
assert_eq!(elem.fmt_font_bold, Some(true));
assert_eq!(elem.fmt_font_underline, Some(true));
assert_eq!(elem.fmt_letter_spacing, Some(2));
assert_eq!(elem.fmt_word_spacing, Some(4));
assert_eq!(
elem.fmt_underline_style,
Some(common::entities::UnderlineStyle::SingleUnderline)
);
Ok(())
}
#[test]
fn test_set_text_format_partial() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("HelloWorld")?;
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 2,
anchor: 7,
font_family: Some("Courier".into()),
font_point_size: Some(12),
font_weight: Some(400),
font_bold: Some(true),
font_italic: Some(true),
font_underline: Some(false),
font_overline: Some(false),
font_strikeout: Some(false),
letter_spacing: Some(0),
word_spacing: Some(0),
underline_style: Some(UnderlineStyle::NoUnderline),
vertical_alignment: Some(CharVerticalAlignment::Normal),
},
)?;
let block_id = get_first_block_id(&db_context)?;
let element_ids = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
assert!(
element_ids.len() >= 3,
"Expected at least 3 elements after split, got {}",
element_ids.len()
);
let mut found_formatted = false;
for elem_id in &element_ids {
let elem = inline_element_controller::get(&db_context, elem_id)?.unwrap();
if elem.fmt_font_bold == Some(true) && elem.fmt_font_italic == Some(true) {
assert_eq!(elem.fmt_font_family, Some("Courier".to_string()));
found_formatted = true;
}
}
assert!(
found_formatted,
"Should find at least one formatted element"
);
Ok(())
}
#[test]
fn test_merge_text_format_preserves_other_fields() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 0,
anchor: 5,
font_family: Some("Times".into()),
font_point_size: Some(18),
font_weight: Some(700),
font_bold: Some(true),
font_italic: Some(false),
font_underline: Some(false),
font_overline: Some(true),
font_strikeout: Some(true),
letter_spacing: Some(5),
word_spacing: Some(10),
underline_style: Some(UnderlineStyle::WaveUnderline),
vertical_alignment: Some(CharVerticalAlignment::SuperScript),
},
)?;
document_formatting_controller::merge_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&MergeTextFormatDto {
position: 0,
anchor: 5,
font_family: None, font_bold: Some(false),
font_italic: Some(true),
font_underline: Some(true),
font_strikeout: None,
},
)?;
let block_id = get_first_block_id(&db_context)?;
let element_ids = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem = inline_element_controller::get(&db_context, &element_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_bold, Some(false));
assert_eq!(elem.fmt_font_italic, Some(true));
assert_eq!(elem.fmt_font_underline, Some(true));
assert_eq!(elem.fmt_font_family, Some("Times".to_string()));
assert_eq!(elem.fmt_font_point_size, Some(18));
assert_eq!(elem.fmt_font_weight, Some(700));
assert_eq!(elem.fmt_font_overline, Some(true));
assert_eq!(elem.fmt_font_strikeout, Some(true));
assert_eq!(elem.fmt_letter_spacing, Some(5));
assert_eq!(elem.fmt_word_spacing, Some(10));
assert_eq!(
elem.fmt_underline_style,
Some(common::entities::UnderlineStyle::WaveUnderline)
);
assert_eq!(
elem.fmt_vertical_alignment,
Some(common::entities::CharVerticalAlignment::SuperScript)
);
Ok(())
}
#[test]
fn test_merge_text_format_undo() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 0,
anchor: 5,
font_family: Some("Helvetica".into()),
font_point_size: Some(16),
font_weight: Some(400),
font_bold: Some(false),
font_italic: Some(false),
font_underline: Some(false),
font_overline: Some(false),
font_strikeout: Some(false),
letter_spacing: Some(0),
word_spacing: Some(0),
underline_style: Some(UnderlineStyle::NoUnderline),
vertical_alignment: Some(CharVerticalAlignment::Normal),
},
)?;
document_formatting_controller::merge_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&MergeTextFormatDto {
position: 0,
anchor: 5,
font_family: None,
font_bold: Some(true),
font_italic: Some(true),
font_underline: Some(false),
font_strikeout: None,
},
)?;
let block_id = get_first_block_id(&db_context)?;
let element_ids = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem = inline_element_controller::get(&db_context, &element_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_bold, Some(true));
assert_eq!(elem.fmt_font_italic, Some(true));
undo_redo_manager.undo(None)?;
let element_ids_after = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem_after = inline_element_controller::get(&db_context, &element_ids_after[0])?.unwrap();
assert_eq!(elem_after.fmt_font_bold, Some(false));
assert_eq!(elem_after.fmt_font_italic, Some(false));
assert_eq!(elem_after.fmt_font_family, Some("Helvetica".to_string()));
Ok(())
}
#[test]
fn test_set_text_format_undo() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
let block_id = get_first_block_id(&db_context)?;
let elem_ids_before = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem_before = inline_element_controller::get(&db_context, &elem_ids_before[0])?.unwrap();
assert_eq!(elem_before.fmt_font_bold, None);
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 0,
anchor: 5,
font_family: Some("Mono".into()),
font_point_size: Some(10),
font_weight: Some(400),
font_bold: Some(true),
font_italic: Some(false),
font_underline: Some(false),
font_overline: Some(false),
font_strikeout: Some(false),
letter_spacing: Some(0),
word_spacing: Some(0),
underline_style: Some(UnderlineStyle::NoUnderline),
vertical_alignment: Some(CharVerticalAlignment::Normal),
},
)?;
let elem_ids = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem = inline_element_controller::get(&db_context, &elem_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_bold, Some(true));
undo_redo_manager.undo(None)?;
let elem_ids_after = block_controller::get_relationship(
&db_context,
&block_id,
&BlockRelationshipField::Elements,
)?;
let elem_after = inline_element_controller::get(&db_context, &elem_ids_after[0])?.unwrap();
assert_eq!(elem_after.fmt_font_bold, None);
Ok(())
}
#[test]
fn test_set_text_format_cross_block() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello\nWorld")?;
document_formatting_controller::set_text_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetTextFormatDto {
position: 0,
anchor: 11,
font_family: Some("Georgia".into()),
font_point_size: Some(16),
font_weight: Some(700),
font_bold: Some(true),
font_italic: Some(true),
font_underline: Some(false),
font_overline: Some(false),
font_strikeout: Some(false),
letter_spacing: Some(0),
word_spacing: Some(0),
underline_style: Some(UnderlineStyle::NoUnderline),
vertical_alignment: Some(CharVerticalAlignment::Normal),
},
)?;
let block_ids = get_all_block_ids(&db_context)?;
for block_id in &block_ids {
let elem_ids = block_controller::get_relationship(
&db_context,
block_id,
&BlockRelationshipField::Elements,
)?;
for elem_id in &elem_ids {
let elem = inline_element_controller::get(&db_context, elem_id)?.unwrap();
if let common::entities::InlineContent::Text(ref t) = elem.content
&& !t.is_empty()
{
assert_eq!(
elem.fmt_font_bold,
Some(true),
"Element in block {:?} should be bold",
block_id
);
assert_eq!(elem.fmt_font_italic, Some(true));
}
}
}
Ok(())
}
#[test]
fn test_set_block_format_empty_range() -> Result<()> {
let (db_context, event_hub, mut undo_redo_manager) = setup_with_text("Hello")?;
document_formatting_controller::set_block_format(
&db_context,
&event_hub,
&mut undo_redo_manager,
None,
&SetBlockFormatDto {
position: 2,
anchor: 2,
alignment: Some(Alignment::Center),
heading_level: Some(1),
indent: Some(0),
marker: Some(MarkerType::NoMarker),
..Default::default()
},
)?;
let block_id = get_first_block_id(&db_context)?;
let block = block_controller::get(&db_context, &block_id)?.unwrap();
assert_eq!(
block.fmt_alignment,
Some(common::entities::Alignment::Center)
);
assert_eq!(block.fmt_heading_level, Some(1));
Ok(())
}