mirror of
https://github.com/zaphar/sycamore-state.git
synced 2025-07-22 20:29:50 -04:00
Testing infrastructure and value getter
This commit is contained in:
parent
66d1307f1b
commit
f74a051bf8
@ -6,4 +6,11 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
sycamore = "0.8"
|
||||
wasm-bindgen-test = "0.3"
|
||||
wasm-bindgen = "0.2.83"
|
||||
|
||||
[dependencies.sycamore]
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
async = ["sycamore/suspense"]
|
18
src/lib.rs
18
src/lib.rs
@ -18,8 +18,8 @@ use sycamore::prelude::*;
|
||||
/// Trait that maps a message and an original state value to a new value.
|
||||
/// Implementors of this trait can implement all of their state management
|
||||
/// logic in one place.
|
||||
pub trait MessageMapper<Msg, Out> {
|
||||
fn map(&self, msg: Msg, original: &ReadSignal<Out>) -> Out;
|
||||
pub trait MessageMapper<Msg, Val> {
|
||||
fn map<'ctx>(&self, cx: Scope<'ctx>, msg: Msg, original: &'ctx Signal<Val>);
|
||||
}
|
||||
|
||||
/// Provides the necessary wiring for a centralized state handling
|
||||
@ -55,8 +55,8 @@ where
|
||||
}
|
||||
|
||||
/// Directly handle a state message without requiring a binding.
|
||||
pub fn dispatch(&self, msg: Msg) {
|
||||
self.signal.set(self.dispatcher.map(msg, self.signal))
|
||||
pub fn dispatch(&'ctx self, cx: Scope<'ctx>, msg: Msg) {
|
||||
self.dispatcher.map(cx, msg, self.signal)
|
||||
}
|
||||
|
||||
/// Provides a ReadSignal handle for the contained Signal implementation.
|
||||
@ -74,7 +74,7 @@ where
|
||||
) where
|
||||
F: Fn(Rc<Val>) -> Msg + 'ctx,
|
||||
{
|
||||
create_effect(cx, move || self.dispatch(message_fn(trigger.get())));
|
||||
create_effect(cx, move || self.dispatch(cx, message_fn(trigger.get())));
|
||||
}
|
||||
|
||||
/// Helper method to get a memoized value derived from the contained
|
||||
@ -91,6 +91,14 @@ where
|
||||
{
|
||||
create_selector(cx, move || selector_factory(self.signal))
|
||||
}
|
||||
|
||||
// Helper method to get a non reactive value from the state.
|
||||
pub fn get_value<F, Val>(&'ctx self, getter_factory: F) -> Val
|
||||
where
|
||||
F: Fn(&'ctx ReadSignal<T>) -> Val + 'ctx,
|
||||
{
|
||||
getter_factory(self.signal)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -12,6 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use super::*;
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
|
||||
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
pub enum Msg {
|
||||
UpdateOne(String),
|
||||
@ -40,8 +43,8 @@ where
|
||||
pub struct StateMachine();
|
||||
|
||||
impl MessageMapper<Msg, FakeState> for StateMachine {
|
||||
fn map(&self, msg: Msg, original: &ReadSignal<FakeState>) -> FakeState {
|
||||
match msg {
|
||||
fn map(&self, _cx: Scope, msg: Msg, original: &Signal<FakeState>) {
|
||||
let new_state = match msg {
|
||||
Msg::UpdateOne(val) => {
|
||||
let mut new_state = original.get().as_ref().clone();
|
||||
new_state.value_one = val;
|
||||
@ -52,7 +55,8 @@ impl MessageMapper<Msg, FakeState> for StateMachine {
|
||||
new_state.value_two = val;
|
||||
new_state
|
||||
}
|
||||
}
|
||||
};
|
||||
original.set(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +69,7 @@ macro_rules! with_scope {
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[wasm_bindgen_test]
|
||||
fn test_state_effect_flow() {
|
||||
with_scope! {cx,
|
||||
let state = FakeState {
|
||||
@ -94,3 +98,38 @@ fn test_state_effect_flow() {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[wasm_bindgen_test]
|
||||
fn test_state_effect_flow_async() {
|
||||
use sycamore::futures::spawn_local_scoped;
|
||||
with_scope! {cx,
|
||||
let state = FakeState {
|
||||
value_one: "foo".to_owned(),
|
||||
value_two: 0,
|
||||
};
|
||||
|
||||
let handler = Handler::new(cx, state, StateMachine());
|
||||
|
||||
create_child_scope(cx, |cx| {
|
||||
let form_val = create_signal(cx, handler.read_signal().get_untracked().value_one.clone());
|
||||
|
||||
handler.bind_trigger(cx, form_val, |val| Msg::UpdateOne((*val).clone()));
|
||||
|
||||
form_val.set("bar".to_owned());
|
||||
|
||||
assert_eq!(handler.read_signal().get_untracked().value_one, "bar".to_owned());
|
||||
|
||||
create_child_scope(cx, |cx| {
|
||||
let form_val = create_signal(cx, 0);
|
||||
|
||||
handler.bind_trigger(cx, form_val, |val| Msg::UpdateTwo(*val));
|
||||
|
||||
spawn_local_scoped(cx, async {
|
||||
form_val.set(1);
|
||||
assert_eq!(handler.read_signal().get_untracked().value_two, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user