chore: add tests for context api

This commit is contained in:
Jonathan Kelley committed 2022-11-27 00:38:40 -05:00
1 parent 04296bb88d
commit d0554b9ed6
5 files changed
+56 -419

No files matched your search

+5
View File
@@ -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
+51
View File
@@ -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,) },]
);
}
-248
View File
@@ -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] },
]
);
}
-67
View File
@@ -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] }
]
);
}
-104
View File
@@ -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);
}