use std::any::Any;
use zed::StateManager;
#[derive(Clone, Debug, PartialEq)]
struct TestState {
counter: i32,
name: String,
}
#[derive(Clone, Debug)]
enum TestAction {
Increment,
Decrement,
SetName(String),
Reset,
}
fn test_reducer(state: &TestState, action: &dyn Any) -> TestState {
if let Some(action) = action.downcast_ref::<TestAction>() {
match action {
TestAction::Increment => TestState {
counter: state.counter + 1,
name: state.name.clone(),
},
TestAction::Decrement => TestState {
counter: state.counter - 1,
name: state.name.clone(),
},
TestAction::SetName(name) => TestState {
counter: state.counter,
name: name.clone(),
},
TestAction::Reset => TestState {
counter: 0,
name: "reset".to_string(),
},
}
} else {
state.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_manager_creation() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let manager = StateManager::new(initial_state.clone(), test_reducer);
assert_eq!(manager.current_state(), &initial_state);
}
#[test]
fn test_state_manager_dispatch() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let mut manager = StateManager::new(initial_state, test_reducer);
manager.dispatch(TestAction::Increment);
assert_eq!(manager.current_state().counter, 1);
manager.dispatch(TestAction::Increment);
assert_eq!(manager.current_state().counter, 2);
manager.dispatch(TestAction::Decrement);
assert_eq!(manager.current_state().counter, 1);
}
#[test]
fn test_state_manager_rewind() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let mut manager = StateManager::new(initial_state, test_reducer);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::SetName("test".to_string()));
assert_eq!(manager.current_state().counter, 2);
assert_eq!(manager.current_state().name, "test");
manager.rewind(1);
assert_eq!(manager.current_state().counter, 2);
assert_eq!(manager.current_state().name, "initial");
manager.rewind(2);
assert_eq!(manager.current_state().counter, 0);
assert_eq!(manager.current_state().name, "initial");
}
#[test]
fn test_state_manager_rewind_too_many_steps() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let mut manager = StateManager::new(initial_state.clone(), test_reducer);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::Increment);
manager.rewind(10);
assert_eq!(manager.current_state(), &initial_state);
}
#[test]
fn test_state_manager_branch() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let mut manager = StateManager::new(initial_state, test_reducer);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::Increment);
manager.rewind(1);
let mut branch = manager.branch();
assert_eq!(manager.current_state().counter, 1);
assert_eq!(branch.current_state().counter, 1);
manager.dispatch(TestAction::SetName("original".to_string()));
branch.dispatch(TestAction::SetName("branch".to_string()));
assert_eq!(manager.current_state().name, "original");
assert_eq!(branch.current_state().name, "branch");
}
#[test]
fn test_state_manager_dispatch_after_rewind() {
let initial_state = TestState {
counter: 0,
name: "initial".to_string(),
};
let mut manager = StateManager::new(initial_state, test_reducer);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::Increment);
manager.dispatch(TestAction::Increment);
assert_eq!(manager.current_state().counter, 3);
manager.rewind(2);
assert_eq!(manager.current_state().counter, 1);
manager.dispatch(TestAction::SetName("new_branch".to_string()));
assert_eq!(manager.current_state().counter, 1);
assert_eq!(manager.current_state().name, "new_branch");
manager.dispatch(TestAction::Increment);
assert_eq!(manager.current_state().counter, 2);
}
#[test]
fn test_state_manager_complex_workflow() {
let initial_state = TestState {
counter: 0,
name: "start".to_string(),
};
let mut manager = StateManager::new(initial_state, test_reducer);
for _ in 1..=5 {
manager.dispatch(TestAction::Increment);
}
manager.dispatch(TestAction::SetName("final".to_string()));
assert_eq!(manager.current_state().counter, 5);
assert_eq!(manager.current_state().name, "final");
manager.rewind(3);
assert_eq!(manager.current_state().counter, 3);
assert_eq!(manager.current_state().name, "start");
manager.dispatch(TestAction::SetName("alternative".to_string()));
manager.dispatch(TestAction::Reset);
assert_eq!(manager.current_state().counter, 0);
assert_eq!(manager.current_state().name, "reset");
}
}