diff --git a/.github/workflows/main-checks.yml b/.github/workflows/main-checks.yml index f65da730e48..ffc64693d84 100644 --- a/.github/workflows/main-checks.yml +++ b/.github/workflows/main-checks.yml @@ -103,8 +103,8 @@ jobs: - name: Run tests - yew run: | cd packages/yew - CHROMEDRIVER=$(which chromedriver) cargo test --features csr,hydration,ssr --target wasm32-unknown-unknown - GECKODRIVER=$(which geckodriver) cargo test --features csr,hydration,ssr --target wasm32-unknown-unknown + CHROMEDRIVER=$(which chromedriver) cargo test --features csr,hydration,ssr,test --target wasm32-unknown-unknown + GECKODRIVER=$(which geckodriver) cargo test --features csr,hydration,ssr,test --target wasm32-unknown-unknown - name: Run tests - yew-router run: | @@ -252,7 +252,7 @@ jobs: - name: Run WASI tests for yew run: | RUST_LOG=info - cargo test --features ssr,hydration --target wasm32-wasip1 -p yew + cargo test --features ssr,hydration,test --target wasm32-wasip1 -p yew example-runnable-tests-on-wasi: name: Example Runnable Tests on WASI diff --git a/examples/function_router/src/components/pagination.rs b/examples/function_router/src/components/pagination.rs index 693bda5e72a..b217c4de036 100644 --- a/examples/function_router/src/components/pagination.rs +++ b/examples/function_router/src/components/pagination.rs @@ -131,12 +131,12 @@ pub fn Links(props: &Props) -> Html { page, total_pages, .. } = *props; - let pages_prev = page.checked_sub(1).unwrap_or_default() as usize; + let pages_prev = page.saturating_sub(1) as usize; let pages_next = (total_pages - page) as usize; let links_left = LINKS_PER_SIDE.min(pages_prev) // if there are less than `LINKS_PER_SIDE` to the right, we add some more on the left. - + LINKS_PER_SIDE.checked_sub(pages_next).unwrap_or_default(); + + LINKS_PER_SIDE.saturating_sub(pages_next); let links_right = 2 * LINKS_PER_SIDE - links_left; html! { diff --git a/examples/keyed_list/src/main.rs b/examples/keyed_list/src/main.rs index 98f6ce31cb1..0dd7b8cd941 100644 --- a/examples/keyed_list/src/main.rs +++ b/examples/keyed_list/src/main.rs @@ -106,8 +106,7 @@ impl Component for App { true } Msg::SortById => { - self.persons - .sort_unstable_by(|a, b| a.info().id.cmp(&b.info().id)); + self.persons.sort_unstable_by_key(|a| a.info().id); true } Msg::SortByName => { diff --git a/examples/router/src/components/pagination.rs b/examples/router/src/components/pagination.rs index 2ced795e76f..6467d20de50 100644 --- a/examples/router/src/components/pagination.rs +++ b/examples/router/src/components/pagination.rs @@ -95,12 +95,12 @@ impl Pagination { page, total_pages, .. } = *props; - let pages_prev = page.checked_sub(1).unwrap_or_default() as usize; + let pages_prev = page.saturating_sub(1) as usize; let pages_next = (total_pages - page) as usize; let links_left = LINKS_PER_SIDE.min(pages_prev) // if there are less than `LINKS_PER_SIDE` to the right, we add some more on the left. - + LINKS_PER_SIDE.checked_sub(pages_next).unwrap_or_default(); + + LINKS_PER_SIDE.saturating_sub(pages_next); let links_right = 2 * LINKS_PER_SIDE - links_left; html! { diff --git a/packages/yew-macro/src/html_tree/tag.rs b/packages/yew-macro/src/html_tree/tag.rs index 4c66f887089..5c860f850a5 100644 --- a/packages/yew-macro/src/html_tree/tag.rs +++ b/packages/yew-macro/src/html_tree/tag.rs @@ -107,14 +107,12 @@ impl TagTokens { let next = input.parse()?; if let TokenTree::Punct(punct) = &next { match punct.as_char() { - '/' => { - if angle_count == 1 && input.peek(Token![>]) { - div = Some(syn::token::Slash { - spans: [punct.span()], - }); - gt = input.parse()?; - break; - } + '/' if angle_count == 1 && input.peek(Token![>]) => { + div = Some(syn::token::Slash { + spans: [punct.span()], + }); + gt = input.parse()?; + break; } '>' => { angle_count = angle_count.checked_sub(1).ok_or_else(|| { diff --git a/packages/yew/Makefile.toml b/packages/yew/Makefile.toml index 63fdf541f93..d67528f7e93 100644 --- a/packages/yew/Makefile.toml +++ b/packages/yew/Makefile.toml @@ -1,6 +1,6 @@ [tasks.native-test] command = "cargo" -args = ["test", "--features", "csr,ssr,hydration"] +args = ["test", "--features", "csr,ssr,hydration,test"] [tasks.wasm-test] command = "wasm-pack" @@ -10,7 +10,7 @@ args = [ "--headless", "--", "--features", - "csr,hydration,ssr", + "csr,hydration,ssr,test", ] [tasks.ssr-test] diff --git a/packages/yew/src/dom_bundle/btag/mod.rs b/packages/yew/src/dom_bundle/btag/mod.rs index 4daae6c9590..72db5197632 100644 --- a/packages/yew/src/dom_bundle/btag/mod.rs +++ b/packages/yew/src/dom_bundle/btag/mod.rs @@ -175,19 +175,20 @@ impl Reconcilable for VTag { match bundle { // If the ancestor is a tag of the same type, don't recreate, keep the // old tag and update its attributes and children. - BNode::Tag(ex) if self.key == ex.key => { - if match (&self.inner, &ex.inner) { - (VTagInner::Input(_), BTagInner::Input(_)) => true, - (VTagInner::Textarea { .. }, BTagInner::Textarea { .. }) => true, - (VTagInner::Other { tag: l, .. }, BTagInner::Other { tag: r, .. }) - if l == r => - { - true - } - _ => false, - } { - return self.reconcile(root, parent_scope, parent, slot, ex.deref_mut()); - } + BNode::Tag(ex) + if self.key == ex.key + && match (&self.inner, &ex.inner) { + (VTagInner::Input(_), BTagInner::Input(_)) => true, + (VTagInner::Textarea { .. }, BTagInner::Textarea { .. }) => true, + (VTagInner::Other { tag: l, .. }, BTagInner::Other { tag: r, .. }) + if l == r => + { + true + } + _ => false, + } => + { + return self.reconcile(root, parent_scope, parent, slot, ex.deref_mut()); } _ => {} }; diff --git a/packages/yew/src/scheduler.rs b/packages/yew/src/scheduler.rs index 28195b934f0..4a42f33df65 100644 --- a/packages/yew/src/scheduler.rs +++ b/packages/yew/src/scheduler.rs @@ -3,6 +3,34 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::rc::Rc; +#[cfg(any(test, feature = "test"))] +mod flush_wakers { + use std::cell::RefCell; + use std::task::Waker; + + thread_local! { + static FLUSH_WAKERS: RefCell> = Default::default(); + } + + #[cfg(all( + target_arch = "wasm32", + not(target_os = "wasi"), + not(feature = "not_browser_env") + ))] + pub(super) fn register(waker: Waker) { + FLUSH_WAKERS.with(|w| { + w.borrow_mut().push(waker); + }); + } + + pub(super) fn wake_all() { + FLUSH_WAKERS.with(|w| { + for waker in w.borrow_mut().drain(..) { + waker.wake(); + } + }); + } +} /// Alias for `Rc>` pub type Shared = Rc>; @@ -207,6 +235,8 @@ pub(crate) fn start_now() { LOCK.with(|l| { if let Ok(_lock) = l.try_borrow_mut() { scheduler_loop(); + #[cfg(any(test, feature = "test"))] + flush_wakers::wake_all(); } }); } @@ -232,6 +262,11 @@ mod arch { IS_SCHEDULED.store(is, Ordering::Relaxed) } + #[cfg(any(test, feature = "test"))] + pub(super) fn is_scheduled() -> bool { + check_scheduled() + } + /// We delay the start of the scheduler to the end of the micro task queue. /// So any messages that needs to be queued can be queued. pub(crate) fn start() { @@ -264,6 +299,51 @@ mod arch { pub(crate) use arch::*; +/// Flush all pending scheduler work, ensuring all rendering and lifecycle callbacks complete. +/// +/// On browser WebAssembly targets, the scheduler defers its work to the microtask queue. +/// This function registers a waker that is notified when `start_now()` finishes draining all +/// queues, providing proper event-driven render-complete notification without arbitrary sleeps. +/// +/// On non-browser targets, the scheduler runs synchronously so this simply drains pending work. +/// +/// Use this in tests after mounting or updating a component to ensure all rendering has +/// completed before making assertions. +#[cfg(all( + any(test, feature = "test"), + target_arch = "wasm32", + not(target_os = "wasi"), + not(feature = "not_browser_env") +))] +pub async fn flush() { + std::future::poll_fn(|cx| { + start_now(); + + if arch::is_scheduled() { + flush_wakers::register(cx.waker().clone()); + std::task::Poll::Pending + } else { + std::task::Poll::Ready(()) + } + }) + .await +} + +/// Flush all pending scheduler work, ensuring all rendering and lifecycle callbacks complete. +/// +/// On non-browser targets, the scheduler runs synchronously so this simply drains pending work. +#[cfg(all( + any(test, feature = "test"), + not(all( + target_arch = "wasm32", + not(target_os = "wasi"), + not(feature = "not_browser_env") + )) +))] +pub async fn flush() { + start_now(); +} + impl Scheduler { /// Fill vector with tasks to be executed according to Runnable type execution priority /// diff --git a/packages/yew/tests/hydration.rs b/packages/yew/tests/hydration.rs index 5b4e1cdd527..e266614a319 100644 --- a/packages/yew/tests/hydration.rs +++ b/packages/yew/tests/hydration.rs @@ -16,7 +16,7 @@ use yew::platform::time::sleep; use yew::prelude::*; use yew::suspense::{use_future, Suspension, SuspensionResult}; use yew::virtual_dom::VNode; -use yew::{component, Renderer, ServerRenderer}; +use yew::{component, scheduler, Renderer, ServerRenderer}; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -62,12 +62,12 @@ async fn hydration_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); @@ -85,7 +85,7 @@ async fn hydration_works() { .unwrap() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); @@ -237,7 +237,7 @@ async fn hydration_with_suspense() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); @@ -393,7 +393,7 @@ async fn hydration_with_suspense_not_suspended_at_start() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); @@ -524,7 +524,7 @@ async fn hydration_nested_suspense_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); @@ -661,12 +661,12 @@ async fn hydration_node_ref_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); assert_eq!( @@ -682,7 +682,7 @@ async fn hydration_node_ref_works() { .unwrap() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); assert_eq!( @@ -754,16 +754,13 @@ async fn hydration_list_order_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); // Wait until all suspended components becomes revealed. - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); assert_eq!( @@ -837,13 +834,13 @@ async fn hydration_suspense_no_flickering() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); // Wait until all suspended components becomes revealed. - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); assert_eq!( @@ -950,16 +947,13 @@ async fn hydration_order_issue_nested_suspense() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); // Wait until all suspended components becomes revealed. - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result_by_id("output"); assert_eq!( @@ -1180,7 +1174,7 @@ async fn hydration_with_camelcase_svg_elements() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; // Hydrate - this should not panic Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) @@ -1268,15 +1262,12 @@ async fn hydration_suspended_child_does_not_trap_sibling_slot() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); diff --git a/packages/yew/tests/mod.rs b/packages/yew/tests/mod.rs index 608c461ca3a..51264b1cc7f 100644 --- a/packages/yew/tests/mod.rs +++ b/packages/yew/tests/mod.rs @@ -2,12 +2,10 @@ mod common; -use std::time::Duration; - use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -36,7 +34,7 @@ async fn props_are_passed() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "done"); } diff --git a/packages/yew/tests/suspense.rs b/packages/yew/tests/suspense.rs index a8d8d3851db..69b80b6372e 100644 --- a/packages/yew/tests/suspense.rs +++ b/packages/yew/tests/suspense.rs @@ -14,7 +14,7 @@ use yew::platform::spawn_local; use yew::platform::time::sleep; use yew::prelude::*; use yew::suspense::{use_future, use_future_with, Suspension, SuspensionResult}; -use yew::UseStateHandle; +use yew::{scheduler, UseStateHandle}; wasm_bindgen_test_configure!(run_in_browser); @@ -123,7 +123,7 @@ async fn suspense_works() { .unwrap() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; gloo::utils::document() .query_selector(".increase") @@ -553,7 +553,7 @@ async fn effects_not_run_when_suspended() { .unwrap() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; gloo::utils::document() .query_selector(".increase") @@ -563,7 +563,7 @@ async fn effects_not_run_when_suspended() { .unwrap() .click(); - sleep(Duration::from_millis(0)).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!( @@ -788,7 +788,7 @@ async fn test_duplicate_suspension() { #[component] fn FetchingProvider(props: &ChildrenProps) -> HtmlResult { use_future(|| async { - sleep(Duration::ZERO).await; + scheduler::flush().await; })?; Ok(html! { <>{props.children.clone()} }) } diff --git a/packages/yew/tests/use_callback.rs b/packages/yew/tests/use_callback.rs index db972f7493b..9307ffa992f 100644 --- a/packages/yew/tests/use_callback.rs +++ b/packages/yew/tests/use_callback.rs @@ -4,12 +4,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; mod common; -use std::time::Duration; - use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -65,7 +63,7 @@ async fn use_callback_works() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "Hello, Yew!"); diff --git a/packages/yew/tests/use_context.rs b/packages/yew/tests/use_context.rs index 5074f223ea8..f519f9c3a0d 100644 --- a/packages/yew/tests/use_context.rs +++ b/packages/yew/tests/use_context.rs @@ -3,12 +3,11 @@ mod common; use std::rc::Rc; -use std::time::Duration; use common::obtain_result_by_id; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -69,7 +68,7 @@ async fn use_context_scoping_works() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result: String = obtain_result_by_id("result"); assert_eq!("correct", result); @@ -152,7 +151,7 @@ async fn use_context_works_with_multiple_types() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; } #[wasm_bindgen_test] @@ -252,7 +251,7 @@ async fn use_context_update_works() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; // 1 initial render + 1 magic assert_eq!(obtain_result_by_id("test-0"), "total: 2"); diff --git a/packages/yew/tests/use_effect.rs b/packages/yew/tests/use_effect.rs index 7d37573243b..de6738e8d59 100644 --- a/packages/yew/tests/use_effect.rs +++ b/packages/yew/tests/use_effect.rs @@ -4,12 +4,11 @@ mod common; use std::ops::{Deref, DerefMut}; use std::rc::Rc; -use std::time::Duration; use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -72,7 +71,7 @@ async fn use_effect_destroys_on_component_drop() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; assert_eq!(1, *destroy_counter.borrow().deref()); } @@ -105,7 +104,7 @@ async fn use_effect_works_many_times() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "4"); } @@ -135,7 +134,7 @@ async fn use_effect_works_once() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); @@ -181,7 +180,7 @@ async fn use_effect_refires_on_dependency_change() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result: String = obtain_result(); assert_eq!(result.as_str(), "11"); diff --git a/packages/yew/tests/use_memo.rs b/packages/yew/tests/use_memo.rs index 4fb2d0d488c..09d2270740f 100644 --- a/packages/yew/tests/use_memo.rs +++ b/packages/yew/tests/use_memo.rs @@ -4,12 +4,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; mod common; -use std::time::Duration; - use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -51,7 +49,7 @@ async fn use_memo_works() { ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "true"); diff --git a/packages/yew/tests/use_prepared_state.rs b/packages/yew/tests/use_prepared_state.rs index d0449c961ac..03afa5548e1 100644 --- a/packages/yew/tests/use_prepared_state.rs +++ b/packages/yew/tests/use_prepared_state.rs @@ -10,7 +10,7 @@ use common::obtain_result_by_id; use wasm_bindgen_test::*; use yew::platform::time::sleep; use yew::prelude::*; -use yew::{Renderer, ServerRenderer}; +use yew::{scheduler, Renderer, ServerRenderer}; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -51,7 +51,7 @@ async fn use_prepared_state_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); @@ -101,7 +101,7 @@ async fn use_prepared_state_with_suspension_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate(); diff --git a/packages/yew/tests/use_reducer.rs b/packages/yew/tests/use_reducer.rs index 53191c024a6..138fb50a8bc 100644 --- a/packages/yew/tests/use_reducer.rs +++ b/packages/yew/tests/use_reducer.rs @@ -2,14 +2,13 @@ use std::collections::HashSet; use std::rc::Rc; -use std::time::Duration; use gloo::utils::document; use wasm_bindgen::JsCast; use wasm_bindgen_test::*; use web_sys::HtmlElement; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; mod common; @@ -57,7 +56,7 @@ async fn use_reducer_works() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "11"); @@ -117,7 +116,7 @@ async fn use_reducer_eq_works() { document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "1"); @@ -127,7 +126,7 @@ async fn use_reducer_eq_works() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "2"); @@ -137,7 +136,7 @@ async fn use_reducer_eq_works() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "2"); @@ -147,7 +146,7 @@ async fn use_reducer_eq_works() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "3"); @@ -157,7 +156,7 @@ async fn use_reducer_eq_works() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "3"); @@ -228,7 +227,7 @@ async fn use_reducer_does_not_rerender_when_rc_is_reused() { document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "1"); @@ -238,7 +237,7 @@ async fn use_reducer_does_not_rerender_when_rc_is_reused() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "2"); @@ -248,7 +247,7 @@ async fn use_reducer_does_not_rerender_when_rc_is_reused() { .unwrap() .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "2"); diff --git a/packages/yew/tests/use_ref.rs b/packages/yew/tests/use_ref.rs index a39535d1157..0b26a4d241b 100644 --- a/packages/yew/tests/use_ref.rs +++ b/packages/yew/tests/use_ref.rs @@ -3,12 +3,11 @@ mod common; use std::ops::DerefMut; -use std::time::Duration; use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -35,7 +34,7 @@ async fn use_ref_works() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "true"); diff --git a/packages/yew/tests/use_state.rs b/packages/yew/tests/use_state.rs index 9f3cdcbf126..c97940e88e9 100644 --- a/packages/yew/tests/use_state.rs +++ b/packages/yew/tests/use_state.rs @@ -2,12 +2,10 @@ mod common; -use std::time::Duration; - use common::obtain_result; use wasm_bindgen_test::*; -use yew::platform::time::sleep; use yew::prelude::*; +use yew::scheduler; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -32,7 +30,7 @@ async fn use_state_works() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "5"); } @@ -72,7 +70,7 @@ async fn multiple_use_state_setters() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "11"); } @@ -101,7 +99,7 @@ async fn use_state_eq_works() { gloo::utils::document().get_element_by_id("output").unwrap(), ) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; let result = obtain_result(); assert_eq!(result.as_str(), "1"); assert_eq!(RENDER_COUNT.load(Ordering::Relaxed), 2); @@ -202,7 +200,7 @@ async fn deref_remains_valid_across_multiple_dispatches_in_callback() { yew::Renderer::::with_root(document().get_element_by_id("output").unwrap()) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; // Fire the callback document() @@ -211,7 +209,7 @@ async fn deref_remains_valid_across_multiple_dispatches_in_callback() { .unchecked_into::() .click(); - sleep(Duration::ZERO).await; + scheduler::flush().await; // The reference obtained between the two dispatches must still read the // value from the first dispatch, not garbage or "second_dispatch". @@ -290,7 +288,7 @@ async fn use_state_handles_read_latest_value_issue_3796() { yew::Renderer::::with_root(document().get_element_by_id("output").unwrap()) .render(); - sleep(Duration::ZERO).await; + scheduler::flush().await; // Initial state let result = obtain_result(); @@ -317,7 +315,7 @@ async fn use_state_handles_read_latest_value_issue_3796() { .click(); // Now wait for rerenders to complete - sleep(Duration::ZERO).await; + scheduler::flush().await; // Check the values captured by the submit handler. // Before the fix, field_b would be empty because the callback captured a stale handle. diff --git a/packages/yew/tests/use_transitive_state.rs b/packages/yew/tests/use_transitive_state.rs index 0d0880ebe0d..d8eeb4d1659 100644 --- a/packages/yew/tests/use_transitive_state.rs +++ b/packages/yew/tests/use_transitive_state.rs @@ -9,7 +9,7 @@ use common::obtain_result_by_id; use wasm_bindgen_test::*; use yew::platform::time::sleep; use yew::prelude::*; -use yew::{Renderer, ServerRenderer}; +use yew::{scheduler, Renderer, ServerRenderer}; wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -51,7 +51,7 @@ async fn use_transitive_state_works() { .unwrap() .set_inner_html(&s); - sleep(Duration::ZERO).await; + scheduler::flush().await; Renderer::::with_root(gloo::utils::document().get_element_by_id("output").unwrap()) .hydrate();