operation_test.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. use crate::node::script::NodeScript::*;
  2. use crate::node::script::NodeTest;
  3. use lib_ot::core::{AttributeBuilder, Node, NodeTree, Transaction, TransactionBuilder};
  4. use lib_ot::{
  5. core::{NodeBodyChangeset, NodeData, NodeDataBuilder, NodeOperation, Path},
  6. text_delta::TextDeltaBuilder,
  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. attributes: AttributeBuilder::new().insert("bold", true).build(),
  36. old_attributes: 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","path":[0,1],"attributes":{"bold":true},"oldAttributes":{"bold":null}}"#
  42. );
  43. }
  44. #[test]
  45. fn operation_update_node_body_serialize_test() {
  46. let delta = TextDeltaBuilder::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 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. let new_op = op_1.transform(&insert_2);
  82. let json = serde_json::to_string(&new_op).unwrap();
  83. assert_eq!(json, r#"{"op":"insert","path":[0,2],"nodes":[{"type":"text_2"}]}"#);
  84. }
  85. #[test]
  86. fn operation_insert_transform_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. //
  93. // rev_id:1 0: text_1
  94. // rev_id:2 1: text_2
  95. //
  96. // Insert a new operation with rev_id 1.But the rev_id:1 is already exist, so
  97. // it needs to do the transform.
  98. //
  99. // --> 1:text_3
  100. // transform into:
  101. // --> 2:text_3
  102. //
  103. let scripts = vec![
  104. InsertNode {
  105. path: 0.into(),
  106. node_data: node_data_1.clone(),
  107. rev_id: 1,
  108. },
  109. InsertNode {
  110. path: 1.into(),
  111. node_data: node_data_2.clone(),
  112. rev_id: 2,
  113. },
  114. InsertNode {
  115. path: 1.into(),
  116. node_data: node_data_3.clone(),
  117. rev_id: 1,
  118. },
  119. AssertNode {
  120. path: 2.into(),
  121. expected: Some(node_3),
  122. },
  123. ];
  124. test.run_scripts(scripts);
  125. }
  126. #[test]
  127. fn operation_delete_transform_test() {
  128. let mut test = NodeTest::new();
  129. let node_data_1 = NodeDataBuilder::new("text_1").build();
  130. let node_data_2 = NodeDataBuilder::new("text_2").build();
  131. let node_data_3 = NodeDataBuilder::new("text_3").build();
  132. let node_3: Node = node_data_3.clone().into();
  133. let scripts = vec![
  134. InsertNode {
  135. path: 0.into(),
  136. node_data: node_data_1.clone(),
  137. rev_id: 1,
  138. },
  139. InsertNode {
  140. path: 1.into(),
  141. node_data: node_data_2.clone(),
  142. rev_id: 2,
  143. },
  144. // The node's in the tree will be:
  145. // 0: text_1
  146. // 2: text_2
  147. //
  148. // The insert action is happened concurrently with the delete action, because they
  149. // share the same rev_id. aka, 3. The delete action is want to delete the node at index 1,
  150. // but it was moved to index 2.
  151. InsertNode {
  152. path: 1.into(),
  153. node_data: node_data_3.clone(),
  154. rev_id: 3,
  155. },
  156. //
  157. // 0: text_1
  158. // 1: text_3
  159. // 2: text_2
  160. //
  161. // The path of the delete action will be transformed to a new path that point to the text_2.
  162. // 1 -> 2
  163. DeleteNode {
  164. path: 1.into(),
  165. rev_id: 3,
  166. },
  167. AssertNode {
  168. path: 1.into(),
  169. expected: Some(node_3),
  170. },
  171. AssertNode {
  172. path: 2.into(),
  173. expected: None,
  174. },
  175. AssertNumberOfNodesAtPath { path: None, len: 2 },
  176. ];
  177. test.run_scripts(scripts);
  178. }