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 });
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// 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