use super::super::effect::{
AppEffect, AppEffectHandler, AppEffectResult, CommitResult, RebaseResult,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Default)]
pub struct MockAppEffectHandler {
pub(super) captured_effects: RefCell<Vec<AppEffect>>,
pub(super) files: RefCell<HashMap<PathBuf, String>>,
pub(super) cwd: RefCell<PathBuf>,
pub(super) repo_exists: RefCell<bool>,
pub(super) head_oid: RefCell<String>,
pub(super) default_branch: RefCell<String>,
pub(super) is_main_branch: RefCell<bool>,
pub(super) env_vars: RefCell<HashMap<String, String>>,
pub(super) log_messages: RefCell<Vec<(String, String)>>,
pub(super) diff_output: RefCell<String>,
pub(super) snapshot_output: RefCell<String>,
pub(super) staged_changes: RefCell<bool>,
pub(super) conflicted_files: RefCell<Vec<String>>,
pub(super) rebase_result: RefCell<Option<RebaseResult>>,
}
impl MockAppEffectHandler {
#[must_use]
pub fn new() -> Self {
Self {
captured_effects: RefCell::new(Vec::new()),
files: RefCell::new(HashMap::new()),
cwd: RefCell::new(PathBuf::from("/")),
repo_exists: RefCell::new(true),
head_oid: RefCell::new("0000000".to_string()),
default_branch: RefCell::new("main".to_string()),
is_main_branch: RefCell::new(false),
env_vars: RefCell::new(HashMap::new()),
log_messages: RefCell::new(Vec::new()),
diff_output: RefCell::new(String::new()),
snapshot_output: RefCell::new(String::new()),
staged_changes: RefCell::new(true),
conflicted_files: RefCell::new(Vec::new()),
rebase_result: RefCell::new(None),
}
}
}
impl AppEffectHandler for MockAppEffectHandler {
fn execute(&mut self, effect: AppEffect) -> AppEffectResult {
self.captured_effects.borrow_mut().push(effect.clone());
match effect {
AppEffect::SetCurrentDir { path } => {
*self.cwd.borrow_mut() = path;
AppEffectResult::Ok
}
AppEffect::WriteFile { path, content } => {
self.files.borrow_mut().insert(path, content);
AppEffectResult::Ok
}
AppEffect::ReadFile { path } => self.files.borrow().get(&path).map_or_else(
|| AppEffectResult::Error(format!("File not found: {}", path.display())),
|content| AppEffectResult::String(content.clone()),
),
AppEffect::DeleteFile { path } => {
if self.files.borrow_mut().remove(&path).is_some() {
AppEffectResult::Ok
} else {
AppEffectResult::Error(format!("File not found: {}", path.display()))
}
}
AppEffect::CreateDir { path: _ } => {
AppEffectResult::Ok
}
AppEffect::PathExists { path } => {
AppEffectResult::Bool(self.files.borrow().contains_key(&path))
}
AppEffect::SetReadOnly {
path: _,
readonly: _,
} => {
AppEffectResult::Ok
}
AppEffect::GitRequireRepo => {
if *self.repo_exists.borrow() {
AppEffectResult::Ok
} else {
AppEffectResult::Error("Not in a git repository".to_string())
}
}
AppEffect::GitGetRepoRoot => {
if *self.repo_exists.borrow() {
AppEffectResult::Path(self.cwd.borrow().clone())
} else {
AppEffectResult::Error("Not in a git repository".to_string())
}
}
AppEffect::GitGetHeadOid => AppEffectResult::String(self.head_oid.borrow().clone()),
AppEffect::GitDiff
| AppEffect::GitDiffFrom { start_oid: _ }
| AppEffect::GitDiffFromStart => {
AppEffectResult::String(self.diff_output.borrow().clone())
}
AppEffect::GitSnapshot => {
AppEffectResult::String(self.snapshot_output.borrow().clone())
}
AppEffect::GitAddAll => AppEffectResult::Bool(*self.staged_changes.borrow()),
AppEffect::GitCommit {
message: _,
user_name: _,
user_email: _,
} => {
if *self.staged_changes.borrow() {
let oid = self.head_oid.borrow().clone();
AppEffectResult::Commit(CommitResult::Success(oid))
} else {
AppEffectResult::Commit(CommitResult::NoChanges)
}
}
AppEffect::GitSaveStartCommit => {
let oid = self.head_oid.borrow().clone();
self.files
.borrow_mut()
.insert(PathBuf::from(".agent/start_commit"), oid.clone());
AppEffectResult::String(oid)
}
AppEffect::GitResetStartCommit => {
let oid = self.head_oid.borrow().clone();
self.files
.borrow_mut()
.insert(PathBuf::from(".agent/start_commit"), oid.clone());
AppEffectResult::String(oid)
}
AppEffect::GitRebaseOnto { upstream_branch: _ } => self
.rebase_result
.borrow()
.clone()
.map_or(AppEffectResult::Rebase(RebaseResult::Success), |result| {
AppEffectResult::Rebase(result)
}),
AppEffect::GitGetConflictedFiles => {
AppEffectResult::StringList(self.conflicted_files.borrow().clone())
}
AppEffect::GitContinueRebase | AppEffect::GitAbortRebase => AppEffectResult::Ok,
AppEffect::GitGetDefaultBranch => {
AppEffectResult::String(self.default_branch.borrow().clone())
}
AppEffect::GitIsMainBranch => AppEffectResult::Bool(*self.is_main_branch.borrow()),
AppEffect::GetEnvVar { name } => self.env_vars.borrow().get(&name).map_or_else(
|| AppEffectResult::Error(format!("Environment variable '{name}' not set")),
|value| AppEffectResult::String(value.clone()),
),
AppEffect::SetEnvVar { name, value } => {
self.env_vars.borrow_mut().insert(name, value);
AppEffectResult::Ok
}
AppEffect::LogInfo { message } => {
self.log_messages
.borrow_mut()
.push(("info".to_string(), message));
AppEffectResult::Ok
}
AppEffect::LogSuccess { message } => {
self.log_messages
.borrow_mut()
.push(("success".to_string(), message));
AppEffectResult::Ok
}
AppEffect::LogWarn { message } => {
self.log_messages
.borrow_mut()
.push(("warn".to_string(), message));
AppEffectResult::Ok
}
AppEffect::LogError { message } => {
self.log_messages
.borrow_mut()
.push(("error".to_string(), message));
AppEffectResult::Ok
}
}
}
}