mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add undo test
This commit is contained in:
parent
8272e2e8f6
commit
bfb80d1184
@ -93,7 +93,8 @@ class EditorController extends ChangeNotifier {
|
|||||||
toggledStyle = toggledStyle.put(attribute);
|
toggledStyle = toggledStyle.put(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
final change = document.format(index, length, attribute);
|
final change =
|
||||||
|
document.format(index, length, LinkAttribute("www.baidu.com"));
|
||||||
final adjustedSelection = selection.copyWith(
|
final adjustedSelection = selection.copyWith(
|
||||||
baseOffset: change.transformPosition(selection.baseOffset),
|
baseOffset: change.transformPosition(selection.baseOffset),
|
||||||
extentOffset: change.transformPosition(selection.extentOffset),
|
extentOffset: change.transformPosition(selection.extentOffset),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::{extensions::DeleteExt, util::is_newline},
|
client::{extensions::DeleteExt, util::is_newline},
|
||||||
core::{Attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, Interval, Operation, NEW_LINE},
|
core::{Attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PreserveLineFormatOnMerge {}
|
pub struct PreserveLineFormatOnMerge {}
|
||||||
|
@ -1,47 +1,48 @@
|
|||||||
use crate::{
|
// use crate::{
|
||||||
client::extensions::FormatExt,
|
// client::extensions::FormatExt,
|
||||||
core::{Attribute, AttributeKey, Delta, DeltaBuilder, DeltaIter, Interval},
|
// core::{Attribute, AttributeKey, Delta, DeltaBuilder, DeltaIter,
|
||||||
};
|
// Interval}, };
|
||||||
|
//
|
||||||
pub struct FormatLinkAtCaretPositionExt {}
|
// pub struct FormatLinkAtCaretPositionExt {}
|
||||||
|
//
|
||||||
impl FormatExt for FormatLinkAtCaretPositionExt {
|
// impl FormatExt for FormatLinkAtCaretPositionExt {
|
||||||
fn ext_name(&self) -> &str { std::any::type_name::<FormatLinkAtCaretPositionExt>() }
|
// fn ext_name(&self) -> &str {
|
||||||
|
// std::any::type_name::<FormatLinkAtCaretPositionExt>() }
|
||||||
fn apply(&self, delta: &Delta, interval: Interval, attribute: &Attribute) -> Option<Delta> {
|
//
|
||||||
if attribute.key != AttributeKey::Link || interval.size() != 0 {
|
// fn apply(&self, delta: &Delta, interval: Interval, attribute: &Attribute)
|
||||||
return None;
|
// -> Option<Delta> { if attribute.key != AttributeKey::Link ||
|
||||||
}
|
// interval.size() != 0 { return None;
|
||||||
|
// }
|
||||||
let mut iter = DeltaIter::from_offset(delta, interval.start);
|
//
|
||||||
let (before, after) = (iter.next_op_with_len(interval.size()), iter.next_op());
|
// let mut iter = DeltaIter::from_offset(delta, interval.start);
|
||||||
let mut start = interval.end;
|
// let (before, after) = (iter.next_op_with_len(interval.size()),
|
||||||
let mut retain = 0;
|
// iter.next_op()); let mut start = interval.end;
|
||||||
|
// let mut retain = 0;
|
||||||
if let Some(before) = before {
|
//
|
||||||
if before.contain_attribute(attribute) {
|
// if let Some(before) = before {
|
||||||
start -= before.len();
|
// if before.contain_attribute(attribute) {
|
||||||
retain += before.len();
|
// start -= before.len();
|
||||||
}
|
// retain += before.len();
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
if let Some(after) = after {
|
//
|
||||||
if after.contain_attribute(attribute) {
|
// if let Some(after) = after {
|
||||||
if retain != 0 {
|
// if after.contain_attribute(attribute) {
|
||||||
retain += after.len();
|
// if retain != 0 {
|
||||||
}
|
// retain += after.len();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
if retain == 0 {
|
//
|
||||||
return None;
|
// if retain == 0 {
|
||||||
}
|
// return None;
|
||||||
|
// }
|
||||||
Some(
|
//
|
||||||
DeltaBuilder::new()
|
// Some(
|
||||||
.retain(start)
|
// DeltaBuilder::new()
|
||||||
.retain_with_attributes(retain, (attribute.clone()).into())
|
// .retain(start)
|
||||||
.build(),
|
// .retain_with_attributes(retain, (attribute.clone()).into())
|
||||||
)
|
// .build(),
|
||||||
}
|
// )
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::{extensions::InsertExt, util::is_newline},
|
client::{extensions::InsertExt, util::is_newline},
|
||||||
core::{AttributeKey, Delta, DeltaBuilder, DeltaIter, Operation},
|
core::{AttributeKey, Delta, DeltaBuilder, DeltaIter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::core::{attributes_except_header, is_empty_line_at_index};
|
use crate::core::{attributes_except_header, is_empty_line_at_index};
|
||||||
|
@ -50,7 +50,7 @@ impl InsertExt for AutoFormatExt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::core::{AttributeBuilder, Attributes, DeltaBuilder, Operation};
|
use crate::core::{AttributeBuilder, Attributes, DeltaBuilder};
|
||||||
use bytecount::num_chars;
|
use bytecount::num_chars;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -7,7 +7,6 @@ use crate::{
|
|||||||
Delta,
|
Delta,
|
||||||
DeltaBuilder,
|
DeltaBuilder,
|
||||||
DeltaIter,
|
DeltaIter,
|
||||||
Operation,
|
|
||||||
NEW_LINE,
|
NEW_LINE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -94,7 +94,7 @@ fn construct_insert_exts() -> Vec<InsertExtension> {
|
|||||||
|
|
||||||
fn construct_format_exts() -> Vec<FormatExtension> {
|
fn construct_format_exts() -> Vec<FormatExtension> {
|
||||||
vec![
|
vec![
|
||||||
Box::new(FormatLinkAtCaretPositionExt {}),
|
// Box::new(FormatLinkAtCaretPositionExt {}),
|
||||||
Box::new(ResolveBlockFormat {}),
|
Box::new(ResolveBlockFormat {}),
|
||||||
Box::new(ResolveInlineFormat {}),
|
Box::new(ResolveInlineFormat {}),
|
||||||
]
|
]
|
||||||
|
@ -47,7 +47,7 @@ impl Attributes {
|
|||||||
None => {
|
None => {
|
||||||
self.inner
|
self.inner
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|(k, v)| v.0 = REMOVE_FLAG.into());
|
.for_each(|(_k, v)| v.0 = REMOVE_FLAG.into());
|
||||||
},
|
},
|
||||||
Some(attribute) => {
|
Some(attribute) => {
|
||||||
self.inner.iter_mut().for_each(|(k, v)| {
|
self.inner.iter_mut().for_each(|(k, v)| {
|
||||||
|
@ -175,14 +175,17 @@ pub struct CharMetric {}
|
|||||||
|
|
||||||
impl Metric for CharMetric {
|
impl Metric for CharMetric {
|
||||||
fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult {
|
fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult {
|
||||||
let _ = check_bound(cursor.consume_count, index)?;
|
if index > 0 {
|
||||||
let _ = cursor.next_with_len(Some(index));
|
let _ = check_bound(cursor.consume_count, index)?;
|
||||||
|
let _ = cursor.next_with_len(Some(index));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_bound(current: usize, target: usize) -> Result<(), OTError> {
|
fn check_bound(current: usize, target: usize) -> Result<(), OTError> {
|
||||||
|
debug_assert!(current <= target);
|
||||||
if current > target {
|
if current > target {
|
||||||
let msg = format!("{} should be greater than current: {}", target, current);
|
let msg = format!("{} should be greater than current: {}", target, current);
|
||||||
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength)
|
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength)
|
||||||
|
@ -1,61 +1,10 @@
|
|||||||
pub mod helper;
|
pub mod helper;
|
||||||
|
|
||||||
use crate::helper::{TestOp::*, *};
|
use crate::helper::{TestOp::*, *};
|
||||||
use flowy_ot::core::Interval;
|
use flowy_ot::core::{Interval, NEW_LINE, WHITESPACE};
|
||||||
|
|
||||||
use flowy_ot::core::{NEW_LINE, WHITESPACE};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_insert_text() {
|
fn attributes_bold_added() {
|
||||||
let ops = vec![
|
|
||||||
Insert(0, "123", 0),
|
|
||||||
Insert(0, "456", 3),
|
|
||||||
AssertOpsJson(0, r#"[{"insert":"123456"}]"#),
|
|
||||||
];
|
|
||||||
OpTester::new().run_script(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes_insert_text_at_head() {
|
|
||||||
let ops = vec![
|
|
||||||
Insert(0, "123", 0),
|
|
||||||
Insert(0, "456", 0),
|
|
||||||
AssertOpsJson(0, r#"[{"insert":"456123"}]"#),
|
|
||||||
];
|
|
||||||
OpTester::new().run_script(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes_insert_text_at_middle() {
|
|
||||||
let ops = vec![
|
|
||||||
Insert(0, "123", 0),
|
|
||||||
Insert(0, "456", 1),
|
|
||||||
AssertOpsJson(0, r#"[{"insert":"145623"}]"#),
|
|
||||||
];
|
|
||||||
OpTester::new().run_script(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes_insert_text_with_attr() {
|
|
||||||
let ops = vec![
|
|
||||||
Insert(0, "145", 0),
|
|
||||||
Insert(0, "23", 1),
|
|
||||||
Bold(0, Interval::new(0, 2), true),
|
|
||||||
AssertOpsJson(
|
|
||||||
0,
|
|
||||||
r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"345"}]"#,
|
|
||||||
),
|
|
||||||
Insert(0, "abc", 1),
|
|
||||||
AssertOpsJson(
|
|
||||||
0,
|
|
||||||
r#"[{"insert":"1abc2","attributes":{"bold":"true"}},{"insert":"345"}]"#,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
OpTester::new().run_script(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes_add_bold() {
|
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Bold(0, Interval::new(3, 5), true),
|
Bold(0, Interval::new(3, 5), true),
|
||||||
@ -72,7 +21,7 @@ fn attributes_add_bold() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_and_invert_all() {
|
fn attributes_bold_added_and_invert_all() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -84,7 +33,7 @@ fn attributes_add_bold_and_invert_all() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_and_invert_partial_suffix() {
|
fn attributes_bold_added_and_invert_partial_suffix() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1234", 0),
|
Insert(0, "1234", 0),
|
||||||
Bold(0, Interval::new(0, 4), true),
|
Bold(0, Interval::new(0, 4), true),
|
||||||
@ -99,7 +48,7 @@ fn attributes_add_bold_and_invert_partial_suffix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_and_invert_partial_suffix2() {
|
fn attributes_bold_added_and_invert_partial_suffix2() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1234", 0),
|
Insert(0, "1234", 0),
|
||||||
Bold(0, Interval::new(0, 4), true),
|
Bold(0, Interval::new(0, 4), true),
|
||||||
@ -116,7 +65,7 @@ fn attributes_add_bold_and_invert_partial_suffix2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_with_new_line() {
|
fn attributes_bold_added_with_new_line() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Bold(0, Interval::new(0, 6), true),
|
Bold(0, Interval::new(0, 6), true),
|
||||||
@ -144,7 +93,7 @@ fn attributes_add_bold_with_new_line() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_and_invert_partial_prefix() {
|
fn attributes_bold_added_and_invert_partial_prefix() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1234", 0),
|
Insert(0, "1234", 0),
|
||||||
Bold(0, Interval::new(0, 4), true),
|
Bold(0, Interval::new(0, 4), true),
|
||||||
@ -159,7 +108,7 @@ fn attributes_add_bold_and_invert_partial_prefix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_consecutive() {
|
fn attributes_bold_added_consecutive() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1234", 0),
|
Insert(0, "1234", 0),
|
||||||
Bold(0, Interval::new(0, 1), true),
|
Bold(0, Interval::new(0, 1), true),
|
||||||
@ -177,7 +126,7 @@ fn attributes_add_bold_consecutive() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_italic() {
|
fn attributes_bold_added_italic() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1234", 0),
|
Insert(0, "1234", 0),
|
||||||
Bold(0, Interval::new(0, 4), true),
|
Bold(0, Interval::new(0, 4), true),
|
||||||
@ -196,7 +145,7 @@ fn attributes_add_bold_italic() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_italic2() {
|
fn attributes_bold_added_italic2() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Bold(0, Interval::new(0, 6), true),
|
Bold(0, Interval::new(0, 6), true),
|
||||||
@ -224,7 +173,7 @@ fn attributes_add_bold_italic2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_italic3() {
|
fn attributes_bold_added_italic3() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456789", 0),
|
Insert(0, "123456789", 0),
|
||||||
Bold(0, Interval::new(0, 5), true),
|
Bold(0, Interval::new(0, 5), true),
|
||||||
@ -261,7 +210,7 @@ fn attributes_add_bold_italic3() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bold_italic_delete() {
|
fn attributes_bold_added_italic_delete() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456789", 0),
|
Insert(0, "123456789", 0),
|
||||||
Bold(0, Interval::new(0, 5), true),
|
Bold(0, Interval::new(0, 5), true),
|
||||||
@ -467,7 +416,7 @@ fn attributes_header_insert_newline_at_middle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_header_insert_newline_at_middle2() {
|
fn attributes_header_insert_double_newline_at_middle() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Header(0, Interval::new(0, 6), 1, true),
|
Header(0, Interval::new(0, 6), 1, true),
|
||||||
@ -523,7 +472,7 @@ fn attributes_header_insert_double_newline_at_trailing() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_link() {
|
fn attributes_link_added() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Link(0, Interval::new(0, 6), "https://appflowy.io", true),
|
Link(0, Interval::new(0, 6), "https://appflowy.io", true),
|
||||||
@ -536,6 +485,25 @@ fn attributes_add_link() {
|
|||||||
OpTester::new().run_script_with_newline(ops);
|
OpTester::new().run_script_with_newline(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes_link_format_with_bold() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123456", 0),
|
||||||
|
Link(0, Interval::new(0, 6), "https://appflowy.io", true),
|
||||||
|
Bold(0, Interval::new(0, 3), true),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[
|
||||||
|
{"insert":"123","attributes":{"bold":"true","link":"https://appflowy.io"}},
|
||||||
|
{"insert":"456","attributes":{"link":"https://appflowy.io"}},
|
||||||
|
{"insert":"\n"}]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_link_insert_char_at_head() {
|
fn attributes_link_insert_char_at_head() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
@ -605,7 +573,7 @@ fn attributes_link_insert_newline_at_middle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_auto_format_link() {
|
fn attributes_link_auto_format() {
|
||||||
let site = "https://appflowy.io";
|
let site = "https://appflowy.io";
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, site, 0),
|
Insert(0, site, 0),
|
||||||
@ -621,7 +589,7 @@ fn attributes_auto_format_link() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_auto_format_exist_link() {
|
fn attributes_link_auto_format_exist() {
|
||||||
let site = "https://appflowy.io";
|
let site = "https://appflowy.io";
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, site, 0),
|
Insert(0, site, 0),
|
||||||
@ -637,7 +605,7 @@ fn attributes_auto_format_exist_link() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_auto_format_exist_link2() {
|
fn attributes_link_auto_format_exist2() {
|
||||||
let site = "https://appflowy.io";
|
let site = "https://appflowy.io";
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, site, 0),
|
Insert(0, site, 0),
|
||||||
@ -653,7 +621,7 @@ fn attributes_auto_format_exist_link2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bullet() {
|
fn attributes_bullet_added() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "12", 0),
|
Insert(0, "12", 0),
|
||||||
Bullet(0, Interval::new(0, 1), true),
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
@ -667,7 +635,7 @@ fn attributes_add_bullet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_add_bullet2() {
|
fn attributes_bullet_added_2() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1", 0),
|
Insert(0, "1", 0),
|
||||||
Bullet(0, Interval::new(0, 1), true),
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
@ -691,7 +659,7 @@ fn attributes_add_bullet2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_un_bullet_one() {
|
fn attributes_bullet_remove_partial() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1", 0),
|
Insert(0, "1", 0),
|
||||||
Bullet(0, Interval::new(0, 1), true),
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
@ -708,7 +676,7 @@ fn attributes_un_bullet_one() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_auto_exit_block() {
|
fn attributes_bullet_auto_exit() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "1", 0),
|
Insert(0, "1", 0),
|
||||||
Bullet(0, Interval::new(0, 1), true),
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
@ -764,7 +732,7 @@ fn attributes_preserve_block_when_insert_newline_inside() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn attributes_preserve_line_format_on_merge() {
|
fn attributes_preserve_header_format_on_merge() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Header(0, Interval::new(0, 6), 1, true),
|
Header(0, Interval::new(0, 6), 1, true),
|
||||||
@ -782,3 +750,23 @@ fn attributes_preserve_line_format_on_merge() {
|
|||||||
|
|
||||||
OpTester::new().run_script_with_newline(ops);
|
OpTester::new().run_script_with_newline(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes_preserve_list_format_on_merge() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123456", 0),
|
||||||
|
Bullet(0, Interval::new(0, 6), true),
|
||||||
|
Insert(0, NEW_LINE, 3),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"123"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Delete(0, Interval::new(3, 4)),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ use flowy_ot::{client::Document, core::*};
|
|||||||
use rand::{prelude::*, Rng as WrappedRng};
|
use rand::{prelude::*, Rng as WrappedRng};
|
||||||
use std::{sync::Once, time::Duration};
|
use std::{sync::Once, time::Duration};
|
||||||
|
|
||||||
const LEVEL: &'static str = "debug";
|
const LEVEL: &'static str = "info";
|
||||||
|
|
||||||
#[derive(Clone, Debug, Display)]
|
#[derive(Clone, Debug, Display)]
|
||||||
pub enum TestOp {
|
pub enum TestOp {
|
||||||
|
@ -5,6 +5,36 @@ use bytecount::num_chars;
|
|||||||
use flowy_ot::core::*;
|
use flowy_ot::core::*;
|
||||||
use helper::*;
|
use helper::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes_insert_text() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123", 0),
|
||||||
|
Insert(0, "456", 3),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"123456"}]"#),
|
||||||
|
];
|
||||||
|
OpTester::new().run_script(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes_insert_text_at_head() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123", 0),
|
||||||
|
Insert(0, "456", 0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"456123"}]"#),
|
||||||
|
];
|
||||||
|
OpTester::new().run_script(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes_insert_text_at_middle() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123", 0),
|
||||||
|
Insert(0, "456", 1),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"145623"}]"#),
|
||||||
|
];
|
||||||
|
OpTester::new().run_script(ops);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delta_get_ops_in_interval_1() {
|
fn delta_get_ops_in_interval_1() {
|
||||||
let mut delta = Delta::default();
|
let mut delta = Delta::default();
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
pub mod helper;
|
pub mod helper;
|
||||||
|
|
||||||
use crate::helper::{TestOp::*, *};
|
use crate::helper::{TestOp::*, *};
|
||||||
use flowy_ot::{client::RECORD_THRESHOLD, core::Interval};
|
use flowy_ot::{
|
||||||
|
client::RECORD_THRESHOLD,
|
||||||
|
core::{Interval, NEW_LINE, WHITESPACE},
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_insert() {
|
fn history_insert_undo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Undo(0),
|
Undo(0),
|
||||||
@ -14,7 +17,7 @@ fn history_undo_insert() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_insert2() {
|
fn history_insert_undo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -28,7 +31,7 @@ fn history_undo_insert2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_insert() {
|
fn history_insert_redo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
|
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
|
||||||
@ -41,7 +44,7 @@ fn history_redo_insert() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_insert_with_lagging() {
|
fn history_insert_redo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -60,7 +63,7 @@ fn history_redo_insert_with_lagging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_attributes() {
|
fn history_bold_undo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -71,7 +74,7 @@ fn history_undo_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_attributes_with_lagging() {
|
fn history_bold_undo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -83,7 +86,7 @@ fn history_undo_attributes_with_lagging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_attributes() {
|
fn history_bold_redo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -99,7 +102,7 @@ fn history_redo_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_attributes_with_lagging() {
|
fn history_bold_redo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -116,7 +119,7 @@ fn history_redo_attributes_with_lagging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_delete() {
|
fn history_delete_undo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
|
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
|
||||||
@ -129,7 +132,7 @@ fn history_undo_delete() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_delete2() {
|
fn history_delete_undo_2() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -148,7 +151,7 @@ fn history_undo_delete2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_delete2_with_lagging() {
|
fn history_delete_undo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -175,7 +178,7 @@ fn history_undo_delete2_with_lagging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_delete() {
|
fn history_delete_redo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -189,7 +192,7 @@ fn history_redo_delete() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_replace() {
|
fn history_replace_undo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -208,7 +211,7 @@ fn history_undo_replace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_replace_with_lagging() {
|
fn history_replace_undo_with_lagging() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Wait(RECORD_THRESHOLD),
|
Wait(RECORD_THRESHOLD),
|
||||||
@ -232,7 +235,7 @@ fn history_undo_replace_with_lagging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_redo_replace() {
|
fn history_replace_redo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123", 0),
|
Insert(0, "123", 0),
|
||||||
Bold(0, Interval::new(0, 3), true),
|
Bold(0, Interval::new(0, 3), true),
|
||||||
@ -251,13 +254,14 @@ fn history_redo_replace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_add_header() {
|
fn history_header_added_undo() {
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, "123456", 0),
|
Insert(0, "123456", 0),
|
||||||
Header(0, Interval::new(0, 6), 1, true),
|
Header(0, Interval::new(0, 6), 1, true),
|
||||||
Insert(0, "\n", 3),
|
Insert(0, "\n", 3),
|
||||||
Insert(0, "\n", 4),
|
Insert(0, "\n", 4),
|
||||||
Undo(0),
|
Undo(0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
|
||||||
Redo(0),
|
Redo(0),
|
||||||
AssertOpsJson(
|
AssertOpsJson(
|
||||||
0,
|
0,
|
||||||
@ -269,7 +273,7 @@ fn history_undo_add_header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn history_undo_add_link() {
|
fn history_link_added_undo() {
|
||||||
let site = "https://appflowy.io";
|
let site = "https://appflowy.io";
|
||||||
let ops = vec![
|
let ops = vec![
|
||||||
Insert(0, site, 0),
|
Insert(0, site, 0),
|
||||||
@ -286,3 +290,103 @@ fn history_undo_add_link() {
|
|||||||
|
|
||||||
OpTester::new().run_script_with_newline(ops);
|
OpTester::new().run_script_with_newline(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn history_link_auto_format_undo_with_lagging() {
|
||||||
|
let site = "https://appflowy.io";
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, site, 0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
|
||||||
|
Wait(RECORD_THRESHOLD),
|
||||||
|
Insert(0, WHITESPACE, site.len()),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
|
||||||
|
),
|
||||||
|
Undo(0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn history_bullet_undo() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "1", 0),
|
||||||
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
|
Insert(0, NEW_LINE, 1),
|
||||||
|
Insert(0, "2", 2),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"2"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Undo(0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
|
||||||
|
Redo(0),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"2"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn history_bullet_undo_with_lagging() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "1", 0),
|
||||||
|
Bullet(0, Interval::new(0, 1), true),
|
||||||
|
Wait(RECORD_THRESHOLD),
|
||||||
|
Insert(0, NEW_LINE, 1),
|
||||||
|
Insert(0, "2", 2),
|
||||||
|
Wait(RECORD_THRESHOLD),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"2"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Undo(0),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Undo(0),
|
||||||
|
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
|
||||||
|
Redo(0),
|
||||||
|
Redo(0),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"2"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn history_undo_attribute_on_merge_between_line() {
|
||||||
|
let ops = vec![
|
||||||
|
Insert(0, "123456", 0),
|
||||||
|
Bullet(0, Interval::new(0, 6), true),
|
||||||
|
Wait(RECORD_THRESHOLD),
|
||||||
|
Insert(0, NEW_LINE, 3),
|
||||||
|
Wait(RECORD_THRESHOLD),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"123"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Delete(0, Interval::new(3, 4)), // delete the newline
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
Undo(0),
|
||||||
|
AssertOpsJson(
|
||||||
|
0,
|
||||||
|
r#"[{"insert":"123"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
OpTester::new().run_script_with_newline(ops);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user