transaction_compose_test.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. use crate::node::script::{edit_node_delta, make_node_delta_changeset};
  2. use lib_ot::core::{AttributeEntry, Changeset, NodeDataBuilder, NodeOperation, Transaction, TransactionBuilder};
  3. use lib_ot::text_delta::DeltaTextOperationBuilder;
  4. #[test]
  5. fn transaction_compose_update_after_insert_test() {
  6. let (initial_delta, changeset, _) = make_node_delta_changeset("Hello", " world");
  7. let node_data = NodeDataBuilder::new("text").insert_delta(initial_delta).build();
  8. // Modify the same path, the operations will be merged after composing if possible.
  9. let mut transaction_a = TransactionBuilder::new().insert_node_at_path(0, node_data).build();
  10. let transaction_b = TransactionBuilder::new().update_node_at_path(0, changeset).build();
  11. transaction_a.compose(transaction_b).unwrap();
  12. // The operations are merged into one operation
  13. assert_eq!(transaction_a.operations.len(), 1);
  14. assert_eq!(
  15. transaction_a.to_json().unwrap(),
  16. r#"{"operations":[{"op":"insert","path":[0],"nodes":[{"type":"text","body":{"delta":[{"insert":"Hello world"}]}}]}]}"#
  17. );
  18. }
  19. #[test]
  20. fn transaction_compose_multiple_update_test() {
  21. let (initial_delta, changeset_1, final_delta) = make_node_delta_changeset("Hello", " world");
  22. let mut transaction = TransactionBuilder::new()
  23. .insert_node_at_path(0, NodeDataBuilder::new("text").insert_delta(initial_delta).build())
  24. .build();
  25. let (changeset_2, _) = edit_node_delta(
  26. &final_delta,
  27. DeltaTextOperationBuilder::new()
  28. .retain(final_delta.utf16_target_len)
  29. .insert("😁")
  30. .build(),
  31. );
  32. let mut other_transaction = Transaction::new();
  33. // the following two update operations will be merged into one
  34. let update_1 = TransactionBuilder::new().update_node_at_path(0, changeset_1).build();
  35. other_transaction.compose(update_1).unwrap();
  36. let update_2 = TransactionBuilder::new().update_node_at_path(0, changeset_2).build();
  37. other_transaction.compose(update_2).unwrap();
  38. let inverted = Transaction::from_operations(other_transaction.operations.inverted());
  39. // the update operation will be merged into insert operation
  40. transaction.compose(other_transaction).unwrap();
  41. assert_eq!(transaction.operations.len(), 1);
  42. assert_eq!(
  43. transaction.to_json().unwrap(),
  44. r#"{"operations":[{"op":"insert","path":[0],"nodes":[{"type":"text","body":{"delta":[{"insert":"Hello world😁"}]}}]}]}"#
  45. );
  46. transaction.compose(inverted).unwrap();
  47. assert_eq!(
  48. transaction.to_json().unwrap(),
  49. r#"{"operations":[{"op":"insert","path":[0],"nodes":[{"type":"text","body":{"delta":[{"insert":"Hello"}]}}]}]}"#
  50. );
  51. }
  52. #[test]
  53. fn transaction_compose_multiple_attribute_test() {
  54. let delta = DeltaTextOperationBuilder::new().insert("Hello").build();
  55. let node = NodeDataBuilder::new("text").insert_delta(delta).build();
  56. let insert_operation = NodeOperation::Insert {
  57. path: 0.into(),
  58. nodes: vec![node],
  59. };
  60. let mut transaction = Transaction::new();
  61. transaction.push_operation(insert_operation);
  62. let new_attribute = AttributeEntry::new("subtype", "bulleted-list");
  63. let update_operation = NodeOperation::Update {
  64. path: 0.into(),
  65. changeset: Changeset::Attributes {
  66. new: new_attribute.clone().into(),
  67. old: Default::default(),
  68. },
  69. };
  70. transaction.push_operation(update_operation);
  71. assert_eq!(
  72. transaction.to_json().unwrap(),
  73. r#"{"operations":[{"op":"insert","path":[0],"nodes":[{"type":"text","body":{"delta":[{"insert":"Hello"}]}}]},{"op":"update","path":[0],"changeset":{"attributes":{"new":{"subtype":"bulleted-list"},"old":{}}}}]}"#
  74. );
  75. let old_attribute = new_attribute;
  76. let new_attribute = AttributeEntry::new("subtype", "number-list");
  77. transaction.push_operation(NodeOperation::Update {
  78. path: 0.into(),
  79. changeset: Changeset::Attributes {
  80. new: new_attribute.into(),
  81. old: old_attribute.into(),
  82. },
  83. });
  84. assert_eq!(
  85. transaction.to_json().unwrap(),
  86. r#"{"operations":[{"op":"insert","path":[0],"nodes":[{"type":"text","body":{"delta":[{"insert":"Hello"}]}}]},{"op":"update","path":[0],"changeset":{"attributes":{"new":{"subtype":"number-list"},"old":{"subtype":"bulleted-list"}}}}]}"#
  87. );
  88. }