diff_element.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. use dioxus::dioxus_core::Mutation::*;
  2. use dioxus::prelude::*;
  3. use dioxus_core::{AttributeValue, ElementId, NoOpMutations};
  4. #[test]
  5. fn text_diff() {
  6. fn app() -> Element {
  7. let gen = generation();
  8. rsx!( h1 { "hello {gen}" } )
  9. }
  10. let mut vdom = VirtualDom::new(app);
  11. vdom.rebuild(&mut NoOpMutations);
  12. vdom.mark_dirty(ScopeId::ROOT);
  13. assert_eq!(
  14. vdom.render_immediate_to_vec().edits,
  15. [SetText { value: "hello 1".to_string(), id: ElementId(2) }]
  16. );
  17. vdom.mark_dirty(ScopeId::ROOT);
  18. assert_eq!(
  19. vdom.render_immediate_to_vec().edits,
  20. [SetText { value: "hello 2".to_string(), id: ElementId(2) }]
  21. );
  22. vdom.mark_dirty(ScopeId::ROOT);
  23. assert_eq!(
  24. vdom.render_immediate_to_vec().edits,
  25. [SetText { value: "hello 3".to_string(), id: ElementId(2) }]
  26. );
  27. }
  28. #[test]
  29. fn element_swap() {
  30. fn app() -> Element {
  31. let gen = generation();
  32. match gen % 2 {
  33. 0 => rsx!( h1 { "hello 1" } ),
  34. 1 => rsx!( h2 { "hello 2" } ),
  35. _ => unreachable!(),
  36. }
  37. }
  38. let mut vdom = VirtualDom::new(app);
  39. vdom.rebuild(&mut NoOpMutations);
  40. vdom.mark_dirty(ScopeId::ROOT);
  41. assert_eq!(
  42. vdom.render_immediate_to_vec().santize().edits,
  43. [
  44. LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
  45. ReplaceWith { id: ElementId(1,), m: 1 },
  46. ]
  47. );
  48. vdom.mark_dirty(ScopeId::ROOT);
  49. assert_eq!(
  50. vdom.render_immediate_to_vec().santize().edits,
  51. [
  52. LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
  53. ReplaceWith { id: ElementId(2,), m: 1 },
  54. ]
  55. );
  56. vdom.mark_dirty(ScopeId::ROOT);
  57. assert_eq!(
  58. vdom.render_immediate_to_vec().santize().edits,
  59. [
  60. LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
  61. ReplaceWith { id: ElementId(1,), m: 1 },
  62. ]
  63. );
  64. vdom.mark_dirty(ScopeId::ROOT);
  65. assert_eq!(
  66. vdom.render_immediate_to_vec().santize().edits,
  67. [
  68. LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
  69. ReplaceWith { id: ElementId(2,), m: 1 },
  70. ]
  71. );
  72. }
  73. #[test]
  74. fn attribute_diff() {
  75. fn app(cx: Scope) -> Element {
  76. let gen = cx.generation();
  77. // attributes have to be sorted by name
  78. let attrs = match gen % 5 {
  79. 0 => cx.bump().alloc([Attribute::new(
  80. "a",
  81. AttributeValue::Text("hello"),
  82. None,
  83. false,
  84. )]) as &[Attribute],
  85. 1 => cx.bump().alloc([
  86. Attribute::new("a", AttributeValue::Text("hello"), None, false),
  87. Attribute::new("b", AttributeValue::Text("hello"), None, false),
  88. Attribute::new("c", AttributeValue::Text("hello"), None, false),
  89. ]) as &[Attribute],
  90. 2 => cx.bump().alloc([
  91. Attribute::new("c", AttributeValue::Text("hello"), None, false),
  92. Attribute::new("d", AttributeValue::Text("hello"), None, false),
  93. Attribute::new("e", AttributeValue::Text("hello"), None, false),
  94. ]) as &[Attribute],
  95. 3 => cx.bump().alloc([Attribute::new(
  96. "d",
  97. AttributeValue::Text("world"),
  98. None,
  99. false,
  100. )]) as &[Attribute],
  101. _ => unreachable!(),
  102. };
  103. cx.render(rsx!(
  104. div {
  105. ..*attrs,
  106. "hello"
  107. }
  108. ))
  109. }
  110. let mut vdom = VirtualDom::new(app);
  111. _ = vdom.rebuild();
  112. vdom.mark_dirty(ScopeId::ROOT);
  113. assert_eq!(
  114. vdom.render_immediate().santize().edits,
  115. [
  116. SetAttribute {
  117. name: "b",
  118. value: (&AttributeValue::Text("hello",)).into(),
  119. id: ElementId(1,),
  120. ns: None,
  121. },
  122. SetAttribute {
  123. name: "c",
  124. value: (&AttributeValue::Text("hello",)).into(),
  125. id: ElementId(1,),
  126. ns: None,
  127. },
  128. ]
  129. );
  130. vdom.mark_dirty(ScopeId::ROOT);
  131. assert_eq!(
  132. vdom.render_immediate().santize().edits,
  133. [
  134. SetAttribute {
  135. name: "a",
  136. value: (&AttributeValue::None).into(),
  137. id: ElementId(1,),
  138. ns: None,
  139. },
  140. SetAttribute {
  141. name: "b",
  142. value: (&AttributeValue::None).into(),
  143. id: ElementId(1,),
  144. ns: None,
  145. },
  146. SetAttribute {
  147. name: "d",
  148. value: (&AttributeValue::Text("hello",)).into(),
  149. id: ElementId(1,),
  150. ns: None,
  151. },
  152. SetAttribute {
  153. name: "e",
  154. value: (&AttributeValue::Text("hello",)).into(),
  155. id: ElementId(1,),
  156. ns: None,
  157. },
  158. ]
  159. );
  160. vdom.mark_dirty(ScopeId::ROOT);
  161. assert_eq!(
  162. vdom.render_immediate().santize().edits,
  163. [
  164. SetAttribute {
  165. name: "c",
  166. value: (&AttributeValue::None).into(),
  167. id: ElementId(1,),
  168. ns: None,
  169. },
  170. SetAttribute {
  171. name: "d",
  172. value: (&AttributeValue::Text("world",)).into(),
  173. id: ElementId(1,),
  174. ns: None,
  175. },
  176. SetAttribute {
  177. name: "e",
  178. value: (&AttributeValue::None).into(),
  179. id: ElementId(1,),
  180. ns: None,
  181. },
  182. ]
  183. );
  184. }