From 31b4bffe129eac30d2322eb114254d9ef6d5c743 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 20 Jul 2026 03:48:34 +0900 Subject: fix(event-dispatcher): un-ignore test_dispatcher_outputs_command The ignore reason went stale: the getListeners override seam and a real ProcessExecutor wired to the IO already cover the PHP setup, and IOStub is the PHPUnit IOInterface-mock equivalent. IOStub now records writeError calls (writeRaw was already recorded) so the expects(once)->with(...) spies on writeError/writeRaw can be reproduced as call-list equality assertions. Co-Authored-By: Claude Fable 5 --- crates/shirabe/tests/common/io_stub.rs | 11 +++++- .../event_dispatcher/event_dispatcher_test.rs | 43 ++++++++++++++++++++-- crates/shirabe/tests/event_dispatcher/main.rs | 2 + 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/crates/shirabe/tests/common/io_stub.rs b/crates/shirabe/tests/common/io_stub.rs index d8c60799..d582447c 100644 --- a/crates/shirabe/tests/common/io_stub.rs +++ b/crates/shirabe/tests/common/io_stub.rs @@ -53,6 +53,8 @@ pub struct IOStub { // `switch` default. ask_and_hide_answer_responses: Option>, + // Records `writeError` calls. + write_error_calls: CallRecorder<(String, bool)>, // Records `writeRaw` calls. write_raw_calls: CallRecorder<(String, bool)>, // Records `setAuthentication` calls. Kept separate from `authentications` so @@ -149,6 +151,11 @@ impl IOStub { self } + // For testing only. Returns the recorded `writeError` calls in call order. + pub fn write_error_calls(&self) -> Vec<(String, bool)> { + self.write_error_calls.calls() + } + // For testing only. Returns the recorded `writeRaw` calls in call order. pub fn write_raw_calls(&self) -> Vec<(String, bool)> { self.write_raw_calls.calls() @@ -193,7 +200,9 @@ impl IOInterfaceImmutable for IOStub { } fn write3(&self, _message: &str, _newline: bool, _verbosity: i64) {} - fn write_error3(&self, _message: &str, _newline: bool, _verbosity: i64) {} + fn write_error3(&self, message: &str, newline: bool, _verbosity: i64) { + self.write_error_calls.push((message.to_string(), newline)); + } fn write_raw3(&self, message: &str, newline: bool, _verbosity: i64) { self.write_raw_calls.push((message.to_string(), newline)); } diff --git a/crates/shirabe/tests/event_dispatcher/event_dispatcher_test.rs b/crates/shirabe/tests/event_dispatcher/event_dispatcher_test.rs index 0f392d7e..c5caf9f3 100644 --- a/crates/shirabe/tests/event_dispatcher/event_dispatcher_test.rs +++ b/crates/shirabe/tests/event_dispatcher/event_dispatcher_test.rs @@ -396,12 +396,47 @@ fn test_dispatcher_support_for_additional_args() { } #[test] -#[ignore = "uses an unmocked ProcessExecutor running a real `echo foo` and a PHPUnit IO spy on writeError/writeRaw; no real-shell-output IO mocking exists"] +#[serial] fn test_dispatcher_outputs_command() { let _tear_down = TearDown; - // TODO(phase-d): uses an unmocked ProcessExecutor running a real `echo foo` and a PHPUnit IO - // spy on writeError/writeRaw; no real-shell-output IO mocking exists - todo!() + + let composer = create_composer_instance(); + let io = std::rc::Rc::new(std::cell::RefCell::new(crate::io_stub::IOStub::new())); + let io_dyn: std::rc::Rc> = io.clone(); + let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some( + io_dyn.clone(), + )))); + + let mut dispatcher = dispatcher_with_listeners( + &composer, + io_dyn, + process, + listeners_const(vec!["echo foo"]), + ); + + dispatcher + .dispatch_script( + ScriptEvents::POST_INSTALL_CMD, + false, + vec![], + IndexMap::new(), + ) + .unwrap(); + + // ref: $io->expects($this->once())->method('writeError')->with('> echo foo') + let write_error_messages: Vec = io + .borrow() + .write_error_calls() + .into_iter() + .map(|(message, _newline)| message) + .collect(); + assert_eq!(write_error_messages, vec!["> echo foo".to_string()]); + + // ref: $io->expects($this->once())->method('writeRaw')->with('foo'.PHP_EOL, false) + assert_eq!( + io.borrow().write_raw_calls(), + vec![(format!("foo{PHP_EOL}"), false)] + ); } #[test] diff --git a/crates/shirabe/tests/event_dispatcher/main.rs b/crates/shirabe/tests/event_dispatcher/main.rs index 0ff669ab..eac717d7 100644 --- a/crates/shirabe/tests/event_dispatcher/main.rs +++ b/crates/shirabe/tests/event_dispatcher/main.rs @@ -1,3 +1,5 @@ +#[path = "../common/io_stub.rs"] +mod io_stub; #[path = "../common/process_executor_mock.rs"] mod process_executor_mock; -- cgit v1.3.1