testing: provide tick() that can be called anywhere in tests

This commit is contained in:
Greg Johnston 2024-06-09 21:15:49 -04:00
parent 6462b3cf15
commit a43fb15e9a
15 changed files with 66 additions and 86 deletions

View file

@ -18,4 +18,3 @@ console_error_panic_hook = "0.1.7"
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"
web-sys = "0.3"
gloo-timers = { version = "0.3", features = ["futures"] }

View file

@ -1,7 +1,7 @@
use counter::*;
use gloo_timers::future::TimeoutFuture;
use leptos::mount::mount_to;
use leptos::prelude::*;
use leptos::spawn::tick;
use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
@ -36,7 +36,7 @@ async fn clear() {
// synchronously in the DOM
// in order to detect the changes here, we'll just yield for a brief time after each change,
// allowing the effects that update the view to run
TimeoutFuture::new(10).await;
tick().await;
// now let's test the <div> against the expected value
// we can do this by testing its `outerHTML`
@ -114,7 +114,7 @@ async fn inc() {
inc.click();
inc.click();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(text.text_content(), Some("Value: 2!".to_string()));
@ -123,13 +123,13 @@ async fn inc() {
dec.click();
dec.click();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(text.text_content(), Some("Value: -2!".to_string()));
clear.click();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(text.text_content(), Some("Value: 0!".to_string()));
@ -154,7 +154,7 @@ async fn inc() {
inc.click();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(
div.outer_html(),

View file

@ -17,7 +17,6 @@ wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.34"
pretty_assertions = "1.3.0"
rstest = "0.17.0"
gloo-timers = { version = "0.3", features = ["futures"] }
[dev-dependencies.web-sys]
features = ["HtmlElement", "XPathResult"]

View file

@ -1,6 +1,5 @@
use counter_without_macros::counter;
use gloo_timers::future::TimeoutFuture;
use leptos::prelude::*;
use leptos::{prelude::*, spawn::tick};
use pretty_assertions::assert_eq;
use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
@ -16,7 +15,7 @@ async fn should_increment_counter() {
click_increment();
// reactive changes run asynchronously, so yield briefly before observing the DOM
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(see_text(), Some("Value: 2!".to_string()));
}
@ -28,7 +27,7 @@ async fn should_decrement_counter() {
click_decrement();
click_decrement();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(see_text(), Some("Value: -2!".to_string()));
}
@ -42,7 +41,7 @@ async fn should_clear_counter() {
click_clear();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(see_text(), Some("Value: 0!".to_string()));
}

View file

@ -8,7 +8,6 @@ leptos = { path = "../../leptos", features = ["csr"] }
console_error_panic_hook = "0.1.7"
[dev-dependencies]
gloo-timers = { version = "0.3", features = ["futures"] }
wasm-bindgen-test = "0.3.0"
wasm-bindgen = "0.2"
web-sys = "0.3"

View file

@ -3,8 +3,8 @@ use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
use counters::Counters;
use gloo_timers::future::TimeoutFuture;
use leptos::prelude::*;
use leptos::spawn::tick;
use web_sys::HtmlElement;
#[wasm_bindgen_test]
@ -31,7 +31,7 @@ async fn inc() {
add_counter.click();
add_counter.click();
TimeoutFuture::new(10).await;
tick().await;
// check HTML
assert_eq!(
@ -74,7 +74,7 @@ async fn inc() {
}
}
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(
div.inner_html(),
@ -99,7 +99,7 @@ async fn inc() {
.unchecked_into::<HtmlElement>()
.click();
TimeoutFuture::new(10).await;
tick().await;
assert_eq!(
div.inner_html(),

View file

@ -14,4 +14,3 @@ wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"
wasm-bindgen = "0.2"
web-sys = "0.3"
gloo-timers = { version = "0.3", features = ["futures"] }

View file

@ -3,13 +3,10 @@ use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
use leptos::spawn::tick;
use leptos::{leptos_dom::helpers::document, mount::mount_to};
use web_sys::HtmlButtonElement;
async fn next_tick() {
gloo_timers::future::TimeoutFuture::new(25).await;
}
#[wasm_bindgen_test]
async fn portal() {
let document = document();
@ -28,7 +25,7 @@ async fn portal() {
show_button.click();
next_tick().await;
tick().await;
// check HTML
assert_eq!(div.inner_html(), "<div><button id=\"btn-show\">Show Overlay</button><div>Show</div><!----></div><div><div style=\"position: fixed; z-index: 10; width: 100vw; height: 100vh; top: 0; left: 0; background: rgba(0, 0, 0, 0.8); color: white;\"><p>This is in the body element</p><button id=\"btn-hide\">Close Overlay</button><button id=\"btn-toggle\">Toggle inner</button>Hidden<!----></div></div>");

View file

@ -282,6 +282,14 @@ pub mod spawn {
pub fn spawn_local(fut: impl Future<Output = ()> + 'static) {
Executor::spawn_local(fut)
}
pub async fn tick() {
let (tx, rx) = futures::channel::oneshot::channel();
any_spawner::Executor::spawn_local(async move {
_ = tx.send(());
});
_ = rx.await;
}
}
#[doc(hidden)]

View file

@ -27,7 +27,7 @@ async-lock = "3.3.0"
web-sys = "0.3"
[dev-dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
tokio-test = { version = "0.4" }
any_spawner = { workspace = true, features = ["futures-executor", "tokio"] }

View file

@ -59,7 +59,7 @@ use std::{future::Future, panic::Location, pin::Pin, sync::Arc};
/// assert_eq!(pending.get(), true); // is pending
/// assert_eq!(result_of_call.get(), None); // has not yet gotten a response
///
/// # tokio::time::sleep(std::time::Duration::from_millis(25)).await;
/// # any_spawner::Executor::tick().await;
///
/// // after call has resolved
/// assert_eq!(input.get(), None); // input clears out after resolved
@ -441,7 +441,7 @@ where
/// assert_eq!(pending.get(), true); // is pending
/// assert_eq!(result_of_call.get(), None); // has not yet gotten a response
///
/// # tokio::time::sleep(std::time::Duration::from_millis(25)).await;
/// # any_spawner::Executor::tick().await;
///
/// // after call has resolved
/// assert_eq!(input.get(), None); // input clears out after resolved

View file

@ -178,7 +178,7 @@ where
///
/// // when submissions resolve, they are not removed from the set
/// // however, their `pending` signal is now `false`, and this can be used to filter them
/// # tokio::time::sleep(std::time::Duration::from_millis(100)).await;
/// # any_spawner::Executor::tick().await;
/// assert_eq!(submissions.with(Vec::len), 3);
/// assert_eq!(pending_submissions(), 0);
/// # });
@ -288,7 +288,7 @@ where
/// add_todo.dispatch("Profit!!!".to_string());
///
/// assert_eq!(version.get(), 0);
/// # tokio::time::sleep(std::time::Duration::from_millis(100)).await;
/// # any_spawner::Executor::tick().await;
///
/// // when they've all resolved
/// assert_eq!(version.get(), 3);
@ -469,7 +469,7 @@ where
///
/// // when submissions resolve, they are not removed from the set
/// // however, their `pending` signal is now `false`, and this can be used to filter them
/// # tokio::time::sleep(std::time::Duration::from_millis(100)).await;
/// # any_spawner::Executor::tick().await;
/// assert_eq!(submissions.with(Vec::len), 3);
/// assert_eq!(pending_submissions(), 0);
/// # });
@ -611,7 +611,7 @@ where
/// add_todo.dispatch("Profit!!!".to_string());
///
/// assert_eq!(version.get(), 0);
/// # tokio::time::sleep(std::time::Duration::from_millis(100)).await;
/// # any_spawner::Executor::tick().await;
///
/// // when they've all resolved
/// assert_eq!(version.get(), 3);

View file

@ -1,6 +1,6 @@
use any_spawner::Executor;
use reactive_graph::{
computed::{ArcAsyncDerived, AsyncDerived, AsyncState},
computed::{ArcAsyncDerived, AsyncDerived},
signal::RwSignal,
traits::{Get, Read, Set, With, WithUntracked},
};
@ -8,13 +8,10 @@ use std::future::pending;
#[tokio::test]
async fn arc_async_derived_calculates_eagerly() {
use std::time::Duration;
use tokio::time::sleep;
_ = Executor::init_tokio();
let value = ArcAsyncDerived::new(|| async {
sleep(Duration::from_millis(25)).await;
Executor::tick().await;
42
});
@ -23,35 +20,29 @@ async fn arc_async_derived_calculates_eagerly() {
#[tokio::test]
async fn arc_async_derived_tracks_signal_change() {
use std::time::Duration;
use tokio::time::sleep;
_ = Executor::init_tokio();
let signal = RwSignal::new(10);
let value = ArcAsyncDerived::new(move || async move {
sleep(Duration::from_millis(25)).await;
Executor::tick().await;
signal.get()
});
assert_eq!(value.clone().await, 10);
signal.set(30);
sleep(Duration::from_millis(5)).await;
Executor::tick().await;
assert_eq!(value.clone().await, 30);
signal.set(50);
sleep(Duration::from_millis(5)).await;
Executor::tick().await;
assert_eq!(value.clone().await, 50);
}
#[tokio::test]
async fn async_derived_calculates_eagerly() {
use std::time::Duration;
use tokio::time::sleep;
_ = Executor::init_tokio();
let value = AsyncDerived::new(|| async {
sleep(Duration::from_millis(25)).await;
Executor::tick().await;
42
});
@ -60,23 +51,20 @@ async fn async_derived_calculates_eagerly() {
#[tokio::test]
async fn async_derived_tracks_signal_change() {
use std::time::Duration;
use tokio::time::sleep;
_ = Executor::init_tokio();
let signal = RwSignal::new(10);
let value = AsyncDerived::new(move || async move {
sleep(Duration::from_millis(25)).await;
Executor::tick().await;
signal.get()
});
assert_eq!(value.await, 10);
signal.set(30);
sleep(Duration::from_millis(5)).await;
Executor::tick().await;
assert_eq!(value.await, 30);
signal.set(50);
sleep(Duration::from_millis(5)).await;
Executor::tick().await;
assert_eq!(value.await, 50);
}

View file

@ -10,10 +10,6 @@ use std::{
};
use tokio::task;
pub async fn tick() {
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
}
#[cfg(feature = "effects")]
#[tokio::test]
async fn render_effect_runs() {
@ -35,13 +31,13 @@ async fn render_effect_runs() {
}
}));
tick().await;
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "Value is -1");
println!("setting to 1");
a.set(1);
tick().await;
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "Value is 1");
})
.await;
@ -67,13 +63,13 @@ async fn effect_runs() {
}
});
tick().await;
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "Value is -1");
println!("setting to 1");
a.set(1);
tick().await;
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "Value is 1");
})
.await
@ -104,42 +100,42 @@ async fn dynamic_dependencies() {
}
}));
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 1);
println!("\nsetting `first` to Bob");
first.set("Bob");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 2);
println!("\nsetting `last` to Bob");
last.set("Thompson");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 3);
println!("\nsetting `use_last` to false");
use_last.set(false);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
println!("\nsetting `last` to Jones");
last.set("Jones");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
println!("\nsetting `last` to Jones");
last.set("Smith");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
println!("\nsetting `last` to Stevens");
last.set("Stevens");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
println!("\nsetting `use_last` to true");
use_last.set(true);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 5);
})
.await

View file

@ -11,10 +11,6 @@ use std::{
};
use tokio::task;
pub async fn tick() {
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
}
#[test]
fn memo_calculates_value() {
let a = RwSignal::new(1);
@ -201,14 +197,14 @@ async fn dynamic_dependencies() {
*combined_count.write().unwrap() += 1;
}
}));
tick().await;
Executor::tick().await;
println!("[After 1 tick]");
assert_eq!(*combined_count.read().unwrap(), 1);
println!("[Set 'Bob']");
first.set("Bob");
tick().await;
Executor::tick().await;
assert_eq!(name.get_untracked(), "Bob Johnston");
@ -216,32 +212,32 @@ async fn dynamic_dependencies() {
println!("[Set 'Thompson']");
last.set("Thompson");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 3);
use_last.set(false);
tick().await;
Executor::tick().await;
assert_eq!(name.get_untracked(), "Bob");
assert_eq!(*combined_count.read().unwrap(), 4);
assert_eq!(*combined_count.read().unwrap(), 4);
last.set("Jones");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
last.set("Smith");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
last.set("Stevens");
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 4);
use_last.set(true);
tick().await;
Executor::tick().await;
assert_eq!(name.get_untracked(), "Bob Stevens");
assert_eq!(*combined_count.read().unwrap(), 5);
@ -269,19 +265,19 @@ async fn render_effect_doesnt_rerun_if_memo_didnt_change() {
}
}));
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 1);
println!("[done]\n");
println!("\n[Set Signal to 2]");
count.set(2);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 2);
println!("[done]\n");
println!("\n[Set Signal to 4]");
count.set(4);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 2);
println!("[done]\n");
})
@ -308,15 +304,15 @@ async fn effect_doesnt_rerun_if_memo_didnt_change() {
}
});
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 1);
count.set(2);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 2);
count.set(4);
tick().await;
Executor::tick().await;
assert_eq!(*combined_count.read().unwrap(), 2);
})
.await