dioxus/packages/core/tests/lifecycle.rs

265 lines
6.9 KiB
Rust
Raw Normal View History

2021-10-22 05:16:39 +00:00
#![allow(unused, non_upper_case_globals)]
2022-02-11 02:00:15 +00:00
#![allow(non_snake_case)]
2021-10-22 05:16:39 +00:00
//! Tests for the lifecycle of components.
2022-11-27 07:06:04 +00:00
use dioxus::core::{ElementId, Mutation::*};
use dioxus::prelude::*;
2021-10-01 06:07:12 +00:00
use std::sync::{Arc, Mutex};
2021-09-25 01:46:23 +00:00
2021-10-01 06:07:12 +00:00
type Shared<T> = Arc<Mutex<T>>;
#[test]
fn manual_diffing() {
struct AppProps {
value: Shared<&'static str>,
}
2021-12-15 02:46:19 +00:00
static App: Component<AppProps> = |cx| {
let val = cx.props.value.lock().unwrap();
cx.render(rsx_without_templates! { div { "{val}" } })
};
2021-10-01 06:07:12 +00:00
let value = Arc::new(Mutex::new("Hello"));
let mut dom = VirtualDom::new_with_props(App, AppProps { value: value.clone() });
let _ = dom.rebuild();
2021-10-01 06:07:12 +00:00
*value.lock().unwrap() = "goodbye";
let edits = dom.rebuild();
println!("edits: {:?}", edits);
}
2021-11-11 16:49:07 +00:00
#[test]
fn events_generate() {
fn app(cx: Scope) -> Element {
let count = cx.use_hook(|| 0);
2021-11-11 16:49:07 +00:00
let inner = match *count {
0 => {
rsx_without_templates! {
2021-11-11 16:49:07 +00:00
div {
2021-12-21 03:33:13 +00:00
onclick: move |_| *count += 1,
2021-11-11 16:49:07 +00:00
div {
"nested"
}
"Click me!"
}
}
}
_ => todo!(),
};
cx.render(inner)
};
let mut dom = VirtualDom::new(app);
2021-11-11 16:49:07 +00:00
let mut channel = dom.get_scheduler_channel();
2021-12-13 00:47:13 +00:00
assert!(dom.has_work());
2021-11-11 16:49:07 +00:00
2021-11-12 02:34:20 +00:00
let edits = dom.rebuild();
2021-11-11 16:49:07 +00:00
assert_eq!(
2021-11-12 02:34:20 +00:00
edits.edits,
2021-11-11 16:49:07 +00:00
[
CreateElement { root: Some(1), tag: "div", children: 0 },
NewEventListener { event_name: "click", scope: ScopeId(0), root: Some(1) },
CreateElement { root: Some(2), tag: "div", children: 0 },
CreateTextNode { root: Some(3), text: "nested" },
AppendChildren { root: Some(2), children: vec![3] },
CreateTextNode { root: Some(4), text: "Click me!" },
AppendChildren { root: Some(1), children: vec![2, 4] },
AppendChildren { root: Some(0), children: vec![1] }
2021-11-11 16:49:07 +00:00
]
)
}
#[test]
fn components_generate() {
fn app(cx: Scope) -> Element {
let render_phase = cx.use_hook(|| 0);
2021-12-21 03:33:13 +00:00
*render_phase += 1;
2021-11-11 16:49:07 +00:00
cx.render(match *render_phase {
1 => rsx_without_templates!("Text0"),
2 => rsx_without_templates!(div {}),
3 => rsx_without_templates!("Text2"),
4 => rsx_without_templates!(Child {}),
5 => rsx_without_templates!({ None as Option<()> }),
6 => rsx_without_templates!("text 3"),
7 => rsx_without_templates!({ (0..2).map(|f| rsx_without_templates!("text {f}")) }),
8 => rsx_without_templates!(Child {}),
2021-11-11 16:49:07 +00:00
_ => todo!(),
})
};
fn Child(cx: Scope) -> Element {
println!("Running child");
cx.render(rsx_without_templates! {
2021-11-11 16:49:07 +00:00
h1 {}
})
}
2021-11-11 16:49:07 +00:00
let mut dom = VirtualDom::new(app);
2021-11-11 16:49:07 +00:00
let edits = dom.rebuild();
assert_eq!(
edits.edits,
[
CreateTextNode { root: Some(1), text: "Text0" },
AppendChildren { root: Some(0), children: vec![1] }
2021-11-11 16:49:07 +00:00
]
);
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateElement { root: Some(2), tag: "div", children: 0 },
ReplaceWith { root: Some(1), nodes: vec![2] }
2021-11-11 16:49:07 +00:00
]
);
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateTextNode { root: Some(1), text: "Text2" },
ReplaceWith { root: Some(2), nodes: vec![1] }
2021-11-11 16:49:07 +00:00
]
);
// child {}
2021-11-11 16:49:07 +00:00
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateElement { root: Some(2), tag: "h1", children: 0 },
ReplaceWith { root: Some(1), nodes: vec![2] }
2021-11-11 16:49:07 +00:00
]
);
// placeholder
2021-11-11 16:49:07 +00:00
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
[
CreatePlaceholder { root: Some(1) },
ReplaceWith { root: Some(2), nodes: vec![1] }
]
2021-11-11 16:49:07 +00:00
);
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateTextNode { root: Some(2), text: "text 3" },
ReplaceWith { root: Some(1), nodes: vec![2] }
2021-11-11 16:49:07 +00:00
]
);
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateTextNode { text: "text 0", root: Some(1) },
CreateTextNode { text: "text 1", root: Some(3) },
ReplaceWith { root: Some(2), nodes: vec![1, 3] },
2021-11-11 16:49:07 +00:00
]
);
assert_eq!(
dom.hard_diff(ScopeId(0)).edits,
2021-11-11 16:49:07 +00:00
[
CreateElement { tag: "h1", root: Some(2), children: 0 },
ReplaceWith { root: Some(1), nodes: vec![2] },
Remove { root: Some(3) },
2021-11-11 16:49:07 +00:00
]
);
}
2021-11-11 21:36:51 +00:00
#[test]
fn component_swap() {
fn app(cx: Scope) -> Element {
let render_phase = cx.use_hook(|| 0);
2021-12-21 03:33:13 +00:00
*render_phase += 1;
2021-11-11 21:36:51 +00:00
cx.render(match *render_phase {
0 => rsx_without_templates!(
2021-11-11 21:36:51 +00:00
div {
NavBar {}
Dashboard {}
}
),
1 => rsx_without_templates!(
2021-11-11 21:36:51 +00:00
div {
NavBar {}
Results {}
}
),
2 => rsx_without_templates!(
2021-11-11 21:36:51 +00:00
div {
NavBar {}
Dashboard {}
}
),
3 => rsx_without_templates!(
2021-11-11 21:36:51 +00:00
div {
NavBar {}
Results {}
}
),
4 => rsx_without_templates!(
2021-11-11 21:36:51 +00:00
div {
NavBar {}
Dashboard {}
}
),
_ => rsx_without_templates!("blah"),
2021-11-11 21:36:51 +00:00
})
};
2021-12-29 04:48:25 +00:00
static NavBar: Component = |cx| {
2021-11-11 21:36:51 +00:00
println!("running navbar");
cx.render(rsx_without_templates! {
2021-11-11 21:36:51 +00:00
h1 {
"NavBar"
{(0..3).map(|f| rsx_without_templates!(NavLink {}))}
2021-11-11 21:36:51 +00:00
}
})
};
2021-12-29 04:48:25 +00:00
static NavLink: Component = |cx| {
2021-11-11 21:36:51 +00:00
println!("running navlink");
cx.render(rsx_without_templates! {
2021-11-11 21:36:51 +00:00
h1 {
"NavLink"
}
})
};
2021-12-29 04:48:25 +00:00
static Dashboard: Component = |cx| {
2021-11-11 21:36:51 +00:00
println!("running dashboard");
cx.render(rsx_without_templates! {
2021-11-11 21:36:51 +00:00
div {
"dashboard"
}
})
};
2021-12-29 04:48:25 +00:00
static Results: Component = |cx| {
2021-11-11 21:36:51 +00:00
println!("running results");
cx.render(rsx_without_templates! {
2021-11-11 21:36:51 +00:00
div {
"results"
}
})
};
let mut dom = VirtualDom::new(app);
2021-11-11 21:36:51 +00:00
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);
}