operation_test.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. use crate::node::script::NodeScript::*;
  2. use crate::node::script::NodeTest;
  3. use lib_ot::core::{AttributeBuilder, Node};
  4. use lib_ot::{
  5. core::{NodeBodyChangeset, NodeData, NodeDataBuilder, NodeOperation, Path},
  6. text_delta::TextOperationBuilder,
  7. };
  8. #[test]
  9. fn operation_insert_node_serde_test() {
  10. let insert = NodeOperation::Insert {
  11. path: Path(vec![0, 1]),
  12. nodes: vec![NodeData::new("text".to_owned())],
  13. };
  14. let result = serde_json::to_string(&insert).unwrap();
  15. assert_eq!(result, r#"{"op":"insert","path":[0,1],"nodes":[{"type":"text"}]}"#);
  16. }
  17. #[test]
  18. fn operation_insert_node_with_children_serde_test() {
  19. let node = NodeDataBuilder::new("text")
  20. .add_node(NodeData::new("sub_text".to_owned()))
  21. .build();
  22. let insert = NodeOperation::Insert {
  23. path: Path(vec![0, 1]),
  24. nodes: vec![node],
  25. };
  26. assert_eq!(
  27. serde_json::to_string(&insert).unwrap(),
  28. r#"{"op":"insert","path":[0,1],"nodes":[{"type":"text","children":[{"type":"sub_text"}]}]}"#
  29. );
  30. }
  31. #[test]
  32. fn operation_update_node_attributes_serde_test() {
  33. let operation = NodeOperation::UpdateAttributes {
  34. path: Path(vec![0, 1]),
  35. new: AttributeBuilder::new().insert("bold", true).build(),
  36. old: AttributeBuilder::new().insert("bold", false).build(),
  37. };
  38. let result = serde_json::to_string(&operation).unwrap();
  39. assert_eq!(
  40. result,
  41. r#"{"op":"update-attribute","path":[0,1],"new":{"bold":true},"old":{"bold":null}}"#
  42. );
  43. }
  44. #[test]
  45. fn operation_update_node_body_serialize_test() {
  46. let delta = TextOperationBuilder::new().insert("AppFlowy...").build();
  47. let inverted = delta.invert_str("");
  48. let changeset = NodeBodyChangeset::Delta { delta, inverted };
  49. let insert = NodeOperation::UpdateBody {
  50. path: Path(vec![0, 1]),
  51. changeset,
  52. };
  53. let result = serde_json::to_string(&insert).unwrap();
  54. assert_eq!(
  55. result,
  56. r#"{"op":"update-body","path":[0,1],"changeset":{"delta":{"delta":[{"insert":"AppFlowy..."}],"inverted":[{"delete":11}]}}}"#
  57. );
  58. //
  59. }
  60. #[test]
  61. fn operation_update_node_body_deserialize_test() {
  62. let json_1 = r#"{"op":"update-body","path":[0,1],"changeset":{"delta":{"delta":[{"insert":"AppFlowy..."}],"inverted":[{"delete":11}]}}}"#;
  63. let operation: NodeOperation = serde_json::from_str(json_1).unwrap();
  64. let json_2 = serde_json::to_string(&operation).unwrap();
  65. assert_eq!(json_1, json_2);
  66. }
  67. #[test]
  68. fn operation_insert_op_transform_test() {
  69. let node_1 = NodeDataBuilder::new("text_1").build();
  70. let node_2 = NodeDataBuilder::new("text_2").build();
  71. let op_1 = NodeOperation::Insert {
  72. path: Path(vec![0, 1]),
  73. nodes: vec![node_1],
  74. };
  75. let mut insert_2 = NodeOperation::Insert {
  76. path: Path(vec![0, 1]),
  77. nodes: vec![node_2],
  78. };
  79. // let mut node_tree = NodeTree::new("root");
  80. // node_tree.apply_op(insert_1.clone()).unwrap();
  81. op_1.transform(&mut insert_2);
  82. let json = serde_json::to_string(&insert_2).unwrap();
  83. assert_eq!(json, r#"{"op":"insert","path":[0,2],"nodes":[{"type":"text_2"}]}"#);
  84. }
  85. #[test]
  86. fn operation_insert_transform_one_level_path_test() {
  87. let mut test = NodeTest::new();
  88. let node_data_1 = NodeDataBuilder::new("text_1").build();
  89. let node_data_2 = NodeDataBuilder::new("text_2").build();
  90. let node_data_3 = NodeDataBuilder::new("text_3").build();
  91. let node_3: Node = node_data_3.clone().into();
  92. // 0: text_1
  93. // 1: text_2
  94. //
  95. // Insert a new operation with rev_id 1,but the rev_id:1 is already exist, so
  96. // it needs to be transformed.
  97. // 1:text_3 => 2:text_3
  98. //
  99. // 0: text_1
  100. // 1: text_2
  101. // 2: text_3
  102. //
  103. // If the rev_id of the insert operation is 3. then the tree will be:
  104. // 0: text_1
  105. // 1: text_3
  106. // 2: text_2
  107. let scripts = vec![
  108. InsertNode {
  109. path: 0.into(),
  110. node_data: node_data_1,
  111. rev_id: 1,
  112. },
  113. InsertNode {
  114. path: 1.into(),
  115. node_data: node_data_2,
  116. rev_id: 2,
  117. },
  118. InsertNode {
  119. path: 1.into(),
  120. node_data: node_data_3,
  121. rev_id: 1,
  122. },
  123. AssertNode {
  124. path: 2.into(),
  125. expected: Some(node_3),
  126. },
  127. ];
  128. test.run_scripts(scripts);
  129. }
  130. #[test]
  131. fn operation_insert_transform_multiple_level_path_test() {
  132. let mut test = NodeTest::new();
  133. let node_data_1 = NodeDataBuilder::new("text_1")
  134. .add_node(NodeDataBuilder::new("text_1_1").build())
  135. .add_node(NodeDataBuilder::new("text_1_2").build())
  136. .build();
  137. let node_data_2 = NodeDataBuilder::new("text_2")
  138. .add_node(NodeDataBuilder::new("text_2_1").build())
  139. .add_node(NodeDataBuilder::new("text_2_2").build())
  140. .build();
  141. let node_data_3 = NodeDataBuilder::new("text_3").build();
  142. let scripts = vec![
  143. InsertNode {
  144. path: 0.into(),
  145. node_data: node_data_1,
  146. rev_id: 1,
  147. },
  148. InsertNode {
  149. path: 1.into(),
  150. node_data: node_data_2,
  151. rev_id: 2,
  152. },
  153. InsertNode {
  154. path: 1.into(),
  155. node_data: node_data_3.clone(),
  156. rev_id: 1,
  157. },
  158. AssertNode {
  159. path: 2.into(),
  160. expected: Some(node_data_3.into()),
  161. },
  162. ];
  163. test.run_scripts(scripts);
  164. }
  165. #[test]
  166. fn operation_delete_transform_path_test() {
  167. let mut test = NodeTest::new();
  168. let node_data_1 = NodeDataBuilder::new("text_1").build();
  169. let node_data_2 = NodeDataBuilder::new("text_2").build();
  170. let node_data_3 = NodeDataBuilder::new("text_3").build();
  171. let node_3: Node = node_data_3.clone().into();
  172. let scripts = vec![
  173. InsertNode {
  174. path: 0.into(),
  175. node_data: node_data_1,
  176. rev_id: 1,
  177. },
  178. InsertNode {
  179. path: 1.into(),
  180. node_data: node_data_2,
  181. rev_id: 2,
  182. },
  183. // The node's in the tree will be:
  184. // 0: text_1
  185. // 2: text_2
  186. //
  187. // The insert action is happened concurrently with the delete action, because they
  188. // share the same rev_id. aka, 3. The delete action is want to delete the node at index 1,
  189. // but it was moved to index 2.
  190. InsertNode {
  191. path: 1.into(),
  192. node_data: node_data_3,
  193. rev_id: 3,
  194. },
  195. // 0: text_1
  196. // 1: text_3
  197. // 2: text_2
  198. //
  199. // The path of the delete action will be transformed to a new path that point to the text_2.
  200. // 1 -> 2
  201. DeleteNode {
  202. path: 1.into(),
  203. rev_id: 3,
  204. },
  205. // After perform the delete action, the tree will be:
  206. // 0: text_1
  207. // 1: text_3
  208. AssertNumberOfNodesAtPath { path: None, len: 2 },
  209. AssertNode {
  210. path: 1.into(),
  211. expected: Some(node_3),
  212. },
  213. AssertNode {
  214. path: 2.into(),
  215. expected: None,
  216. },
  217. ];
  218. test.run_scripts(scripts);
  219. }