123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #![allow(unused, non_upper_case_globals)]
- //! Tests for the lifecycle of components.
- use dioxus::prelude::*;
- use dioxus_core as dioxus;
- use dioxus_core::DomEdit::*;
- use dioxus_core::ScopeId;
- use dioxus_core_macro::*;
- use dioxus_hooks::*;
- use dioxus_html as dioxus_elements;
- use std::sync::{Arc, Mutex};
- mod test_logging;
- const IS_LOGGING_ENABLED: bool = true;
- type Shared<T> = Arc<Mutex<T>>;
- #[test]
- fn manual_diffing() {
- test_logging::set_up_logging(IS_LOGGING_ENABLED);
- struct AppProps {
- value: Shared<&'static str>,
- }
- static App: FC<AppProps> = |cx, props| {
- let val = props.value.lock().unwrap();
- cx.render(rsx! { div { "{val}" } })
- };
- let value = Arc::new(Mutex::new("Hello"));
- let mut dom = VirtualDom::new_with_props(
- App,
- AppProps {
- value: value.clone(),
- },
- );
- let _ = dom.rebuild();
- *value.lock().unwrap() = "goodbye";
- let edits = dom.rebuild();
- log::debug!("edits: {:?}", edits);
- }
- #[test]
- fn events_generate() {
- static App: FC<()> = |cx, _| {
- let mut count = use_state(cx, || 0);
- let inner = match *count {
- 0 => {
- rsx! {
- div {
- onclick: move |_| count += 1,
- div {
- "nested"
- }
- "Click me!"
- }
- }
- }
- _ => todo!(),
- };
- cx.render(inner)
- };
- let mut dom = VirtualDom::new(App);
- let mut channel = dom.get_scheduler_channel();
- assert!(dom.has_any_work());
- let edits = dom.work_with_deadline(|| false);
- assert_eq!(
- edits[0].edits,
- [
- CreateElement {
- tag: "div",
- root: 0,
- },
- NewEventListener {
- event_name: "click",
- scope: ScopeId(0),
- root: 0,
- },
- CreateElement {
- tag: "div",
- root: 1,
- },
- CreateTextNode {
- text: "nested",
- root: 2,
- },
- AppendChildren { many: 1 },
- CreateTextNode {
- text: "Click me!",
- root: 3,
- },
- AppendChildren { many: 2 },
- ]
- )
- }
- #[test]
- fn components_generate() {
- static App: FC<()> = |cx, _| {
- let mut render_phase = use_state(cx, || 0);
- render_phase += 1;
- cx.render(match *render_phase {
- 0 => rsx!("Text0"),
- 1 => rsx!(div {}),
- 2 => rsx!("Text2"),
- 3 => rsx!(Child {}),
- 4 => rsx!({ None as Option<()> }),
- 5 => rsx!("text 3"),
- 6 => rsx!({ (0..2).map(|f| rsx!("text {f}")) }),
- 7 => rsx!(Child {}),
- _ => todo!(),
- })
- };
- static Child: FC<()> = |cx, _| {
- println!("running child");
- cx.render(rsx! {
- h1 {}
- })
- };
- let mut dom = VirtualDom::new(App);
- let edits = dom.rebuild();
- assert_eq!(
- edits.edits,
- [
- CreateTextNode {
- text: "Text0",
- root: 0,
- },
- AppendChildren { many: 1 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateElement {
- tag: "div",
- root: 1,
- },
- ReplaceWith { root: 0, m: 1 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateTextNode {
- text: "Text2",
- root: 2,
- },
- ReplaceWith { root: 1, m: 1 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateElement { tag: "h1", root: 3 },
- ReplaceWith { root: 2, m: 1 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [CreatePlaceholder { root: 4 }, ReplaceWith { root: 3, m: 1 },]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateTextNode {
- text: "text 3",
- root: 5,
- },
- ReplaceWith { root: 4, m: 1 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateTextNode {
- text: "text 0",
- root: 6,
- },
- CreateTextNode {
- text: "text 1",
- root: 7,
- },
- ReplaceWith { root: 5, m: 2 },
- ]
- );
- let edits = dom.hard_diff(&ScopeId(0)).unwrap();
- assert_eq!(
- edits.edits,
- [
- CreateElement { tag: "h1", root: 8 },
- ReplaceWith { root: 6, m: 1 },
- Remove { root: 7 },
- ]
- );
- }
- #[test]
- fn component_swap() {
- // simple_logger::init();
- static App: FC<()> = |cx, _| {
- let mut render_phase = use_state(cx, || 0);
- render_phase += 1;
- cx.render(match *render_phase {
- 0 => rsx!(
- div {
- NavBar {}
- Dashboard {}
- }
- ),
- 1 => rsx!(
- div {
- NavBar {}
- Results {}
- }
- ),
- 2 => rsx!(
- div {
- NavBar {}
- Dashboard {}
- }
- ),
- 3 => rsx!(
- div {
- NavBar {}
- Results {}
- }
- ),
- 4 => rsx!(
- div {
- NavBar {}
- Dashboard {}
- }
- ),
- _ => rsx!("blah"),
- })
- };
- static NavBar: FC<()> = |cx, _| {
- println!("running navbar");
- cx.render(rsx! {
- h1 {
- "NavBar"
- {(0..3).map(|f| rsx!(NavLink {}))}
- }
- })
- };
- static NavLink: FC<()> = |cx, _| {
- println!("running navlink");
- cx.render(rsx! {
- h1 {
- "NavLink"
- }
- })
- };
- static Dashboard: FC<()> = |cx, _| {
- println!("running dashboard");
- cx.render(rsx! {
- div {
- "dashboard"
- }
- })
- };
- static Results: FC<()> = |cx, _| {
- println!("running results");
- cx.render(rsx! {
- div {
- "results"
- }
- })
- };
- let mut dom = VirtualDom::new(App);
- let edits = dom.rebuild();
- dbg!(&edits);
- let edits = dom.work_with_deadline(|| false);
- dbg!(&edits);
- let edits = dom.work_with_deadline(|| false);
- dbg!(&edits);
- let edits = dom.work_with_deadline(|| false);
- dbg!(&edits);
- let edits = dom.work_with_deadline(|| false);
- dbg!(&edits);
- }
|