leptos/reactive_graph/tests/watch.rs

232 lines
6.1 KiB
Rust

#[cfg(feature = "effects")]
use any_spawner::Executor;
#[cfg(feature = "effects")]
use reactive_graph::{effect::Effect, prelude::*, signal::RwSignal};
#[cfg(feature = "effects")]
use std::sync::{Arc, RwLock};
#[cfg(feature = "effects")]
use tokio::task;
#[cfg(feature = "effects")]
#[tokio::test]
async fn watch_runs() {
_ = Executor::init_tokio();
task::LocalSet::new()
.run_until(async {
let a = RwSignal::new(-1);
// simulate an arbitrary side effect
let b = Arc::new(RwLock::new(String::new()));
let effect = Effect::watch(
move || a.get(),
{
let b = b.clone();
move |a, prev_a, prev_ret| {
let formatted = format!(
"Value is {a}; Prev is {prev_a:?}; Prev return is \
{prev_ret:?}"
);
*b.write().unwrap() = formatted;
a + 10
}
},
false,
);
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "");
a.set(1);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is 1; Prev is Some(-1); Prev return is None"
);
a.set(2);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is 2; Prev is Some(1); Prev return is Some(11)"
);
effect.stop();
*b.write().unwrap() = "nothing happened".to_string();
a.set(3);
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "nothing happened");
})
.await
}
#[cfg(feature = "effects")]
#[tokio::test]
async fn watch_runs_immediately() {
_ = Executor::init_tokio();
task::LocalSet::new()
.run_until(async {
let a = RwSignal::new(-1);
// simulate an arbitrary side effect
let b = Arc::new(RwLock::new(String::new()));
Effect::watch(
move || a.get(),
{
let b = b.clone();
move |a, prev_a, prev_ret| {
let formatted = format!(
"Value is {a}; Prev is {prev_a:?}; Prev return is \
{prev_ret:?}"
);
*b.write().unwrap() = formatted;
a + 10
}
},
true,
);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is -1; Prev is None; Prev return is None"
);
a.set(1);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is 1; Prev is Some(-1); Prev return is Some(9)"
);
})
.await
}
#[cfg(feature = "effects")]
#[tokio::test]
async fn watch_ignores_callback() {
_ = Executor::init_tokio();
task::LocalSet::new()
.run_until(async {
let a = RwSignal::new(-1);
let b = RwSignal::new(0);
// simulate an arbitrary side effect
let s = Arc::new(RwLock::new(String::new()));
Effect::watch(
move || a.get(),
{
let s = s.clone();
move |a, _, _| {
let formatted =
format!("Value a is {a}; Value b is {}", b.get());
*s.write().unwrap() = formatted;
a + 10
}
},
false,
);
Executor::tick().await;
a.set(1);
Executor::tick().await;
assert_eq!(
s.read().unwrap().as_str(),
"Value a is 1; Value b is 0"
);
*s.write().unwrap() = "nothing happened".to_string();
b.set(10);
Executor::tick().await;
assert_eq!(s.read().unwrap().as_str(), "nothing happened");
a.set(2);
Executor::tick().await;
assert_eq!(
s.read().unwrap().as_str(),
"Value a is 2; Value b is 10"
);
})
.await
}
#[cfg(feature = "effects")]
#[tokio::test]
async fn deprecated_watch_runs() {
_ = Executor::init_tokio();
task::LocalSet::new()
.run_until(async {
let a = RwSignal::new(-1);
// simulate an arbitrary side effect
let b = Arc::new(RwLock::new(String::new()));
#[allow(deprecated)]
let effect = reactive_graph::effect::watch(
move || a.get(),
{
let b = b.clone();
move |a, prev_a, prev_ret| {
let formatted = format!(
"Value is {a}; Prev is {prev_a:?}; Prev return is \
{prev_ret:?}"
);
*b.write().unwrap() = formatted;
a + 10
}
},
false,
);
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "");
a.set(1);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is 1; Prev is Some(-1); Prev return is None"
);
a.set(2);
Executor::tick().await;
assert_eq!(
b.read().unwrap().as_str(),
"Value is 2; Prev is Some(1); Prev return is Some(11)"
);
effect();
*b.write().unwrap() = "nothing happened".to_string();
a.set(3);
Executor::tick().await;
assert_eq!(b.read().unwrap().as_str(), "nothing happened");
})
.await
}