use mt_dom::{diff::*, patch::*, *};
pub type MyNode =
Node<&'static str, &'static str, &'static str, &'static str, &'static str>;
#[test]
fn keyed_no_changed() {
let old: MyNode = element(
"div",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let new: MyNode = element(
"div",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let diff = diff_with_key(&old, &new, &"key");
assert_eq!(diff, vec![]);
}
#[test]
fn key_1_removed_at_start() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "2")], vec![])],
);
let diff = diff_with_key(&old, &new, &"key");
assert_eq!(
diff,
vec![Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0]))]
);
}
#[test]
fn non_unique_keys_matched_at_old() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "2")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "2")], vec![])],
);
let diff = diff_with_key(&old, &new, &"key");
assert_eq!(
diff,
vec![Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 1]))]
);
}
#[test]
fn key_2_removed_at_the_end() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let diff = diff_with_key(&old, &new, &"key");
assert_eq!(
diff,
vec![Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 1]),)]
);
}
#[test]
fn key_2_removed_at_the_middle() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
element("div", vec![attr("key", "3")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "3")], vec![]),
],
);
let diff = diff_with_key(&old, &new, &"key");
assert_eq!(
diff,
vec![Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 1]))]
);
}
#[test]
fn there_are_2_exact_same_keys_in_the_old() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("0")]),
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "3")], vec![leaf("2")]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "3")], vec![leaf("2")]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::replace_leaf(TreePath::new(vec![0, 0, 0]), &"0", &"1"),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 1]))
]
);
}
#[test]
fn there_are_2_exact_same_keys_in_the_new() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("0")]),
element("div", vec![attr("key", "3")], vec![leaf("2")]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "3")], vec![leaf("2")]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::replace_leaf(TreePath::new(vec![0, 0, 0]), &"0", &"1"),
Patch::insert_node(
Some(&"main"),
TreePath::new(vec![0, 1]),
&element("div", vec![attr("key", "1")], vec![leaf("1")])
),
]
);
}
#[test]
fn there_are_2_exact_same_keys_in_both_old_and_new() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("0")]), element("div", vec![attr("key", "3")], vec![leaf("1")]),
element("div", vec![attr("key", "3")], vec![leaf("2")]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("1")]), element("div", vec![attr("key", "1")], vec![leaf("2")]),
element("div", vec![attr("key", "3")], vec![leaf("3")]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::replace_leaf(TreePath::new(vec![0, 0, 0]), &"0", &"1"),
Patch::replace_leaf(TreePath::new(vec![0, 1, 0]), &"1", &"3"),
Patch::insert_node(
Some(&"main"),
TreePath::new(vec![0, 1]),
&element("div", vec![attr("key", "1")], vec![leaf("2")])
),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 2])),
]
);
}
#[test]
fn key_2_inserted_at_start() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "2")], vec![]),
element("div", vec![attr("key", "1")], vec![]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![Patch::insert_node(
Some(&"main"),
TreePath::new(vec![0, 0]),
&element("div", vec![attr("key", "2")], vec![])
)]
);
}
#[test]
fn keyed_element_not_reused() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "2")], vec![])],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![Patch::replace_node(
Some(&"div"),
TreePath::new(vec![0, 0]),
&element("div", vec![attr("key", "2")], vec![])
)]
);
}
#[test]
fn key_2_inserted_at_the_end() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element("div", vec![attr("key", "1")], vec![])],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![Patch::append_children(
&"main",
TreePath::new(vec![0]),
vec![&element("div", vec![attr("key", "2")], vec![])]
)]
);
}
#[test]
fn test_append_at_sub_level() {
let old: MyNode = element(
"div",
vec![attr("id", "some-id"), attr("class", "some-class")],
vec![element(
"main",
vec![],
vec![element("div", vec![attr("key", "1")], vec![leaf("1")])],
)],
);
let new: MyNode = element(
"div",
vec![attr("id", "some-id"), attr("class", "some-class")],
vec![element(
"main",
vec![],
vec![
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "2")], vec![leaf("2")]),
element("div", vec![attr("key", "3")], vec![leaf("3")]),
],
)],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::append_children(
&"main",
TreePath::new(vec![0, 0]),
vec![&element("div", vec![attr("key", "2")], vec![leaf("2")]),],
),
Patch::append_children(
&"main",
TreePath::new(vec![0, 0]),
vec![&element("div", vec![attr("key", "3")], vec![leaf("3")])],
)
]
)
}
#[test]
fn key_2_inserted_in_the_middle() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "3")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
element("div", vec![attr("key", "3")], vec![]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![Patch::insert_node(
Some(&"main"),
TreePath::new(vec![0, 1]),
&element("div", vec![attr("key", "2")], vec![])
)]
);
}
#[test]
fn key1_removed_at_start_then_key2_has_additional_attributes() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"div",
vec![attr("key", "2"), attr("class", "some-class")],
vec![],
)],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::add_attributes(
&"div",
TreePath::new(vec![0, 1]),
vec![&attr("class", "some-class")]
),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0]),),
]
);
}
#[test]
fn deep_nested_key1_removed_at_start_then_key2_has_additional_attributes() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
)],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![element(
"div",
vec![attr("key", "2"), attr("class", "some-class")],
vec![],
)],
)],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::add_attributes(
&"div",
TreePath::new(vec![0, 0, 1]),
vec![&attr("class", "some-class")]
),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0, 0]),),
]
);
}
#[test]
fn deep_nested_more_children_key0_and_key1_removed_at_start_then_key2_has_additional_attributes(
) {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![
element("div", vec![attr("key", "0")], vec![]),
element("div", vec![attr("key", "1")], vec![]),
element("div", vec![attr("key", "2")], vec![]),
],
)],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![element(
"div",
vec![attr("key", "2"), attr("class", "some-class")],
vec![],
)],
)],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::add_attributes(
&"div",
TreePath::new(vec![0, 0, 2]),
vec![&attr("class", "some-class")]
),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0, 0]),),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0, 1]),),
]
);
}
#[test]
fn deep_nested_keyed_with_non_keyed_children() {
let old: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![
element("div", vec![attr("key", "0")], vec![]),
element("div", vec![attr("key", "1")], vec![]),
element(
"div",
vec![attr("key", "2")],
vec![
element("p", vec![], vec![leaf("paragraph1")]),
element(
"a",
vec![attr("href", "#link1")],
vec![leaf("Click here")],
),
],
),
],
)],
);
let new: MyNode = element(
"main",
vec![attr("class", "container")],
vec![element(
"article",
vec![],
vec![element(
"div",
vec![attr("key", "2"), attr("class", "some-class")],
vec![
element(
"p",
vec![],
vec![leaf("paragraph1, with added content")],
),
element(
"a",
vec![attr("href", "#link1")],
vec![leaf("Click here to continue")],
),
],
)],
)],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![
Patch::add_attributes(
&"div",
TreePath::new(vec![0, 0, 2]),
vec![&attr("class", "some-class")]
),
Patch::replace_leaf(
TreePath::new(vec![0, 0, 2, 0, 0]),
&"paragraph1",
&"paragraph1, with added content"
),
Patch::replace_leaf(
TreePath::new(vec![0, 0, 2, 1, 0]),
&"Click here",
&"Click here to continue"
),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0, 0]),),
Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0, 1]),),
]
);
}
#[test]
fn text_changed_in_keyed_elements() {
let old: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![element(
"section",
vec![attr("class", "todo")],
vec![
element("article", vec![attr("key", "1")], vec![leaf("item1")]),
element("article", vec![attr("key", "2")], vec![leaf("item2")]),
element("article", vec![attr("key", "3")], vec![leaf("item3")]),
],
)],
);
let update1: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![element(
"section",
vec![attr("class", "todo")],
vec![
element("article", vec![attr("key", "2")], vec![leaf("item2")]),
element(
"article",
vec![attr("key", "3")],
vec![leaf("item3 with changes")],
),
],
)],
);
let patch = diff_with_key(&old, &update1, &"key");
dbg!(&patch);
assert_eq!(
patch,
vec![
Patch::replace_leaf(
TreePath::new(vec![0, 0, 2, 0]),
&"item3",
&"item3 with changes"
),
Patch::remove_node(Some(&"article"), TreePath::new(vec![0, 0, 0]),)
]
);
}
#[test]
fn text_changed_in_mixed_keyed_and_non_keyed_elements() {
let old: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![
element(
"section",
vec![attr("class", "todo")],
vec![
element(
"article",
vec![attr("key", "1")],
vec![leaf("item1")],
),
element(
"article",
vec![attr("key", "2")],
vec![leaf("item2")],
),
element(
"article",
vec![attr("key", "3")],
vec![leaf("item3")],
),
],
),
element("footer", vec![], vec![leaf("3 items left")]),
],
);
let update1: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![
element(
"section",
vec![attr("class", "todo")],
vec![
element(
"article",
vec![attr("key", "2")],
vec![leaf("item2")],
),
element(
"article",
vec![attr("key", "3")],
vec![leaf("item3 with changes")],
),
],
),
element("footer", vec![], vec![leaf("2 items left")]),
],
);
let patch = diff_with_key(&old, &update1, &"key");
dbg!(&patch);
assert_eq!(
patch,
vec![
Patch::replace_leaf(
TreePath::new(vec![0, 0, 2, 0]),
&"item3",
&"item3 with changes"
),
Patch::remove_node(Some(&"article"), TreePath::new(vec![0, 0, 0]),),
Patch::replace_leaf(
TreePath::new(vec![0, 1, 0]),
&"3 items left",
&"2 items left"
),
]
);
}
#[test]
fn test12() {
let old: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![
element("header", vec![], vec![leaf("Items:")]),
element(
"section",
vec![attr("class", "todo")],
vec![
element(
"article",
vec![attr("key", "1")],
vec![leaf("item1")],
),
element(
"article",
vec![attr("key", "2")],
vec![leaf("item2")],
),
element(
"article",
vec![attr("key", "3")],
vec![leaf("item3")],
),
],
),
element("footer", vec![], vec![leaf("3 items left")]),
],
);
let update1: MyNode = element(
"main",
vec![attr("class", "test4")],
vec![
element("header", vec![], vec![leaf("Items:")]),
element(
"section",
vec![attr("class", "todo")],
vec![
element(
"article",
vec![attr("key", "2")],
vec![leaf("item2")],
),
element(
"article",
vec![attr("key", "3")],
vec![leaf("item3 with changes")],
),
],
),
element("footer", vec![], vec![leaf("2 items left")]),
],
);
let patch = diff_with_key(&old, &update1, &"key");
dbg!(&patch);
assert_eq!(
patch,
vec![
Patch::replace_leaf(
TreePath::new(vec![0, 1, 2, 0]),
&"item3",
&"item3 with changes"
),
Patch::remove_node(Some(&"article"), TreePath::new(vec![0, 1, 0]),),
Patch::replace_leaf(
TreePath::new(vec![0, 2, 0]),
&"3 items left",
&"2 items left"
),
]
);
}
#[test]
fn remove_first() {
let old: MyNode = element(
"div",
vec![attr("id", "some-id"), attr("class", "some-class")],
vec![
element("div", vec![attr("key", "1")], vec![leaf("1")]),
element("div", vec![attr("key", "2")], vec![leaf("2")]),
element("div", vec![attr("key", "3")], vec![leaf("3")]),
],
);
let new: MyNode = element(
"div",
vec![attr("id", "some-id"), attr("class", "some-class")],
vec![
element("div", vec![attr("key", "2")], vec![leaf("2")]),
element("div", vec![attr("key", "3")], vec![leaf("3")]),
],
);
let diff = diff_with_key(&old, &new, &"key");
dbg!(&diff);
assert_eq!(
diff,
vec![Patch::remove_node(Some(&"div"), TreePath::new(vec![0, 0]),)]
)
}