extern crate text_document_formatting as document_formatting;
use anyhow::Result;
use common::entities::InlineContent;
use document_formatting::document_formatting_controller;
use document_formatting::{CharVerticalAlignment, SetTextFormatDto, UnderlineStyle};
use test_harness::{
BlockRelationshipField, FrameRelationshipField, UpdateBlockDto, UpdateInlineElementDto,
block_controller, create_list, frame_controller, get_block_ids, get_sorted_cells,
inline_element_controller, insert_image, insert_table, setup_with_text,
};
#[test]
fn test_set_text_format_block_with_image() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("ABCD")?;
let block_ids = get_block_ids(&db)?;
let block_id = block_ids[0];
insert_image(&db, &hub, &mut urm, 2, "test.png", 100, 50)?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 0,
anchor: 2,
font_bold: Some(true),
..Default::default()
},
)?;
let elem_ids =
block_controller::get_relationship(&db, &block_id, &BlockRelationshipField::Elements)?;
let mut found_bold_text = false;
let mut image_is_bold = false;
for eid in &elem_ids {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
match &elem.content {
InlineContent::Text(t) if t == "AB" => {
assert_eq!(elem.fmt_font_bold, Some(true));
found_bold_text = true;
}
InlineContent::Image { .. } => {
image_is_bold = elem.fmt_font_bold == Some(true);
}
InlineContent::Text(t) if t == "CD" => {
assert_ne!(elem.fmt_font_bold, Some(true), "CD should not be bold");
}
_ => {}
}
}
assert!(found_bold_text, "Should find bold 'AB' element");
assert!(!image_is_bold, "Image should not be bold");
Ok(())
}
#[test]
fn test_set_text_format_including_image() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("ABCD")?;
insert_image(&db, &hub, &mut urm, 2, "pic.png", 64, 64)?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 0,
anchor: 5,
font_italic: Some(true),
..Default::default()
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
for eid in &elem_ids {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
assert_eq!(
elem.fmt_font_italic,
Some(true),
"All elements (text and image) should be italic"
);
}
Ok(())
}
#[test]
fn test_set_text_format_unicode_split() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("\u{00e9}\u{00e0}\u{00fc}\u{00f6}")?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 1,
anchor: 3,
font_underline: Some(true),
underline_style: Some(UnderlineStyle::DashUnderline),
..Default::default()
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
assert!(
elem_ids.len() >= 3,
"Unicode text should be split into at least 3 parts, got {}",
elem_ids.len()
);
let mut found_underlined = false;
for eid in &elem_ids {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
if elem.fmt_font_underline == Some(true)
&& let InlineContent::Text(ref t) = elem.content
{
assert_eq!(t, "\u{00e0}\u{00fc}", "Middle chars should be underlined");
assert_eq!(
elem.fmt_underline_style,
Some(common::entities::UnderlineStyle::DashUnderline)
);
found_underlined = true;
}
}
assert!(found_underlined, "Should find underlined middle part");
Ok(())
}
#[test]
fn test_set_text_format_in_list_blocks() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("Item one\nItem two\nItem three")?;
let list_result = create_list(
&db,
&hub,
&mut urm,
0,
27,
common::entities::ListStyle::Decimal,
)?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 0,
anchor: 13,
font_bold: Some(true),
font_family: Some("Serif".into()),
..Default::default()
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids_0 =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
for eid in &elem_ids_0 {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
if let InlineContent::Text(ref t) = elem.content
&& !t.is_empty()
{
assert_eq!(elem.fmt_font_bold, Some(true));
assert_eq!(elem.fmt_font_family, Some("Serif".into()));
}
}
let elem_ids_1 =
block_controller::get_relationship(&db, &block_ids[1], &BlockRelationshipField::Elements)?;
let mut found_bold_item = false;
for eid in &elem_ids_1 {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
if let InlineContent::Text(ref t) = elem.content
&& elem.fmt_font_bold == Some(true)
{
assert_eq!(t, "Item");
found_bold_item = true;
}
}
assert!(found_bold_item, "Should find bold 'Item' in second block");
let block_0 = block_controller::get(&db, &block_ids[0])?.unwrap();
assert_eq!(block_0.list, Some(list_result.list_id));
Ok(())
}
#[test]
fn test_set_text_format_in_table_cell() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("Before table")?;
let table_result = insert_table(&db, &hub, &mut urm, 12, 2, 2)?;
let cells = get_sorted_cells(&db, &table_result.table_id)?;
let cell_frame_id = cells[0].cell_frame.unwrap();
let cell_block_ids =
frame_controller::get_relationship(&db, &cell_frame_id, &FrameRelationshipField::Blocks)?;
let cell_block = block_controller::get(&db, &cell_block_ids[0])?.unwrap();
let cell_block_pos = cell_block.document_position;
let elem_ids =
block_controller::get_relationship(&db, &cell_block.id, &BlockRelationshipField::Elements)?;
let elem = inline_element_controller::get(&db, &elem_ids[0])?.unwrap();
let mut update_elem: UpdateInlineElementDto = elem.into();
update_elem.content = InlineContent::Text("Cell text".into());
inline_element_controller::update(&db, &hub, &mut urm, None, &update_elem)?;
let mut update_block: UpdateBlockDto = cell_block.into();
update_block.plain_text = "Cell text".into();
update_block.text_length = 9;
block_controller::update(&db, &hub, &mut urm, None, &update_block)?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: cell_block_pos,
anchor: cell_block_pos + 4,
font_bold: Some(true),
font_italic: Some(true),
..Default::default()
},
)?;
let cell_block_ids_after =
frame_controller::get_relationship(&db, &cell_frame_id, &FrameRelationshipField::Blocks)?;
let elem_ids_after = block_controller::get_relationship(
&db,
&cell_block_ids_after[0],
&BlockRelationshipField::Elements,
)?;
let mut found_bold_cell = false;
for eid in &elem_ids_after {
let elem = inline_element_controller::get(&db, eid)?.unwrap();
if elem.fmt_font_bold == Some(true)
&& elem.fmt_font_italic == Some(true)
&& let InlineContent::Text(ref t) = elem.content
{
assert_eq!(t, "Cell");
found_bold_cell = true;
}
}
assert!(
found_bold_cell,
"Should find bold+italic 'Cell' in table cell"
);
Ok(())
}
#[test]
fn test_set_text_format_undo_redo_with_split() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("ABCDEFGH")?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 2,
anchor: 5,
font_bold: Some(true),
..Default::default()
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids_after =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
assert!(
elem_ids_after.len() >= 3,
"Should have at least 3 elements after split"
);
urm.undo(None)?;
let elem_ids_undo =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
assert_eq!(elem_ids_undo.len(), 1, "After undo should have 1 element");
let elem = inline_element_controller::get(&db, &elem_ids_undo[0])?.unwrap();
assert_eq!(elem.fmt_font_bold, None);
urm.redo(None)?;
let elem_ids_redo =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
assert!(
elem_ids_redo.len() >= 3,
"After redo should have 3+ elements again"
);
let mut found_bold = false;
for eid in &elem_ids_redo {
let e = inline_element_controller::get(&db, eid)?.unwrap();
if e.fmt_font_bold == Some(true) {
found_bold = true;
}
}
assert!(found_bold, "After redo should have bold element");
Ok(())
}
#[test]
fn test_set_text_format_empty_range_no_op() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("Hello")?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 3,
anchor: 3,
font_bold: Some(true),
..Default::default()
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
assert_eq!(elem_ids.len(), 1);
let elem = inline_element_controller::get(&db, &elem_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_bold, None);
Ok(())
}
#[test]
fn test_set_text_format_all_fields() -> Result<()> {
let (db, hub, mut urm) = setup_with_text("Test")?;
document_formatting_controller::set_text_format(
&db,
&hub,
&mut urm,
None,
&SetTextFormatDto {
position: 0,
anchor: 4,
font_family: Some("Monospace".into()),
font_point_size: Some(24),
font_weight: Some(900),
font_bold: Some(true),
font_italic: Some(true),
font_underline: Some(true),
font_overline: Some(true),
font_strikeout: Some(true),
letter_spacing: Some(3),
word_spacing: Some(6),
underline_style: Some(UnderlineStyle::WaveUnderline),
vertical_alignment: Some(CharVerticalAlignment::SuperScript),
},
)?;
let block_ids = get_block_ids(&db)?;
let elem_ids =
block_controller::get_relationship(&db, &block_ids[0], &BlockRelationshipField::Elements)?;
let elem = inline_element_controller::get(&db, &elem_ids[0])?.unwrap();
assert_eq!(elem.fmt_font_family, Some("Monospace".into()));
assert_eq!(elem.fmt_font_point_size, Some(24));
assert_eq!(elem.fmt_font_weight, Some(900));
assert_eq!(elem.fmt_font_bold, Some(true));
assert_eq!(elem.fmt_font_italic, Some(true));
assert_eq!(elem.fmt_font_underline, Some(true));
assert_eq!(elem.fmt_font_overline, Some(true));
assert_eq!(elem.fmt_font_strikeout, Some(true));
assert_eq!(elem.fmt_letter_spacing, Some(3));
assert_eq!(elem.fmt_word_spacing, Some(6));
assert_eq!(
elem.fmt_underline_style,
Some(common::entities::UnderlineStyle::WaveUnderline)
);
assert_eq!(
elem.fmt_vertical_alignment,
Some(common::entities::CharVerticalAlignment::SuperScript)
);
Ok(())
}