chore: add tests for context api
This commit is contained in:
1 parent
04296bb88d
commit
d0554b9ed6
5 files changed
+56
-419
No files matched your search
@@ -290,6 +290,11 @@ impl VirtualDom {
|
|||||||
self.dirty_scopes.insert(DirtyScope { height, id });
|
self.dirty_scopes.insert(DirtyScope { height, id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark the entire tree as dirty.
|
||||||
|
///
|
||||||
|
/// Will force a re-render of every component
|
||||||
|
pub fn mark_dirty_all(&mut self) {}
|
||||||
|
|
||||||
/// Determine whether or not a scope is currently in a suspended state
|
/// Determine whether or not a scope is currently in a suspended state
|
||||||
///
|
///
|
||||||
/// This does not mean the scope is waiting on its own futures, just that the tree that the scope exists in is
|
/// This does not mean the scope is waiting on its own futures, just that the tree that the scope exists in is
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
use dioxus::core::{ElementId, Mutation::*};
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn state_shares() {
|
||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
cx.provide_context(cx.generation() as i32);
|
||||||
|
|
||||||
|
cx.render(rsx!(child_1 {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn child_1(cx: Scope) -> Element {
|
||||||
|
cx.render(rsx!(child_2 {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn child_2(cx: Scope) -> Element {
|
||||||
|
let value = cx.consume_context::<i32>().unwrap();
|
||||||
|
cx.render(rsx!("Value is {value}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dom = VirtualDom::new(app);
|
||||||
|
assert_eq!(
|
||||||
|
dom.rebuild().santize().edits,
|
||||||
|
[
|
||||||
|
CreateTextNode { value: "Value is 0", id: ElementId(1,) },
|
||||||
|
AppendChildren { m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
dom.render_immediate();
|
||||||
|
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 1);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
dom.render_immediate();
|
||||||
|
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 2);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(2));
|
||||||
|
assert_eq!(
|
||||||
|
dom.render_immediate().santize().edits,
|
||||||
|
[SetText { value: "Value is 2", id: ElementId(1,) },]
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
dom.mark_dirty_scope(ScopeId(2));
|
||||||
|
let edits = dom.render_immediate();
|
||||||
|
assert_eq!(
|
||||||
|
edits.santize().edits,
|
||||||
|
[SetText { value: "Value is 3", id: ElementId(1,) },]
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
#![allow(unused, non_upper_case_globals, non_snake_case)]
|
|
||||||
|
|
||||||
//! Prove that the dom works normally through virtualdom methods.
|
|
||||||
//!
|
|
||||||
//! This methods all use "rebuild" which completely bypasses the scheduler.
|
|
||||||
//! Hard rebuilds don't consume any events from the event queue.
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
|
||||||
|
|
||||||
use dioxus_edit_stream::DomEdit::*;
|
|
||||||
|
|
||||||
fn new_dom<P: 'static + Send>(app: Component<P>, props: P) -> VirtualDom {
|
|
||||||
VirtualDom::new_with_props(app, props)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_original_diff() {
|
|
||||||
static APP: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
div {
|
|
||||||
div {
|
|
||||||
"Hello, world!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(APP, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "Hello, world!" },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
// add to root
|
|
||||||
AppendChildren { root: Some(0), children: vec![2] },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create() {
|
|
||||||
static APP: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
div {
|
|
||||||
div {
|
|
||||||
"Hello, world!"
|
|
||||||
div {
|
|
||||||
div {
|
|
||||||
Fragment {
|
|
||||||
"hello"
|
|
||||||
"world"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(APP, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 2 },
|
|
||||||
CreateTextNode { root: None, text: "Hello, world!" },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
SetLastNode { id: 2 },
|
|
||||||
FirstChild {},
|
|
||||||
StoreWithId { id: 3 },
|
|
||||||
FirstChild {},
|
|
||||||
NextSibling {},
|
|
||||||
StoreWithId { id: 4 },
|
|
||||||
FirstChild {},
|
|
||||||
StoreWithId { id: 5 },
|
|
||||||
CreateTextNode { root: Some(6), text: "hello" },
|
|
||||||
CreateTextNode { root: Some(7), text: "world" },
|
|
||||||
SetLastNode { id: 5 },
|
|
||||||
AppendChildren { root: None, children: vec![6, 7] },
|
|
||||||
AppendChildren { root: Some(0), children: vec![2] }
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_list() {
|
|
||||||
static APP: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
{(0..3).map(|f| rsx!{ div {
|
|
||||||
"hello"
|
|
||||||
}})}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(APP, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "hello" },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![3] },
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![4] },
|
|
||||||
// add to root
|
|
||||||
AppendChildren { root: Some(0), children: vec![2, 3, 4] },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_simple() {
|
|
||||||
static APP: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
div {}
|
|
||||||
div {}
|
|
||||||
div {}
|
|
||||||
div {}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(APP, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 4 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4, 5] },
|
|
||||||
// add to root
|
|
||||||
AppendChildren { root: Some(0), children: vec![2, 3, 4, 5] },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn create_components() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
Child { "abc1" }
|
|
||||||
Child { "abc2" }
|
|
||||||
Child { "abc3" }
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Props)]
|
|
||||||
struct ChildProps<'a> {
|
|
||||||
children: Element<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
|
|
||||||
cx.render(rsx! {
|
|
||||||
h1 {}
|
|
||||||
div { &cx.props.children }
|
|
||||||
p {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut dom = new_dom(App, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 3 },
|
|
||||||
CreateElement { root: None, tag: "h1", children: 0 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 0 },
|
|
||||||
CreateElement { root: None, tag: "p", children: 0 },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4] },
|
|
||||||
// update template
|
|
||||||
SetLastNode { id: 2 },
|
|
||||||
NextSibling {},
|
|
||||||
CreateTextNode { root: Some(5), text: "abc1" },
|
|
||||||
SetLastNode { id: 3 },
|
|
||||||
AppendChildren { root: None, children: vec![5] },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![6, 7, 8] },
|
|
||||||
SetLastNode { id: 6 },
|
|
||||||
NextSibling {},
|
|
||||||
// update template
|
|
||||||
CreateTextNode { root: Some(9), text: "abc2" },
|
|
||||||
SetLastNode { id: 7 },
|
|
||||||
AppendChildren { root: None, children: vec![9] },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![10, 11, 12] },
|
|
||||||
// update template
|
|
||||||
SetLastNode { id: 10 },
|
|
||||||
NextSibling {},
|
|
||||||
CreateTextNode { root: Some(13), text: "abc3" },
|
|
||||||
SetLastNode { id: 11 },
|
|
||||||
AppendChildren { root: None, children: vec![13] },
|
|
||||||
// add to root
|
|
||||||
AppendChildren { root: Some(0), children: vec![2, 3, 4, 6, 7, 8, 10, 11, 12] }
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn anchors() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx! {
|
|
||||||
{true.then(|| rsx!{ div { "hello" } })}
|
|
||||||
{false.then(|| rsx!{ div { "goodbye" } })}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(App, ());
|
|
||||||
let mutations = dom.rebuild();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "hello" },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
CreatePlaceholder { root: Some(3) },
|
|
||||||
// add to root
|
|
||||||
AppendChildren { root: Some(0), children: vec![2, 3] },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
#![allow(unused, non_upper_case_globals, non_snake_case)]
|
|
||||||
|
|
||||||
//! Prove that the dom works normally through virtualdom methods.
|
|
||||||
//!
|
|
||||||
//! This methods all use "rebuild" which completely bypasses the scheduler.
|
|
||||||
//! Hard rebuilds don't consume any events from the event queue.
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
|
||||||
|
|
||||||
use dioxus_core::{DomEdit::*, ScopeId};
|
|
||||||
|
|
||||||
const IS_LOGGING_ENABLED: bool = false;
|
|
||||||
|
|
||||||
fn new_dom<P: 'static + Send>(app: Component<P>, props: P) -> VirtualDom {
|
|
||||||
VirtualDom::new_with_props(app, props)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This test ensures that if a component aborts early, it is replaced with a placeholder.
|
|
||||||
/// In debug, this should also toss a warning.
|
|
||||||
#[test]
|
|
||||||
fn test_early_abort() {
|
|
||||||
const app: Component = |cx| {
|
|
||||||
let val = cx.use_hook(|| 0);
|
|
||||||
|
|
||||||
*val += 1;
|
|
||||||
|
|
||||||
if *val == 2 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
render!(div { "Hello, world!" })
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dom = new_dom(app, ());
|
|
||||||
|
|
||||||
let edits = dom.rebuild();
|
|
||||||
assert_eq!(
|
|
||||||
edits.edits,
|
|
||||||
[
|
|
||||||
// create template
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "div", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "Hello, world!" },
|
|
||||||
// clone template
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
AppendChildren { root: Some(0), children: vec![2] }
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
let edits = dom.hard_diff(ScopeId(0));
|
|
||||||
assert_eq!(
|
|
||||||
edits.edits,
|
|
||||||
[
|
|
||||||
CreatePlaceholder { root: Some(3) },
|
|
||||||
ReplaceWith { root: Some(2), nodes: vec![3] }
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
let edits = dom.hard_diff(ScopeId(0));
|
|
||||||
assert_eq!(
|
|
||||||
edits.edits,
|
|
||||||
[
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2] },
|
|
||||||
ReplaceWith { root: Some(3), nodes: vec![2] }
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#![allow(unused, non_upper_case_globals)]
|
|
||||||
|
|
||||||
//! Rebuilding tests
|
|
||||||
//! ----------------
|
|
||||||
//!
|
|
||||||
//! This tests module ensures that the initial build of the virtualdom is correct.
|
|
||||||
//! This does not include dynamic tests or the diffing algorithm itself.
|
|
||||||
//!
|
|
||||||
//! It does prove that mounting works properly and the correct edit streams are generated.
|
|
||||||
//!
|
|
||||||
//! Don't have a good way to validate, everything is done manually ATM
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
|
||||||
use dioxus_core::DomEdit::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn app_runs() {
|
|
||||||
static App: Component = |cx| render!(div{"hello"} );
|
|
||||||
|
|
||||||
let mut vdom = VirtualDom::new(App);
|
|
||||||
let edits = vdom.rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn fragments_work() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx!(
|
|
||||||
div{"hello"}
|
|
||||||
div{"goodbye"}
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new(App);
|
|
||||||
let edits = vdom.rebuild();
|
|
||||||
// should result in a final "appendchildren n=2"
|
|
||||||
dbg!(edits);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn lists_work() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx!(
|
|
||||||
h1 {"hello"}
|
|
||||||
(0..6).map(|f| rsx!(span{ "{f}" }))
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new(App);
|
|
||||||
let edits = vdom.rebuild();
|
|
||||||
dbg!(edits);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn conditional_rendering() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx!(
|
|
||||||
h1 {"hello"}
|
|
||||||
{true.then(|| rsx!(span{ "a" }))}
|
|
||||||
{false.then(|| rsx!(span{ "b" }))}
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new(App);
|
|
||||||
|
|
||||||
let mutations = vdom.rebuild();
|
|
||||||
assert_eq!(
|
|
||||||
mutations.edits,
|
|
||||||
[
|
|
||||||
CreateElement { root: Some(1), tag: "template", children: 3 },
|
|
||||||
CreateElement { root: None, tag: "h1", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "hello" },
|
|
||||||
CreatePlaceholder { root: None },
|
|
||||||
CreatePlaceholder { root: None },
|
|
||||||
CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4] },
|
|
||||||
CreateElement { root: Some(5), tag: "template", children: 1 },
|
|
||||||
CreateElement { root: None, tag: "span", children: 1 },
|
|
||||||
CreateTextNode { root: None, text: "a" },
|
|
||||||
CloneNodeChildren { id: Some(5), new_ids: vec![6] },
|
|
||||||
SetLastNode { id: 3 },
|
|
||||||
ReplaceWith { root: None, nodes: vec![6] },
|
|
||||||
CreatePlaceholder { root: Some(7) },
|
|
||||||
SetLastNode { id: 4 },
|
|
||||||
ReplaceWith { root: None, nodes: vec![7] },
|
|
||||||
AppendChildren { root: Some(0), children: vec![2, 3, 4] }
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn child_components() {
|
|
||||||
static App: Component = |cx| {
|
|
||||||
cx.render(rsx!(
|
|
||||||
{true.then(|| rsx!(Child { }))}
|
|
||||||
{false.then(|| rsx!(Child { }))}
|
|
||||||
))
|
|
||||||
};
|
|
||||||
static Child: Component = |cx| {
|
|
||||||
cx.render(rsx!(
|
|
||||||
h1 {"hello"}
|
|
||||||
h1 {"goodbye"}
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new(App);
|
|
||||||
let edits = vdom.rebuild();
|
|
||||||
dbg!(edits);
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user