|
@@ -0,0 +1,194 @@
|
|
|
+use crate::node::script::NodeScript::*;
|
|
|
+use crate::node::script::NodeTest;
|
|
|
+use lib_ot::core::{AttributeEntry, Changeset, NodeData, OperationTransform};
|
|
|
+use lib_ot::text_delta::DeltaTextOperationBuilder;
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn changeset_delta_compose_delta_test() {
|
|
|
+ // delta 1
|
|
|
+ let delta_1 = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
|
|
+ let inverted_1 = delta_1.inverted();
|
|
|
+ let mut changeset_1 = Changeset::Delta {
|
|
|
+ delta: delta_1.clone(),
|
|
|
+ inverted: inverted_1,
|
|
|
+ };
|
|
|
+
|
|
|
+ // delta 2
|
|
|
+ let delta_2 = DeltaTextOperationBuilder::new()
|
|
|
+ .retain(delta_1.utf16_target_len)
|
|
|
+ .insert("!")
|
|
|
+ .build();
|
|
|
+ let inverted_2 = delta_2.inverted();
|
|
|
+ let changeset_2 = Changeset::Delta {
|
|
|
+ delta: delta_2,
|
|
|
+ inverted: inverted_2,
|
|
|
+ };
|
|
|
+
|
|
|
+ // compose
|
|
|
+ changeset_1.compose(&changeset_2).unwrap();
|
|
|
+
|
|
|
+ if let Changeset::Delta { delta, inverted } = changeset_1 {
|
|
|
+ assert_eq!(delta.content().unwrap(), "Hello world!");
|
|
|
+ let new_delta = delta.compose(&inverted).unwrap();
|
|
|
+ assert_eq!(new_delta.content().unwrap(), "");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn operation_compose_delta_changeset_then_invert_test() {
|
|
|
+ let delta = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
|
|
+ let inverted = delta.inverted();
|
|
|
+ let changeset = Changeset::Delta {
|
|
|
+ delta: delta.clone(),
|
|
|
+ inverted: inverted.clone(),
|
|
|
+ };
|
|
|
+
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let text_node = NodeData::new("text");
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset.clone(),
|
|
|
+ },
|
|
|
+ AssertNodeDelta {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: delta.clone(),
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset.inverted(),
|
|
|
+ },
|
|
|
+ AssertNodeDelta {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: delta.compose(&inverted).unwrap(),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn operation_compose_multiple_delta_changeset_then_invert_test() {
|
|
|
+ // delta 1
|
|
|
+ let delta_1 = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
|
|
+ let inverted_1 = delta_1.inverted();
|
|
|
+ let changeset_1 = Changeset::Delta {
|
|
|
+ delta: delta_1.clone(),
|
|
|
+ inverted: inverted_1,
|
|
|
+ };
|
|
|
+
|
|
|
+ // delta 2
|
|
|
+ let delta_2 = DeltaTextOperationBuilder::new()
|
|
|
+ .retain(delta_1.utf16_target_len)
|
|
|
+ .insert("!")
|
|
|
+ .build();
|
|
|
+ let inverted_2 = delta_2.inverted();
|
|
|
+ let changeset_2 = Changeset::Delta {
|
|
|
+ delta: delta_2.clone(),
|
|
|
+ inverted: inverted_2,
|
|
|
+ };
|
|
|
+
|
|
|
+ // delta 3
|
|
|
+ let delta_3 = DeltaTextOperationBuilder::new()
|
|
|
+ .retain(delta_2.utf16_target_len)
|
|
|
+ .insert("AppFlowy")
|
|
|
+ .build();
|
|
|
+ let inverted_3 = delta_3.inverted();
|
|
|
+ let changeset_3 = Changeset::Delta {
|
|
|
+ delta: delta_3.clone(),
|
|
|
+ inverted: inverted_3,
|
|
|
+ };
|
|
|
+
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let text_node = NodeData::new("text");
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_1.clone(),
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_2.clone(),
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_3.clone(),
|
|
|
+ },
|
|
|
+ AssertNodeDelta {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: delta_1.compose(&delta_2).unwrap().compose(&delta_3).unwrap(),
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_3.inverted(),
|
|
|
+ },
|
|
|
+ AssertNodeDeltaContent {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: r#"Hello world!"#,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_2.inverted(),
|
|
|
+ },
|
|
|
+ AssertNodeDeltaContent {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: r#"Hello world"#,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: changeset_1.inverted(),
|
|
|
+ },
|
|
|
+ AssertNodeDeltaContent {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: r#""#,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+#[should_panic]
|
|
|
+fn changeset_delta_compose_attributes_test() {
|
|
|
+ // delta 1
|
|
|
+ let delta = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
|
|
+ let inverted = delta.inverted();
|
|
|
+ let mut delta_changeset = Changeset::Delta { delta, inverted };
|
|
|
+
|
|
|
+ // attributes
|
|
|
+ let attribute_changeset = Changeset::Attributes {
|
|
|
+ new: Default::default(),
|
|
|
+ old: Default::default(),
|
|
|
+ };
|
|
|
+
|
|
|
+ // compose
|
|
|
+ delta_changeset.compose(&attribute_changeset).unwrap();
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn changeset_attributes_compose_attributes_test() {
|
|
|
+ // attributes
|
|
|
+ let mut changeset_1 = Changeset::Attributes {
|
|
|
+ new: AttributeEntry::new("bold", true).into(),
|
|
|
+ old: Default::default(),
|
|
|
+ };
|
|
|
+
|
|
|
+ let changeset_2 = Changeset::Attributes {
|
|
|
+ new: AttributeEntry::new("Italic", true).into(),
|
|
|
+ old: Default::default(),
|
|
|
+ };
|
|
|
+ // compose
|
|
|
+ changeset_1.compose(&changeset_2).unwrap();
|
|
|
+
|
|
|
+ if let Changeset::Attributes { new, old: _ } = changeset_1 {
|
|
|
+ assert_eq!(new, AttributeEntry::new("Italic", true).into());
|
|
|
+ }
|
|
|
+}
|