mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: changeset composing (#1398)
This commit is contained in:
@ -35,7 +35,7 @@ packages:
|
|||||||
path: "packages/appflowy_editor"
|
path: "packages/appflowy_editor"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "0.0.6"
|
version: "0.0.7"
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -36,8 +36,7 @@ fn attributes_insert_text_at_middle() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delta_get_ops_in_interval_1() {
|
fn delta_get_ops_in_interval_1() {
|
||||||
let operations = OperationsBuilder::new().insert("123").insert("4").build();
|
let delta = DeltaTextOperationBuilder::new().insert("123").insert("4").build();
|
||||||
let delta = DeltaTextOperationBuilder::from_operations(operations);
|
|
||||||
|
|
||||||
let mut iterator = OperationIterator::from_interval(&delta, Interval::new(0, 4));
|
let mut iterator = OperationIterator::from_interval(&delta, Interval::new(0, 4));
|
||||||
assert_eq!(iterator.ops(), delta.ops);
|
assert_eq!(iterator.ops(), delta.ops);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::core::delta::operation::OperationAttributes;
|
use crate::core::delta::operation::OperationAttributes;
|
||||||
use crate::core::delta::{trim, DeltaOperations};
|
use crate::core::delta::{trim, DeltaOperations};
|
||||||
use crate::core::DeltaOperation;
|
|
||||||
|
|
||||||
/// A builder for creating new [Operations] objects.
|
/// A builder for creating new [Operations] objects.
|
||||||
///
|
///
|
||||||
@ -39,12 +38,13 @@ where
|
|||||||
DeltaOperationBuilder::default()
|
DeltaOperationBuilder::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_operations(operations: Vec<DeltaOperation<T>>) -> DeltaOperations<T> {
|
pub fn from_delta_operation(delta_operation: DeltaOperations<T>) -> Self {
|
||||||
let mut delta = DeltaOperationBuilder::default().build();
|
debug_assert!(delta_operation.utf16_base_len == 0);
|
||||||
operations.into_iter().for_each(|operation| {
|
let mut builder = DeltaOperationBuilder::new();
|
||||||
delta.add(operation);
|
delta_operation.ops.into_iter().for_each(|operation| {
|
||||||
|
builder.delta.add(operation);
|
||||||
});
|
});
|
||||||
delta
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retain the 'n' characters with the attributes. Use 'retain' instead if you don't
|
/// Retain the 'n' characters with the attributes. Use 'retain' instead if you don't
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
use crate::core::delta::operation::{DeltaOperation, EmptyAttributes, OperationAttributes};
|
|
||||||
|
|
||||||
// pub type RichTextOpBuilder = OperationsBuilder<TextAttributes>;
|
|
||||||
pub type PlainTextOpBuilder = OperationsBuilder<EmptyAttributes>;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct OperationsBuilder<T: OperationAttributes> {
|
|
||||||
operations: Vec<DeltaOperation<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> OperationsBuilder<T>
|
|
||||||
where
|
|
||||||
T: OperationAttributes,
|
|
||||||
{
|
|
||||||
pub fn new() -> OperationsBuilder<T> {
|
|
||||||
OperationsBuilder::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retain_with_attributes(mut self, n: usize, attributes: T) -> OperationsBuilder<T> {
|
|
||||||
let retain = DeltaOperation::retain_with_attributes(n, attributes);
|
|
||||||
self.operations.push(retain);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retain(mut self, n: usize) -> OperationsBuilder<T> {
|
|
||||||
let retain = DeltaOperation::retain(n);
|
|
||||||
self.operations.push(retain);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(mut self, n: usize) -> OperationsBuilder<T> {
|
|
||||||
self.operations.push(DeltaOperation::Delete(n));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_with_attributes(mut self, s: &str, attributes: T) -> OperationsBuilder<T> {
|
|
||||||
let insert = DeltaOperation::insert_with_attributes(s, attributes);
|
|
||||||
self.operations.push(insert);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(mut self, s: &str) -> OperationsBuilder<T> {
|
|
||||||
let insert = DeltaOperation::insert(s);
|
|
||||||
self.operations.push(insert);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(self) -> Vec<DeltaOperation<T>> {
|
|
||||||
self.operations
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
mod builder;
|
|
||||||
mod operation;
|
mod operation;
|
||||||
mod operation_serde;
|
mod operation_serde;
|
||||||
|
|
||||||
pub use builder::*;
|
|
||||||
pub use operation::*;
|
pub use operation::*;
|
||||||
pub use operation_serde::*;
|
pub use operation_serde::*;
|
||||||
|
@ -224,6 +224,10 @@ where
|
|||||||
Ok(new_s)
|
Ok(new_s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inverted(&self) -> Self {
|
||||||
|
self.invert_str("")
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the inverse [Delta]. The inverse of an operation is the
|
/// Computes the inverse [Delta]. The inverse of an operation is the
|
||||||
/// operation that reverts the effects of the operation
|
/// operation that reverts the effects of the operation
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -212,7 +212,7 @@ impl Changeset {
|
|||||||
inverted: _,
|
inverted: _,
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
let original = delta.invert(inverted);
|
let original = delta.compose(inverted)?;
|
||||||
let new_delta = delta.compose(other_delta)?;
|
let new_delta = delta.compose(other_delta)?;
|
||||||
let new_inverted = new_delta.invert(&original);
|
let new_inverted = new_delta.invert(&original);
|
||||||
|
|
||||||
|
@ -234,16 +234,6 @@ impl NodeOperations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if let Some(operations) = self.inner.get_mut(other.get_path()) {
|
|
||||||
// if let Some(last_operation) = operations.last_mut() {
|
|
||||||
// if last_operation.can_compose(&other) {
|
|
||||||
// let mut_operation = Arc::make_mut(last_operation);
|
|
||||||
// if mut_operation.compose(&other).is_ok() {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// If the passed-in operation can't be composed, then append it to the end.
|
// If the passed-in operation can't be composed, then append it to the end.
|
||||||
self.inner.push(other);
|
self.inner.push(other);
|
||||||
}
|
}
|
||||||
|
194
shared-lib/lib-ot/tests/node/changeset_compose_test.rs
Normal file
194
shared-lib/lib-ot/tests/node/changeset_compose_test.rs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
use crate::node::script::NodeScript::*;
|
||||||
|
use crate::node::script::NodeTest;
|
||||||
|
use lib_ot::core::{AttributeEntry, Changeset, NodeData, OperationTransform};
|
||||||
|
use lib_ot::text_delta::DeltaTextOperationBuilder;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn changeset_delta_compose_delta_test() {
|
||||||
|
// delta 1
|
||||||
|
let delta_1 = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
||||||
|
let inverted_1 = delta_1.inverted();
|
||||||
|
let mut changeset_1 = Changeset::Delta {
|
||||||
|
delta: delta_1.clone(),
|
||||||
|
inverted: inverted_1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// delta 2
|
||||||
|
let delta_2 = DeltaTextOperationBuilder::new()
|
||||||
|
.retain(delta_1.utf16_target_len)
|
||||||
|
.insert("!")
|
||||||
|
.build();
|
||||||
|
let inverted_2 = delta_2.inverted();
|
||||||
|
let changeset_2 = Changeset::Delta {
|
||||||
|
delta: delta_2,
|
||||||
|
inverted: inverted_2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// compose
|
||||||
|
changeset_1.compose(&changeset_2).unwrap();
|
||||||
|
|
||||||
|
if let Changeset::Delta { delta, inverted } = changeset_1 {
|
||||||
|
assert_eq!(delta.content().unwrap(), "Hello world!");
|
||||||
|
let new_delta = delta.compose(&inverted).unwrap();
|
||||||
|
assert_eq!(new_delta.content().unwrap(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_compose_delta_changeset_then_invert_test() {
|
||||||
|
let delta = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
||||||
|
let inverted = delta.inverted();
|
||||||
|
let changeset = Changeset::Delta {
|
||||||
|
delta: delta.clone(),
|
||||||
|
inverted: inverted.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut test = NodeTest::new();
|
||||||
|
let text_node = NodeData::new("text");
|
||||||
|
let scripts = vec![
|
||||||
|
InsertNode {
|
||||||
|
path: 0.into(),
|
||||||
|
node_data: text_node,
|
||||||
|
rev_id: 1,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset.clone(),
|
||||||
|
},
|
||||||
|
AssertNodeDelta {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: delta.clone(),
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset.inverted(),
|
||||||
|
},
|
||||||
|
AssertNodeDelta {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: delta.compose(&inverted).unwrap(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
test.run_scripts(scripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_compose_multiple_delta_changeset_then_invert_test() {
|
||||||
|
// delta 1
|
||||||
|
let delta_1 = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
||||||
|
let inverted_1 = delta_1.inverted();
|
||||||
|
let changeset_1 = Changeset::Delta {
|
||||||
|
delta: delta_1.clone(),
|
||||||
|
inverted: inverted_1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// delta 2
|
||||||
|
let delta_2 = DeltaTextOperationBuilder::new()
|
||||||
|
.retain(delta_1.utf16_target_len)
|
||||||
|
.insert("!")
|
||||||
|
.build();
|
||||||
|
let inverted_2 = delta_2.inverted();
|
||||||
|
let changeset_2 = Changeset::Delta {
|
||||||
|
delta: delta_2.clone(),
|
||||||
|
inverted: inverted_2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// delta 3
|
||||||
|
let delta_3 = DeltaTextOperationBuilder::new()
|
||||||
|
.retain(delta_2.utf16_target_len)
|
||||||
|
.insert("AppFlowy")
|
||||||
|
.build();
|
||||||
|
let inverted_3 = delta_3.inverted();
|
||||||
|
let changeset_3 = Changeset::Delta {
|
||||||
|
delta: delta_3.clone(),
|
||||||
|
inverted: inverted_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut test = NodeTest::new();
|
||||||
|
let text_node = NodeData::new("text");
|
||||||
|
let scripts = vec![
|
||||||
|
InsertNode {
|
||||||
|
path: 0.into(),
|
||||||
|
node_data: text_node,
|
||||||
|
rev_id: 1,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_1.clone(),
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_2.clone(),
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_3.clone(),
|
||||||
|
},
|
||||||
|
AssertNodeDelta {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: delta_1.compose(&delta_2).unwrap().compose(&delta_3).unwrap(),
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_3.inverted(),
|
||||||
|
},
|
||||||
|
AssertNodeDeltaContent {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#"Hello world!"#,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_2.inverted(),
|
||||||
|
},
|
||||||
|
AssertNodeDeltaContent {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#"Hello world"#,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: changeset_1.inverted(),
|
||||||
|
},
|
||||||
|
AssertNodeDeltaContent {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#""#,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
test.run_scripts(scripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn changeset_delta_compose_attributes_test() {
|
||||||
|
// delta 1
|
||||||
|
let delta = DeltaTextOperationBuilder::new().insert("Hello world").build();
|
||||||
|
let inverted = delta.inverted();
|
||||||
|
let mut delta_changeset = Changeset::Delta { delta, inverted };
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
let attribute_changeset = Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// compose
|
||||||
|
delta_changeset.compose(&attribute_changeset).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn changeset_attributes_compose_attributes_test() {
|
||||||
|
// attributes
|
||||||
|
let mut changeset_1 = Changeset::Attributes {
|
||||||
|
new: AttributeEntry::new("bold", true).into(),
|
||||||
|
old: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let changeset_2 = Changeset::Attributes {
|
||||||
|
new: AttributeEntry::new("Italic", true).into(),
|
||||||
|
old: Default::default(),
|
||||||
|
};
|
||||||
|
// compose
|
||||||
|
changeset_1.compose(&changeset_2).unwrap();
|
||||||
|
|
||||||
|
if let Changeset::Attributes { new, old: _ } = changeset_1 {
|
||||||
|
assert_eq!(new, AttributeEntry::new("Italic", true).into());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
mod changeset_compose_test;
|
||||||
mod operation_attribute_test;
|
mod operation_attribute_test;
|
||||||
|
mod operation_compose_test;
|
||||||
mod operation_delete_test;
|
mod operation_delete_test;
|
||||||
mod operation_delta_test;
|
mod operation_delta_test;
|
||||||
mod operation_insert_test;
|
mod operation_insert_test;
|
||||||
|
@ -9,7 +9,7 @@ fn operation_update_attribute_with_float_value_test() {
|
|||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
InsertNode {
|
InsertNode {
|
||||||
path: 0.into(),
|
path: 0.into(),
|
||||||
node_data: text_node.clone(),
|
node_data: text_node,
|
||||||
rev_id: 1,
|
rev_id: 1,
|
||||||
},
|
},
|
||||||
UpdateBody {
|
UpdateBody {
|
||||||
@ -34,7 +34,7 @@ fn operation_update_attribute_with_negative_value_test() {
|
|||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
InsertNode {
|
InsertNode {
|
||||||
path: 0.into(),
|
path: 0.into(),
|
||||||
node_data: text_node.clone(),
|
node_data: text_node,
|
||||||
rev_id: 1,
|
rev_id: 1,
|
||||||
},
|
},
|
||||||
UpdateBody {
|
UpdateBody {
|
||||||
|
135
shared-lib/lib-ot/tests/node/operation_compose_test.rs
Normal file
135
shared-lib/lib-ot/tests/node/operation_compose_test.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use lib_ot::core::{Changeset, NodeOperation};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_insert_compose_delta_update_test() {
|
||||||
|
let insert_operation = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let update_operation = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Delta {
|
||||||
|
delta: Default::default(),
|
||||||
|
inverted: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(insert_operation.can_compose(&update_operation))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_insert_compose_attribute_update_test() {
|
||||||
|
let insert_operation = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let update_operation = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!insert_operation.can_compose(&update_operation))
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn operation_insert_compose_update_with_diff_path_test() {
|
||||||
|
let insert_operation = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let update_operation = NodeOperation::Update {
|
||||||
|
path: 1.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!insert_operation.can_compose(&update_operation))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_insert_compose_insert_operation_test() {
|
||||||
|
let insert_operation = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!insert_operation.can_compose(&NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
}),)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_update_compose_insert_operation_test() {
|
||||||
|
let update_operation = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!update_operation.can_compose(&NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn operation_update_compose_update_test() {
|
||||||
|
let update_operation_1 = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let update_operation_2 = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(update_operation_1.can_compose(&update_operation_2));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn operation_update_compose_update_with_diff_path_test() {
|
||||||
|
let update_operation_1 = NodeOperation::Update {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let update_operation_2 = NodeOperation::Update {
|
||||||
|
path: 1.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: Default::default(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!update_operation_1.can_compose(&update_operation_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_insert_compose_insert_test() {
|
||||||
|
let insert_operation_1 = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
let insert_operation_2 = NodeOperation::Insert {
|
||||||
|
path: 0.into(),
|
||||||
|
nodes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!insert_operation_1.can_compose(&insert_operation_2));
|
||||||
|
}
|
@ -55,6 +55,10 @@ pub enum NodeScript {
|
|||||||
path: Path,
|
path: Path,
|
||||||
expected: DeltaTextOperations,
|
expected: DeltaTextOperations,
|
||||||
},
|
},
|
||||||
|
AssertNodeDeltaContent {
|
||||||
|
path: Path,
|
||||||
|
expected: &'static str,
|
||||||
|
},
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
AssertTreeJSON {
|
AssertTreeJSON {
|
||||||
expected: String,
|
expected: String,
|
||||||
@ -165,6 +169,14 @@ impl NodeTest {
|
|||||||
panic!("Node body type not match, expect Delta");
|
panic!("Node body type not match, expect Delta");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NodeScript::AssertNodeDeltaContent { path, expected } => {
|
||||||
|
let node = self.node_tree.get_node_at_path(&path).unwrap();
|
||||||
|
if let Body::Delta(delta) = node.body.clone() {
|
||||||
|
debug_assert_eq!(delta.content().unwrap(), expected);
|
||||||
|
} else {
|
||||||
|
panic!("Node body type not match, expect Delta");
|
||||||
|
}
|
||||||
|
}
|
||||||
NodeScript::AssertTreeJSON { expected } => {
|
NodeScript::AssertTreeJSON { expected } => {
|
||||||
let json = serde_json::to_string(&self.node_tree).unwrap();
|
let json = serde_json::to_string(&self.node_tree).unwrap();
|
||||||
assert_eq!(json, expected)
|
assert_eq!(json, expected)
|
||||||
|
Reference in New Issue
Block a user