lifecycle.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #![allow(unused, non_upper_case_globals)]
  2. #![allow(non_snake_case)]
  3. //! Tests for the lifecycle of components.
  4. use dioxus::core::{ElementId, Mutation::*};
  5. use dioxus::prelude::*;
  6. use dioxus_html::SerializedHtmlEventConverter;
  7. use std::rc::Rc;
  8. use std::sync::{Arc, Mutex};
  9. type Shared<T> = Arc<Mutex<T>>;
  10. #[test]
  11. fn manual_diffing() {
  12. struct AppProps {
  13. value: Shared<&'static str>,
  14. }
  15. fn app(cx: Scope<AppProps>) -> Element {
  16. let val = cx.props.value.lock().unwrap();
  17. cx.render(rsx! { div { "{val}" } })
  18. };
  19. let value = Arc::new(Mutex::new("Hello"));
  20. let mut dom = VirtualDom::new_with_props(app, AppProps { value: value.clone() });
  21. let _ = dom.rebuild();
  22. *value.lock().unwrap() = "goodbye";
  23. assert_eq!(
  24. dom.rebuild().santize().edits,
  25. [
  26. LoadTemplate { name: "template", index: 0, id: ElementId(3) },
  27. HydrateText { path: &[0], value: "goodbye", id: ElementId(4) },
  28. AppendChildren { m: 1, id: ElementId(0) }
  29. ]
  30. );
  31. }
  32. #[test]
  33. fn events_generate() {
  34. set_event_converter(Box::new(SerializedHtmlEventConverter));
  35. fn app(cx: Scope) -> Element {
  36. let count = cx.use_hook(|| 0);
  37. match *count {
  38. 0 => cx.render(rsx! {
  39. div { onclick: move |_| *count += 1,
  40. div { "nested" }
  41. "Click me!"
  42. }
  43. }),
  44. _ => cx.render(rsx!(())),
  45. }
  46. };
  47. let mut dom = VirtualDom::new(app);
  48. _ = dom.rebuild();
  49. dom.handle_event(
  50. "click",
  51. Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
  52. ElementId(1),
  53. true,
  54. );
  55. dom.mark_dirty(ScopeId::ROOT);
  56. let edits = dom.render_immediate();
  57. assert_eq!(
  58. edits.edits,
  59. [
  60. CreatePlaceholder { id: ElementId(2) },
  61. ReplaceWith { id: ElementId(1), m: 1 }
  62. ]
  63. )
  64. }
  65. // #[test]
  66. // fn components_generate() {
  67. // fn app(cx: Scope) -> Element {
  68. // let render_phase = cx.use_hook(|| 0);
  69. // *render_phase += 1;
  70. // cx.render(match *render_phase {
  71. // 1 => rsx_without_templates!("Text0"),
  72. // 2 => rsx_without_templates!(div {}),
  73. // 3 => rsx_without_templates!("Text2"),
  74. // 4 => rsx_without_templates!(Child {}),
  75. // 5 => rsx_without_templates!({ None as Option<()> }),
  76. // 6 => rsx_without_templates!("text 3"),
  77. // 7 => rsx_without_templates!({ (0..2).map(|f| rsx_without_templates!("text {f}")) }),
  78. // 8 => rsx_without_templates!(Child {}),
  79. // _ => todo!(),
  80. // })
  81. // };
  82. // fn Child(cx: Scope) -> Element {
  83. // println!("Running child");
  84. // cx.render(rsx_without_templates! {
  85. // h1 {}
  86. // })
  87. // }
  88. // let mut dom = VirtualDom::new(app);
  89. // let edits = dom.rebuild();
  90. // assert_eq!(
  91. // edits.edits,
  92. // [
  93. // CreateTextNode { root: Some(1), text: "Text0" },
  94. // AppendChildren { root: Some(0), children: vec![1] }
  95. // ]
  96. // );
  97. // assert_eq!(
  98. // dom.hard_diff(ScopeId::ROOT).edits,
  99. // [
  100. // CreateElement { root: Some(2), tag: "div", children: 0 },
  101. // ReplaceWith { root: Some(1), nodes: vec![2] }
  102. // ]
  103. // );
  104. // assert_eq!(
  105. // dom.hard_diff(ScopeId::ROOT).edits,
  106. // [
  107. // CreateTextNode { root: Some(1), text: "Text2" },
  108. // ReplaceWith { root: Some(2), nodes: vec![1] }
  109. // ]
  110. // );
  111. // // child {}
  112. // assert_eq!(
  113. // dom.hard_diff(ScopeId::ROOT).edits,
  114. // [
  115. // CreateElement { root: Some(2), tag: "h1", children: 0 },
  116. // ReplaceWith { root: Some(1), nodes: vec![2] }
  117. // ]
  118. // );
  119. // // placeholder
  120. // assert_eq!(
  121. // dom.hard_diff(ScopeId::ROOT).edits,
  122. // [
  123. // CreatePlaceholder { root: Some(1) },
  124. // ReplaceWith { root: Some(2), nodes: vec![1] }
  125. // ]
  126. // );
  127. // assert_eq!(
  128. // dom.hard_diff(ScopeId::ROOT).edits,
  129. // [
  130. // CreateTextNode { root: Some(2), text: "text 3" },
  131. // ReplaceWith { root: Some(1), nodes: vec![2] }
  132. // ]
  133. // );
  134. // assert_eq!(
  135. // dom.hard_diff(ScopeId::ROOT).edits,
  136. // [
  137. // CreateTextNode { text: "text 0", root: Some(1) },
  138. // CreateTextNode { text: "text 1", root: Some(3) },
  139. // ReplaceWith { root: Some(2), nodes: vec![1, 3] },
  140. // ]
  141. // );
  142. // assert_eq!(
  143. // dom.hard_diff(ScopeId::ROOT).edits,
  144. // [
  145. // CreateElement { tag: "h1", root: Some(2), children: 0 },
  146. // ReplaceWith { root: Some(1), nodes: vec![2] },
  147. // Remove { root: Some(3) },
  148. // ]
  149. // );
  150. // }