diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 1a94d04e5..cbb1f7250 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -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 diff --git a/packages/core/tests/context_api.rs b/packages/core/tests/context_api.rs new file mode 100644 index 000000000..71069d2fc --- /dev/null +++ b/packages/core/tests/context_api.rs @@ -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::().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::().unwrap(), 1); + + dom.mark_dirty_scope(ScopeId(0)); + dom.render_immediate(); + assert_eq!(dom.base_scope().consume_context::().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,) },] + ); +} diff --git a/packages/dioxus/tests/create_dom.rs b/packages/dioxus/tests/create_dom.rs deleted file mode 100644 index a49efb1f7..000000000 --- a/packages/dioxus/tests/create_dom.rs +++ /dev/null @@ -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(app: Component

, 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] }, - ] - ); -} diff --git a/packages/dioxus/tests/earlyabort.rs b/packages/dioxus/tests/earlyabort.rs deleted file mode 100644 index 11bf3e2ca..000000000 --- a/packages/dioxus/tests/earlyabort.rs +++ /dev/null @@ -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(app: Component

, 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] } - ] - ); -} diff --git a/packages/dioxus/tests/vdom_rebuild.rs b/packages/dioxus/tests/vdom_rebuild.rs deleted file mode 100644 index 5d19de48e..000000000 --- a/packages/dioxus/tests/vdom_rebuild.rs +++ /dev/null @@ -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); -}