//! Configurable IOInterface stub, equivalent to PHPUnit's //! `getMockBuilder(IOInterface::class)->getMock()` where individual methods are //! configured via `->method('x')->willReturn(y)`. //! //! Each configurable method is backed by an `Option` field plus a //! builder-style setter. Unset methods fall back to NullIO-equivalent defaults. #![allow(dead_code)] use shirabe::config::Config; use shirabe::io::{BaseIO, IOInterface, IOInterfaceImmutable, IOInterfaceMutable}; use shirabe_php_shim::PhpMixed; #[derive(Debug, Default)] pub struct IOStub { authentications: indexmap::IndexMap>>, is_interactive: Option, is_decorated: Option, is_verbose: Option, is_very_verbose: Option, is_debug: Option, // `hasAuthentication` is keyed: PHPUnit tests usually configure a single bool // willReturn that applies to any argument, so a single Option matches. has_authentication: Option, // `getAuthentication` willReturn is a `['username' => ..., 'password' => ...]` array. get_authentication: Option>>, ask: Option, ask_confirmation: Option, ask_and_hide_answer: Option>, } impl IOStub { pub fn new() -> Self { Self::default() } pub fn with_is_interactive(mut self, value: bool) -> Self { self.is_interactive = Some(value); self } pub fn with_is_decorated(mut self, value: bool) -> Self { self.is_decorated = Some(value); self } pub fn with_is_verbose(mut self, value: bool) -> Self { self.is_verbose = Some(value); self } pub fn with_is_very_verbose(mut self, value: bool) -> Self { self.is_very_verbose = Some(value); self } pub fn with_is_debug(mut self, value: bool) -> Self { self.is_debug = Some(value); self } pub fn with_has_authentication(mut self, value: bool) -> Self { self.has_authentication = Some(value); self } pub fn with_get_authentication( mut self, value: indexmap::IndexMap>, ) -> Self { self.get_authentication = Some(value); self } pub fn with_ask(mut self, value: PhpMixed) -> Self { self.ask = Some(value); self } pub fn with_ask_confirmation(mut self, value: bool) -> Self { self.ask_confirmation = Some(value); self } pub fn with_ask_and_hide_answer(mut self, value: Option) -> Self { self.ask_and_hide_answer = Some(value); self } } impl IOInterfaceImmutable for IOStub { fn is_interactive(&self) -> bool { self.is_interactive.unwrap_or(false) } fn is_verbose(&self) -> bool { self.is_verbose.unwrap_or(false) } fn is_very_verbose(&self) -> bool { self.is_very_verbose.unwrap_or(false) } fn is_debug(&self) -> bool { self.is_debug.unwrap_or(false) } fn is_decorated(&self) -> bool { self.is_decorated.unwrap_or(false) } fn write3(&self, _message: &str, _newline: bool, _verbosity: i64) {} fn write_error3(&self, _message: &str, _newline: bool, _verbosity: i64) {} fn write_raw3(&self, _message: &str, _newline: bool, _verbosity: i64) {} fn write_error_raw3(&self, _message: &str, _newline: bool, _verbosity: i64) {} fn overwrite4(&self, _message: &str, _newline: bool, _size: Option, _verbosity: i64) {} fn overwrite_error4( &self, _message: &str, _newline: bool, _size: Option, _verbosity: i64, ) { } fn ask(&self, _question: String, default: PhpMixed) -> PhpMixed { self.ask.clone().unwrap_or(default) } fn ask_confirmation(&self, _question: String, default: bool) -> bool { self.ask_confirmation.unwrap_or(default) } fn ask_and_validate( &self, _question: String, _validator: Box anyhow::Result>, _attempts: Option, default: PhpMixed, ) -> anyhow::Result { Ok(default) } fn ask_and_hide_answer(&self, _question: String) -> Option { self.ask_and_hide_answer.clone().unwrap_or(None) } fn select( &self, _question: String, _choices: Vec, default: PhpMixed, _attempts: PhpMixed, _error_message: String, _multiselect: bool, ) -> PhpMixed { default } fn get_authentications( &self, ) -> indexmap::IndexMap>> { ::get_authentications(self) } fn has_authentication(&self, repository_name: &str) -> bool { match self.has_authentication { Some(value) => value, None => ::has_authentication(self, repository_name), } } fn get_authentication( &self, repository_name: &str, ) -> indexmap::IndexMap> { match &self.get_authentication { Some(value) => value.clone(), None => ::get_authentication(self, repository_name), } } fn error(&self, message: &str, context: &[(&str, &str)]) { ::error(self, message, context); } fn warning(&self, message: &str, context: &[(&str, &str)]) { ::warning(self, message, context); } fn debug(&self, message: &str, context: &[(&str, &str)]) { ::debug(self, message, context); } } impl IOInterfaceMutable for IOStub { fn set_authentication( &mut self, repository_name: String, username: String, password: Option, ) { ::set_authentication(self, repository_name, username, password) } fn load_configuration(&mut self, config: &mut Config) -> anyhow::Result<()> { ::load_configuration(self, config) } } impl IOInterface for IOStub { fn as_any(&self) -> &dyn std::any::Any { self } fn as_base_io_mut(&mut self) -> Option<&mut dyn BaseIO> { Some(self) } } impl BaseIO for IOStub { fn authentications( &self, ) -> &indexmap::IndexMap>> { &self.authentications } fn authentications_mut( &mut self, ) -> &mut indexmap::IndexMap>> { &mut self.authentications } }