use std::collections::VecDeque;
use super::io::CapturedState;
use super::{Effect, PipelineEvent, PipelineState, UIEvent};
pub struct MockEffectHandler {
pub state: PipelineState,
pub(super) captured_state: CapturedState,
pub(super) simulate_empty_diff: bool,
pub(super) simulate_commit_diff_error: Option<String>,
pub(super) simulate_commit_diff_content: Option<String>,
pub(super) staged_diff_contents: VecDeque<String>,
pub(super) simulate_commit_message_xml: Option<String>,
pub(super) pre_termination_snapshot: PreTerminationSnapshotMock,
pub(super) residual_files_pass_1: Option<Vec<String>>,
pub(super) residual_files_pass_2: Option<Vec<String>>,
pub(super) panic_on_next_execute: bool,
pub(super) replay_prompt_keys: Option<std::collections::HashSet<String>>,
}
#[derive(Debug, Clone)]
pub(super) enum PreTerminationSnapshotMock {
Clean,
Dirty {
file_count: usize,
},
Error {
kind: crate::reducer::event::WorkspaceIoErrorKind,
},
}
impl MockEffectHandler {
#[must_use]
pub fn new(state: PipelineState) -> Self {
Self {
state,
captured_state: CapturedState::new(),
simulate_empty_diff: false,
simulate_commit_diff_error: None,
simulate_commit_diff_content: None,
staged_diff_contents: VecDeque::new(),
simulate_commit_message_xml: None,
pre_termination_snapshot: PreTerminationSnapshotMock::Clean,
residual_files_pass_1: None,
residual_files_pass_2: None,
panic_on_next_execute: false,
replay_prompt_keys: None,
}
}
#[must_use]
pub const fn with_empty_diff(mut self) -> Self {
self.simulate_empty_diff = true;
self
}
#[must_use]
pub fn with_commit_diff_error(mut self, message: impl Into<String>) -> Self {
self.simulate_commit_diff_error = Some(message.into());
self
}
#[must_use]
pub fn with_commit_diff_content(mut self, content: impl Into<String>) -> Self {
self.simulate_commit_diff_content = Some(content.into());
self
}
#[must_use]
pub fn with_staged_diff_sequence(
mut self,
contents: impl IntoIterator<Item = impl Into<String>>,
) -> Self {
self.staged_diff_contents = contents.into_iter().map(Into::into).collect();
self
}
#[must_use]
pub fn with_commit_message_xml(mut self, xml: impl Into<String>) -> Self {
self.simulate_commit_message_xml = Some(xml.into());
self
}
#[must_use]
pub fn with_replay_prompt_key(self, key: impl Into<String>) -> Self {
Self {
replay_prompt_keys: Some(
self.replay_prompt_keys
.iter()
.flatten()
.cloned()
.chain(std::iter::once(key.into()))
.collect(),
),
..self
}
}
#[must_use]
pub const fn with_clean_pre_termination_snapshot(mut self) -> Self {
self.pre_termination_snapshot = PreTerminationSnapshotMock::Clean;
self
}
#[must_use]
pub const fn with_dirty_pre_termination_snapshot(mut self, file_count: usize) -> Self {
self.pre_termination_snapshot = PreTerminationSnapshotMock::Dirty { file_count };
self
}
#[must_use]
pub fn with_residual_files_for_pass<I, S>(mut self, pass: u8, files: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
let files: Vec<String> = files.into_iter().map(Into::into).collect();
match pass {
1 => self.residual_files_pass_1 = Some(files),
2.. => self.residual_files_pass_2 = Some(files),
_ => {}
}
self
}
#[must_use]
pub const fn with_pre_termination_snapshot_error(
mut self,
kind: crate::reducer::event::WorkspaceIoErrorKind,
) -> Self {
self.pre_termination_snapshot = PreTerminationSnapshotMock::Error { kind };
self
}
#[must_use]
pub const fn with_panic_on_next_execute(mut self) -> Self {
self.panic_on_next_execute = true;
self
}
pub fn captured_effects(&self) -> Vec<Effect> {
self.captured_state.effects.borrow().clone()
}
pub fn captured_ui_events(&self) -> Vec<UIEvent> {
self.captured_state.ui_events.borrow().clone()
}
pub fn captured_events(&self) -> Vec<PipelineEvent> {
self.captured_state.events.borrow().clone()
}
pub fn was_effect_executed<F>(&self, predicate: F) -> bool
where
F: Fn(&Effect) -> bool,
{
self.captured_state.effects.borrow().iter().any(predicate)
}
pub fn was_ui_event_emitted<F>(&self, predicate: F) -> bool
where
F: Fn(&UIEvent) -> bool,
{
self.captured_state.ui_events.borrow().iter().any(predicate)
}
pub fn was_event_emitted<F>(&self, predicate: F) -> bool
where
F: Fn(&PipelineEvent) -> bool,
{
self.captured_state.events.borrow().iter().any(predicate)
}
pub fn clear_captured(&self) {
self.captured_state.effects.borrow_mut().clear();
self.captured_state.ui_events.borrow_mut().clear();
self.captured_state.events.borrow_mut().clear();
}
pub fn effect_count(&self) -> usize {
self.captured_state.effects.borrow().len()
}
pub fn ui_event_count(&self) -> usize {
self.captured_state.ui_events.borrow().len()
}
pub fn event_count(&self) -> usize {
self.captured_state.events.borrow().len()
}
}