use gstore::{self, Actionable, Keybinding};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct State {
current_page: String,
page_history: Vec<String>,
selection: (u32, u32),
}
impl Default for State {
fn default() -> Self {
Self {
current_page: "home".to_string(),
page_history: vec![],
selection: Default::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Action {
A,
B,
C,
}
impl Actionable for Action {
fn list() -> Vec<Self> {
vec![Action::A, Action::B, Action::C]
}
fn try_from_name(name: &str) -> Option<Self> {
match name {
"a" => Some(Action::A),
"b" => Some(Action::B),
"c" => Some(Action::C),
_ => None,
}
}
fn keybinding(&self) -> Option<Keybinding> {
None
}
fn name(&self) -> &'static str {
match self {
Action::A => "a",
Action::B => "b",
Action::C => "c",
}
}
}
mod dispatch_during_reduce_works_but_is_not_smart {
use std::sync::mpsc::sync_channel;
use super::*;
gstore::store!(Action, State);
#[test]
fn test() {
env_logger::try_init().ok();
let (s, r) = sync_channel(100);
let reduce = store().init(
|a, _| {
println!("Reduce: {:?}", a);
if a == &Action::A {
store().dispatch(Action::C);
store().dispatch(Action::B);
store().dispatch(Action::B);
store().dispatch(Action::C);
store().dispatch(Action::C);
}
},
move |a| {
s.send(a).expect("Failed to send");
},
);
std::thread::spawn(|| {
for _ in 0..5 {
store().dispatch(Action::A);
std::thread::sleep(std::time::Duration::from_millis(10));
store().dispatch(Action::B);
std::thread::sleep(std::time::Duration::from_millis(10));
}
});
println!("waiting for actions");
const EXPECTED: u32 = 35;
let mut actions = Vec::new();
for _ in 0..EXPECTED {
if let Ok(a) = r.recv_timeout(std::time::Duration::from_secs(1)) {
actions.push(a.name());
reduce(a);
} else {
assert!(false, "Test ran into timeout");
}
}
assert_eq!(
actions.join(""),
"a cbbcc ba cbbcc ba cbbcc ba cbbcc ba cbbcc b".replace(" ", "")
)
}
}