mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
179 lines
4.8 KiB
Rust
179 lines
4.8 KiB
Rust
|
use crate::node::script::NodeScript::*;
|
||
|
use crate::node::script::NodeTest;
|
||
|
|
||
|
use lib_ot::core::{Changeset, NodeData, NodeDataBuilder};
|
||
|
|
||
|
#[test]
|
||
|
fn operation_delete_nested_node_test() {
|
||
|
let mut test = NodeTest::new();
|
||
|
let image_a = NodeData::new("image_a");
|
||
|
let image_b = NodeData::new("image_b");
|
||
|
|
||
|
let video_a = NodeData::new("video_a");
|
||
|
let video_b = NodeData::new("video_b");
|
||
|
|
||
|
let image_1 = NodeDataBuilder::new("image_1")
|
||
|
.add_node_data(image_a.clone())
|
||
|
.add_node_data(image_b.clone())
|
||
|
.build();
|
||
|
let video_1 = NodeDataBuilder::new("video_1")
|
||
|
.add_node_data(video_a.clone())
|
||
|
.add_node_data(video_b)
|
||
|
.build();
|
||
|
|
||
|
let text_node_1 = NodeDataBuilder::new("text_1")
|
||
|
.add_node_data(image_1)
|
||
|
.add_node_data(video_1.clone())
|
||
|
.build();
|
||
|
|
||
|
let image_2 = NodeDataBuilder::new("image_2")
|
||
|
.add_node_data(image_a)
|
||
|
.add_node_data(image_b.clone())
|
||
|
.build();
|
||
|
let text_node_2 = NodeDataBuilder::new("text_2").add_node_data(image_2).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,
|
||
|
rev_id: 2,
|
||
|
},
|
||
|
// 0:text_1
|
||
|
// 0:image_1
|
||
|
// 0:image_a
|
||
|
// 1:image_b
|
||
|
// 1:video_1
|
||
|
// 0:video_a
|
||
|
// 1:video_b
|
||
|
// 1:text_2
|
||
|
// 0:image_2
|
||
|
// 0:image_a
|
||
|
// 1:image_b
|
||
|
DeleteNode {
|
||
|
path: vec![0, 0, 0].into(),
|
||
|
rev_id: 3,
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: vec![0, 0, 0].into(),
|
||
|
expected: Some(image_b),
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: vec![0, 1].into(),
|
||
|
expected: Some(video_1),
|
||
|
},
|
||
|
DeleteNode {
|
||
|
path: vec![0, 1, 1].into(),
|
||
|
rev_id: 4,
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: vec![0, 1, 0].into(),
|
||
|
expected: Some(video_a),
|
||
|
},
|
||
|
];
|
||
|
test.run_scripts(scripts);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn operation_delete_node_with_revision_conflict_test() {
|
||
|
let mut test = NodeTest::new();
|
||
|
let text_1 = NodeDataBuilder::new("text_1").build();
|
||
|
let text_2 = NodeDataBuilder::new("text_2").build();
|
||
|
let text_3 = NodeDataBuilder::new("text_3").build();
|
||
|
|
||
|
let scripts = vec![
|
||
|
InsertNode {
|
||
|
path: 0.into(),
|
||
|
node_data: text_1.clone(),
|
||
|
rev_id: 1,
|
||
|
},
|
||
|
InsertNode {
|
||
|
path: 1.into(),
|
||
|
node_data: text_2,
|
||
|
rev_id: 2,
|
||
|
},
|
||
|
// The node's in the tree will be:
|
||
|
// 0: text_1
|
||
|
// 2: text_2
|
||
|
//
|
||
|
// The insert action is happened concurrently with the delete action, because they
|
||
|
// share the same rev_id. aka, 3. The delete action is want to delete the node at index 1,
|
||
|
// but it was moved to index 2.
|
||
|
InsertNode {
|
||
|
path: 1.into(),
|
||
|
node_data: text_3.clone(),
|
||
|
rev_id: 3,
|
||
|
},
|
||
|
// 0: text_1
|
||
|
// 1: text_3
|
||
|
// 2: text_2
|
||
|
//
|
||
|
// The path of the delete action will be transformed to a new path that point to the text_2.
|
||
|
// 1 -> 2
|
||
|
DeleteNode {
|
||
|
path: 1.into(),
|
||
|
rev_id: 3,
|
||
|
},
|
||
|
// After perform the delete action, the tree will be:
|
||
|
// 0: text_1
|
||
|
// 1: text_3
|
||
|
AssertNumberOfChildrenAtPath {
|
||
|
path: None,
|
||
|
expected: 2,
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: 0.into(),
|
||
|
expected: Some(text_1),
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: 1.into(),
|
||
|
expected: Some(text_3),
|
||
|
},
|
||
|
AssertNode {
|
||
|
path: 2.into(),
|
||
|
expected: None,
|
||
|
},
|
||
|
];
|
||
|
test.run_scripts(scripts);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn operation_update_node_after_delete_test() {
|
||
|
let mut test = NodeTest::new();
|
||
|
let text_1 = NodeDataBuilder::new("text_1").build();
|
||
|
let text_2 = NodeDataBuilder::new("text_2").build();
|
||
|
let scripts = vec![
|
||
|
InsertNode {
|
||
|
path: 0.into(),
|
||
|
node_data: text_1,
|
||
|
rev_id: 1,
|
||
|
},
|
||
|
InsertNode {
|
||
|
path: 1.into(),
|
||
|
node_data: text_2,
|
||
|
rev_id: 2,
|
||
|
},
|
||
|
DeleteNode {
|
||
|
path: 0.into(),
|
||
|
rev_id: 3,
|
||
|
},
|
||
|
// The node at path 1 is not exist. The following UpdateBody script will do nothing
|
||
|
AssertNode {
|
||
|
path: 1.into(),
|
||
|
expected: None,
|
||
|
},
|
||
|
UpdateBody {
|
||
|
path: 1.into(),
|
||
|
changeset: Changeset::Delta {
|
||
|
delta: Default::default(),
|
||
|
inverted: Default::default(),
|
||
|
},
|
||
|
},
|
||
|
];
|
||
|
test.run_scripts(scripts);
|
||
|
}
|