1
0

diff_element.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. use dioxus::dioxus_core::Mutation::*;
  2. use dioxus::dioxus_core::{AttributeValue, ElementId, NoOpMutations};
  3. use dioxus::prelude::*;
  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::APP);
  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::APP);
  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::APP);
  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::APP);
  41. assert_eq!(
  42. vdom.render_immediate_to_vec().edits,
  43. [
  44. LoadTemplate { index: 0, id: ElementId(2,) },
  45. ReplaceWith { id: ElementId(1,), m: 1 },
  46. ]
  47. );
  48. vdom.mark_dirty(ScopeId::APP);
  49. assert_eq!(
  50. vdom.render_immediate_to_vec().edits,
  51. [
  52. LoadTemplate { index: 0, id: ElementId(1,) },
  53. ReplaceWith { id: ElementId(2,), m: 1 },
  54. ]
  55. );
  56. vdom.mark_dirty(ScopeId::APP);
  57. assert_eq!(
  58. vdom.render_immediate_to_vec().edits,
  59. [
  60. LoadTemplate { index: 0, id: ElementId(2,) },
  61. ReplaceWith { id: ElementId(1,), m: 1 },
  62. ]
  63. );
  64. vdom.mark_dirty(ScopeId::APP);
  65. assert_eq!(
  66. vdom.render_immediate_to_vec().edits,
  67. [
  68. LoadTemplate { index: 0, id: ElementId(1,) },
  69. ReplaceWith { id: ElementId(2,), m: 1 },
  70. ]
  71. );
  72. }
  73. #[test]
  74. fn attribute_diff() {
  75. fn app() -> Element {
  76. let gen = generation();
  77. // attributes have to be sorted by name
  78. let attrs = match gen % 5 {
  79. 0 => vec![Attribute::new(
  80. "a",
  81. AttributeValue::Text("hello".into()),
  82. None,
  83. false,
  84. )],
  85. 1 => vec![
  86. Attribute::new("a", AttributeValue::Text("hello".into()), None, false),
  87. Attribute::new("b", AttributeValue::Text("hello".into()), None, false),
  88. Attribute::new("c", AttributeValue::Text("hello".into()), None, false),
  89. ],
  90. 2 => vec![
  91. Attribute::new("c", AttributeValue::Text("hello".into()), None, false),
  92. Attribute::new("d", AttributeValue::Text("hello".into()), None, false),
  93. Attribute::new("e", AttributeValue::Text("hello".into()), None, false),
  94. ],
  95. 3 => vec![Attribute::new(
  96. "d",
  97. AttributeValue::Text("world".into()),
  98. None,
  99. false,
  100. )],
  101. _ => unreachable!(),
  102. };
  103. rsx!(
  104. div {
  105. ..attrs,
  106. "hello"
  107. }
  108. )
  109. }
  110. let mut vdom = VirtualDom::new(app);
  111. vdom.rebuild(&mut NoOpMutations);
  112. vdom.mark_dirty(ScopeId::APP);
  113. assert_eq!(
  114. vdom.render_immediate_to_vec().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::APP);
  131. assert_eq!(
  132. vdom.render_immediate_to_vec().edits,
  133. [
  134. SetAttribute { name: "a", value: AttributeValue::None, id: ElementId(1,), ns: None },
  135. SetAttribute { name: "b", value: AttributeValue::None, id: ElementId(1,), ns: None },
  136. SetAttribute {
  137. name: "d",
  138. value: AttributeValue::Text("hello".into()),
  139. id: ElementId(1,),
  140. ns: None,
  141. },
  142. SetAttribute {
  143. name: "e",
  144. value: AttributeValue::Text("hello".into()),
  145. id: ElementId(1,),
  146. ns: None,
  147. },
  148. ]
  149. );
  150. vdom.mark_dirty(ScopeId::APP);
  151. assert_eq!(
  152. vdom.render_immediate_to_vec().edits,
  153. [
  154. SetAttribute { name: "c", value: AttributeValue::None, id: ElementId(1,), ns: None },
  155. SetAttribute {
  156. name: "d",
  157. value: AttributeValue::Text("world".into()),
  158. id: ElementId(1,),
  159. ns: None,
  160. },
  161. SetAttribute { name: "e", value: AttributeValue::None, id: ElementId(1,), ns: None },
  162. ]
  163. );
  164. }
  165. #[test]
  166. fn diff_empty() {
  167. fn app() -> Element {
  168. match generation() % 2 {
  169. 0 => rsx! { div { "hello" } },
  170. 1 => rsx! {},
  171. _ => unreachable!(),
  172. }
  173. }
  174. let mut vdom = VirtualDom::new(app);
  175. vdom.rebuild(&mut NoOpMutations);
  176. vdom.mark_dirty(ScopeId::APP);
  177. let edits = vdom.render_immediate_to_vec().edits;
  178. assert_eq!(
  179. edits,
  180. [
  181. CreatePlaceholder { id: ElementId(2,) },
  182. ReplaceWith { id: ElementId(1,), m: 1 },
  183. ]
  184. )
  185. }