operation_test.rs 7.3 KB

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