|
@@ -1,93 +1,216 @@
|
|
|
use crate::node::script::NodeScript::*;
|
|
|
use crate::node::script::NodeTest;
|
|
|
-use lib_ot::core::NodeBody;
|
|
|
-use lib_ot::core::NodeBodyChangeset;
|
|
|
+use lib_ot::core::Body;
|
|
|
+use lib_ot::core::Changeset;
|
|
|
use lib_ot::core::OperationTransform;
|
|
|
use lib_ot::core::{NodeData, NodeDataBuilder, Path};
|
|
|
-use lib_ot::text_delta::TextOperationBuilder;
|
|
|
+use lib_ot::text_delta::{TextOperationBuilder, TextOperations};
|
|
|
|
|
|
#[test]
|
|
|
fn node_insert_test() {
|
|
|
let mut test = NodeTest::new();
|
|
|
- let inserted_node = NodeData::new("text");
|
|
|
- let path: Path = 0.into();
|
|
|
+ let node_data = NodeData::new("text");
|
|
|
+ let path: Path = vec![0].into();
|
|
|
let scripts = vec![
|
|
|
InsertNode {
|
|
|
path: path.clone(),
|
|
|
- node_data: inserted_node.clone(),
|
|
|
+ node_data: node_data.clone(),
|
|
|
rev_id: 1,
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path,
|
|
|
- expected: Some(inserted_node),
|
|
|
+ expected: Some(node_data),
|
|
|
},
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
-fn node_insert_node_with_children_test() {
|
|
|
+#[should_panic]
|
|
|
+fn node_insert_with_empty_path_test() {
|
|
|
let mut test = NodeTest::new();
|
|
|
- let inserted_node = NodeDataBuilder::new("text").add_node(NodeData::new("image")).build();
|
|
|
- let path: Path = 0.into();
|
|
|
+ let scripts = vec![InsertNode {
|
|
|
+ path: vec![].into(),
|
|
|
+ node_data: NodeData::new("text"),
|
|
|
+ rev_id: 1,
|
|
|
+ }];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+#[should_panic]
|
|
|
+fn node_insert_with_not_exist_path_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let node_data = NodeData::new("text");
|
|
|
+ let path: Path = vec![0, 0, 9].into();
|
|
|
let scripts = vec![
|
|
|
InsertNode {
|
|
|
path: path.clone(),
|
|
|
- node_data: inserted_node.clone(),
|
|
|
+ node_data: node_data.clone(),
|
|
|
rev_id: 1,
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path,
|
|
|
- expected: Some(inserted_node),
|
|
|
+ expected: Some(node_data),
|
|
|
},
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
-fn node_insert_multi_nodes_test() {
|
|
|
+// Append the node to the end of the list if the insert path is out of bounds.
|
|
|
+fn node_insert_out_of_bound_test() {
|
|
|
let mut test = NodeTest::new();
|
|
|
- let path_1: Path = 0.into();
|
|
|
- let node_1 = NodeData::new("text_1");
|
|
|
+ let image_a = NodeData::new("image_a");
|
|
|
+ let image_b = NodeData::new("image_b");
|
|
|
+ let image = NodeDataBuilder::new("image_1")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node = NodeDataBuilder::new("text_1").add_node_data(image.clone()).build();
|
|
|
+ let image_c = NodeData::new("image_c");
|
|
|
|
|
|
- let path_2: Path = 1.into();
|
|
|
- let node_2 = NodeData::new("text_2");
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ InsertNode {
|
|
|
+ path: vec![0, 0, 10].into(),
|
|
|
+ node_data: image_c.clone(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ // 2:image_b
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 2].into(),
|
|
|
+ expected: Some(image_c),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 10].into(),
|
|
|
+ expected: None,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
|
|
|
- let path_3: Path = 2.into();
|
|
|
- let node_3 = NodeData::new("text_3");
|
|
|
+#[test]
|
|
|
+fn tree_insert_multiple_nodes_at_root_path_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let node_1 = NodeData::new("a");
|
|
|
+ let node_2 = NodeData::new("b");
|
|
|
+ let node_3 = NodeData::new("c");
|
|
|
+ let node_data_list = vec![node_1, node_2, node_3];
|
|
|
+ let path: Path = vec![0].into();
|
|
|
|
|
|
+ // Insert three nodes under the root
|
|
|
+ let scripts = vec![
|
|
|
+ // 0:a
|
|
|
+ // 1:b
|
|
|
+ // 2:c
|
|
|
+ InsertNodes {
|
|
|
+ path,
|
|
|
+ node_data_list: node_data_list.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ AssertNodesAtRoot {
|
|
|
+ expected: node_data_list,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn tree_insert_multiple_nodes_at_root_path_test2() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let node_1 = NodeData::new("a");
|
|
|
+ let node_2 = NodeData::new("b");
|
|
|
+ let node_3 = NodeData::new("c");
|
|
|
let scripts = vec![
|
|
|
InsertNode {
|
|
|
- path: path_1.clone(),
|
|
|
+ path: 0.into(),
|
|
|
node_data: node_1.clone(),
|
|
|
rev_id: 1,
|
|
|
},
|
|
|
InsertNode {
|
|
|
- path: path_2.clone(),
|
|
|
+ path: 1.into(),
|
|
|
node_data: node_2.clone(),
|
|
|
rev_id: 2,
|
|
|
},
|
|
|
InsertNode {
|
|
|
- path: path_3.clone(),
|
|
|
+ path: 2.into(),
|
|
|
node_data: node_3.clone(),
|
|
|
rev_id: 3,
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
- path: path_1,
|
|
|
+ // 0:a
|
|
|
+ // 1:b
|
|
|
+ // 2:c
|
|
|
+ AssertNode {
|
|
|
+ path: 0.into(),
|
|
|
expected: Some(node_1),
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
- path: path_2,
|
|
|
+ AssertNode {
|
|
|
+ path: 1.into(),
|
|
|
expected: Some(node_2),
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
- path: path_3,
|
|
|
+ AssertNode {
|
|
|
+ path: 2.into(),
|
|
|
expected: Some(node_3),
|
|
|
},
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
|
|
|
|
+#[test]
|
|
|
+fn node_insert_node_with_children_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let image_1 = NodeData::new("image_a");
|
|
|
+ let image_2 = NodeData::new("image_b");
|
|
|
+
|
|
|
+ let image = NodeDataBuilder::new("image")
|
|
|
+ .add_node_data(image_1.clone())
|
|
|
+ .add_node_data(image_2.clone())
|
|
|
+ .build();
|
|
|
+ let node_data = NodeDataBuilder::new("text").add_node_data(image.clone()).build();
|
|
|
+ let path: Path = 0.into();
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: path.clone(),
|
|
|
+ node_data: node_data.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ // 0:text
|
|
|
+ // 0:image
|
|
|
+ // 0:image_1
|
|
|
+ // 1:image_2
|
|
|
+ AssertNode {
|
|
|
+ path,
|
|
|
+ expected: Some(node_data),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ expected: Some(image),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ expected: Some(image_1),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 1].into(),
|
|
|
+ expected: Some(image_2),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
#[test]
|
|
|
fn node_insert_node_in_ordered_nodes_test() {
|
|
|
let mut test = NodeTest::new();
|
|
@@ -129,19 +252,22 @@ fn node_insert_node_in_ordered_nodes_test() {
|
|
|
// 1:text_2_2
|
|
|
// 2:text_2_1
|
|
|
// 3:text_3
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path: path_1,
|
|
|
expected: Some(node_1),
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path: path_2,
|
|
|
expected: Some(node_2_2),
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path: path_3,
|
|
|
expected: Some(node_2_1),
|
|
|
},
|
|
|
- AssertNumberOfNodesAtPath { path: None, len: 4 },
|
|
|
+ AssertNumberOfChildrenAtPath {
|
|
|
+ path: None,
|
|
|
+ expected: 4,
|
|
|
+ },
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
@@ -152,15 +278,15 @@ fn node_insert_nested_nodes_test() {
|
|
|
let node_data_1_1 = NodeDataBuilder::new("text_1_1").build();
|
|
|
let node_data_1_2 = NodeDataBuilder::new("text_1_2").build();
|
|
|
let node_data_1 = NodeDataBuilder::new("text_1")
|
|
|
- .add_node(node_data_1_1.clone())
|
|
|
- .add_node(node_data_1_2.clone())
|
|
|
+ .add_node_data(node_data_1_1.clone())
|
|
|
+ .add_node_data(node_data_1_2.clone())
|
|
|
.build();
|
|
|
|
|
|
let node_data_2_1 = NodeDataBuilder::new("text_2_1").build();
|
|
|
let node_data_2_2 = NodeDataBuilder::new("text_2_2").build();
|
|
|
let node_data_2 = NodeDataBuilder::new("text_2")
|
|
|
- .add_node(node_data_2_1.clone())
|
|
|
- .add_node(node_data_2_2.clone())
|
|
|
+ .add_node_data(node_data_2_1.clone())
|
|
|
+ .add_node_data(node_data_2_2.clone())
|
|
|
.build();
|
|
|
|
|
|
let scripts = vec![
|
|
@@ -207,8 +333,8 @@ fn node_insert_node_before_existing_nested_nodes_test() {
|
|
|
let node_data_1_1 = NodeDataBuilder::new("text_1_1").build();
|
|
|
let node_data_1_2 = NodeDataBuilder::new("text_1_2").build();
|
|
|
let node_data_1 = NodeDataBuilder::new("text_1")
|
|
|
- .add_node(node_data_1_1.clone())
|
|
|
- .add_node(node_data_1_2.clone())
|
|
|
+ .add_node_data(node_data_1_1.clone())
|
|
|
+ .add_node_data(node_data_1_2.clone())
|
|
|
.build();
|
|
|
|
|
|
let scripts = vec![
|
|
@@ -258,7 +384,7 @@ fn node_insert_with_attributes_test() {
|
|
|
path: path.clone(),
|
|
|
attributes: inserted_node.attributes.clone(),
|
|
|
},
|
|
|
- AssertNodeData {
|
|
|
+ AssertNode {
|
|
|
path,
|
|
|
expected: Some(inserted_node),
|
|
|
},
|
|
@@ -270,7 +396,6 @@ fn node_insert_with_attributes_test() {
|
|
|
fn node_delete_test() {
|
|
|
let mut test = NodeTest::new();
|
|
|
let inserted_node = NodeData::new("text");
|
|
|
-
|
|
|
let path: Path = 0.into();
|
|
|
let scripts = vec![
|
|
|
InsertNode {
|
|
@@ -282,7 +407,314 @@ fn node_delete_test() {
|
|
|
path: path.clone(),
|
|
|
rev_id: 2,
|
|
|
},
|
|
|
- AssertNodeData { path, expected: None },
|
|
|
+ AssertNode { path, expected: None },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn node_delete_node_from_list_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let image_a = NodeData::new("image_a");
|
|
|
+ let image_b = NodeData::new("image_b");
|
|
|
+
|
|
|
+ let image_1 = NodeDataBuilder::new("image_1")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_1 = NodeDataBuilder::new("text_1").add_node_data(image_1.clone()).build();
|
|
|
+ let image_2 = NodeDataBuilder::new("image_2")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_2 = NodeDataBuilder::new("text_2").add_node_data(image_2.clone()).build();
|
|
|
+
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node_1,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ InsertNode {
|
|
|
+ path: 1.into(),
|
|
|
+ node_data: text_node_2.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ DeleteNode {
|
|
|
+ path: 0.into(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: 1.into(),
|
|
|
+ expected: None,
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: Some(text_node_2),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ expected: Some(image_2),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn node_delete_nested_node_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let image_a = NodeData::new("image_a");
|
|
|
+ let image_b = NodeData::new("image_b");
|
|
|
+
|
|
|
+ let image_1 = NodeDataBuilder::new("image_1")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_1 = NodeDataBuilder::new("text_1").add_node_data(image_1.clone()).build();
|
|
|
+
|
|
|
+ let image_2 = NodeDataBuilder::new("image_2")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_2 = NodeDataBuilder::new("text_2").add_node_data(image_2.clone()).build();
|
|
|
+
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node_1,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ InsertNode {
|
|
|
+ path: 1.into(),
|
|
|
+ node_data: text_node_2.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ // 1:text_2
|
|
|
+ // 0:image_2
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ DeleteNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_b
|
|
|
+ // 1:text_2
|
|
|
+ // 0:image_2
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ expected: Some(image_b.clone()),
|
|
|
+ },
|
|
|
+ DeleteNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ rev_id: 3,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 1:text_2
|
|
|
+ // 0:image_2
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ AssertNumberOfChildrenAtPath {
|
|
|
+ path: Some(0.into()),
|
|
|
+ expected: 0,
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0].into(),
|
|
|
+ expected: Some(NodeDataBuilder::new("text_1").build()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![1, 0, 0].into(),
|
|
|
+ expected: Some(image_a.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![1, 0, 1].into(),
|
|
|
+ expected: Some(image_b.clone()),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn node_delete_children_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let inserted_node = NodeDataBuilder::new("text")
|
|
|
+ .add_node_data(NodeDataBuilder::new("sub_text_1").build())
|
|
|
+ .add_node_data(NodeDataBuilder::new("sub_text_2").build())
|
|
|
+ .add_node_data(NodeDataBuilder::new("sub_text_3").build())
|
|
|
+ .build();
|
|
|
+
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: vec![0].into(),
|
|
|
+ node_data: inserted_node,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ expected: Some(NodeDataBuilder::new("sub_text_1").build()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 1].into(),
|
|
|
+ expected: Some(NodeDataBuilder::new("sub_text_2").build()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 2].into(),
|
|
|
+ expected: Some(NodeDataBuilder::new("sub_text_3").build()),
|
|
|
+ },
|
|
|
+ AssertNumberOfChildrenAtPath {
|
|
|
+ path: Some(Path(vec![0])),
|
|
|
+ expected: 3,
|
|
|
+ },
|
|
|
+ DeleteNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ expected: Some(NodeDataBuilder::new("sub_text_2").build()),
|
|
|
+ },
|
|
|
+ AssertNumberOfChildrenAtPath {
|
|
|
+ path: Some(Path(vec![0])),
|
|
|
+ expected: 2,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn node_reorder_sub_nodes_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let image_a = NodeData::new("image_a");
|
|
|
+ let image_b = NodeData::new("image_b");
|
|
|
+
|
|
|
+ let child_1 = NodeDataBuilder::new("image_1")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_1 = NodeDataBuilder::new("text_1").add_node_data(child_1.clone()).build();
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node_1,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ DeleteNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_b
|
|
|
+ InsertNode {
|
|
|
+ path: vec![0, 0, 1].into(),
|
|
|
+ node_data: image_a.clone(),
|
|
|
+ rev_id: 3,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_b
|
|
|
+ // 1:image_a
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ expected: Some(image_b.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 1].into(),
|
|
|
+ expected: Some(image_a.clone()),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn node_reorder_nodes_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let image_a = NodeData::new("image_a");
|
|
|
+ let image_b = NodeData::new("image_b");
|
|
|
+
|
|
|
+ let image_1 = NodeDataBuilder::new("image_1")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_1 = NodeDataBuilder::new("text_1").add_node_data(image_1.clone()).build();
|
|
|
+
|
|
|
+ let image_2 = NodeDataBuilder::new("image_2")
|
|
|
+ .add_node_data(image_a.clone())
|
|
|
+ .add_node_data(image_b.clone())
|
|
|
+ .build();
|
|
|
+ let text_node_2 = NodeDataBuilder::new("text_2").add_node_data(image_2.clone()).build();
|
|
|
+
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node_1.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: text_node_2.clone(),
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ // 0:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ // 1:text_2
|
|
|
+ // 0:image_2
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ DeleteNode {
|
|
|
+ path: vec![0].into(),
|
|
|
+ rev_id: 2,
|
|
|
+ },
|
|
|
+ InsertNode {
|
|
|
+ path: vec![1].into(),
|
|
|
+ node_data: text_node_1.clone(),
|
|
|
+ rev_id: 3,
|
|
|
+ },
|
|
|
+ // 0:text_2
|
|
|
+ // 0:image_2
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ // 1:text_1
|
|
|
+ // 0:image_1
|
|
|
+ // 0:image_a
|
|
|
+ // 1:image_b
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0].into(),
|
|
|
+ expected: Some(text_node_2.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0].into(),
|
|
|
+ expected: Some(image_2.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![0, 0, 0].into(),
|
|
|
+ expected: Some(image_a.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![1].into(),
|
|
|
+ expected: Some(text_node_1.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![1, 0].into(),
|
|
|
+ expected: Some(image_1.clone()),
|
|
|
+ },
|
|
|
+ AssertNode {
|
|
|
+ path: vec![1, 0, 1].into(),
|
|
|
+ expected: Some(image_b.clone()),
|
|
|
+ },
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
@@ -290,29 +722,79 @@ fn node_delete_test() {
|
|
|
#[test]
|
|
|
fn node_update_body_test() {
|
|
|
let mut test = NodeTest::new();
|
|
|
- let path: Path = 0.into();
|
|
|
+ let (initial_delta, changeset, _, expected) = make_node_delta_changeset("Hello", "AppFlowy");
|
|
|
+ let node = NodeDataBuilder::new("text")
|
|
|
+ .insert_body(Body::Delta(initial_delta))
|
|
|
+ .build();
|
|
|
|
|
|
- let s = "Hello".to_owned();
|
|
|
- let init_delta = TextOperationBuilder::new().insert(&s).build();
|
|
|
- let delta = TextOperationBuilder::new().retain(s.len()).insert(" AppFlowy").build();
|
|
|
- let inverted = delta.invert(&init_delta);
|
|
|
- let expected = init_delta.compose(&delta).unwrap();
|
|
|
+ let scripts = vec![
|
|
|
+ InsertNode {
|
|
|
+ path: 0.into(),
|
|
|
+ node_data: node,
|
|
|
+ rev_id: 1,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset,
|
|
|
+ },
|
|
|
+ AssertNodeDelta {
|
|
|
+ path: 0.into(),
|
|
|
+ expected,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ test.run_scripts(scripts);
|
|
|
+}
|
|
|
|
|
|
+#[test]
|
|
|
+fn node_inverted_body_changeset_test() {
|
|
|
+ let mut test = NodeTest::new();
|
|
|
+ let (initial_delta, changeset, inverted_changeset, _expected) = make_node_delta_changeset("Hello", "AppFlowy");
|
|
|
let node = NodeDataBuilder::new("text")
|
|
|
- .insert_body(NodeBody::Delta(init_delta))
|
|
|
+ .insert_body(Body::Delta(initial_delta.clone()))
|
|
|
.build();
|
|
|
|
|
|
let scripts = vec![
|
|
|
InsertNode {
|
|
|
- path: path.clone(),
|
|
|
+ path: 0.into(),
|
|
|
node_data: node,
|
|
|
rev_id: 1,
|
|
|
},
|
|
|
UpdateBody {
|
|
|
- path: path.clone(),
|
|
|
- changeset: NodeBodyChangeset::Delta { delta, inverted },
|
|
|
+ path: 0.into(),
|
|
|
+ changeset,
|
|
|
+ },
|
|
|
+ UpdateBody {
|
|
|
+ path: 0.into(),
|
|
|
+ changeset: inverted_changeset,
|
|
|
+ },
|
|
|
+ AssertNodeDelta {
|
|
|
+ path: 0.into(),
|
|
|
+ expected: initial_delta,
|
|
|
},
|
|
|
- AssertNodeDelta { path, expected },
|
|
|
];
|
|
|
test.run_scripts(scripts);
|
|
|
}
|
|
|
+
|
|
|
+fn make_node_delta_changeset(
|
|
|
+ initial_content: &str,
|
|
|
+ insert_str: &str,
|
|
|
+) -> (TextOperations, Changeset, Changeset, TextOperations) {
|
|
|
+ let initial_content = initial_content.to_owned();
|
|
|
+ let initial_delta = TextOperationBuilder::new().insert(&initial_content).build();
|
|
|
+ let delta = TextOperationBuilder::new()
|
|
|
+ .retain(initial_content.len())
|
|
|
+ .insert(insert_str)
|
|
|
+ .build();
|
|
|
+ let inverted = delta.invert(&initial_delta);
|
|
|
+ let expected = initial_delta.compose(&delta).unwrap();
|
|
|
+
|
|
|
+ let changeset = Changeset::Delta {
|
|
|
+ delta: delta.clone(),
|
|
|
+ inverted: inverted.clone(),
|
|
|
+ };
|
|
|
+ let inverted_changeset = Changeset::Delta {
|
|
|
+ delta: inverted,
|
|
|
+ inverted: delta,
|
|
|
+ };
|
|
|
+ (initial_delta, changeset, inverted_changeset, expected)
|
|
|
+}
|