diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-26 02:23:58 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-26 02:23:58 +0900 |
| commit | 6c89c720d9e4728c288e3c66ffb7dcb4cba5121c (patch) | |
| tree | 4697f897302425df1b57eb87bf9441308530d0bf /crates/shirabe/tests/command/global_command_test.rs | |
| parent | 4bd544608e4934fff4463fd6b104d06162a51ba0 (diff) | |
| download | php-shirabe-6c89c720d9e4728c288e3c66ffb7dcb4cba5121c.tar.gz php-shirabe-6c89c720d9e4728c288e3c66ffb7dcb4cba5121c.tar.zst php-shirabe-6c89c720d9e4728c288e3c66ffb7dcb4cba5121c.zip | |
test(command): port show/remove/global/audit/check-platform-reqs/status/self-update/validate tests
Faithfully port the remaining stubbed command test bodies from their PHP
counterparts (expected values verbatim). Newly passing: remove (6), global (2),
check-platform-reqs (1), status (1), audit (1), self-update (1).
Tests whose ported bodies reach a genuine unported src path keep faithful bodies
but stay #[ignore] with precise reasons. Dominant blockers surfaced:
- ShowCommand::configure stub (empty set_definition) blocks all 42 show tests
- Composer-handle RefCell re-entrancy in the Installer (composer.rs:500) and
Factory::create_composer (composer.rs:446) paths
- check_platform_reqs nests InstalledRepository in InstalledRepository
- audit's non-locked branch (audit_command.rs:285) and write_error3 re-entrancy
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/command/global_command_test.rs')
| -rw-r--r-- | crates/shirabe/tests/command/global_command_test.rs | 369 |
1 files changed, 337 insertions, 32 deletions
diff --git a/crates/shirabe/tests/command/global_command_test.rs b/crates/shirabe/tests/command/global_command_test.rs index 0b62150..6eec017 100644 --- a/crates/shirabe/tests/command/global_command_test.rs +++ b/crates/shirabe/tests/command/global_command_test.rs @@ -1,80 +1,385 @@ //! ref: composer/tests/Composer/Test/Command/GlobalCommandTest.php +use crate::test_case::{ + RunOptions, create_composer_lock, create_installed_json, get_application_tester, + get_complete_package, get_package, init_temp_composer, +}; +use serial_test::serial; use shirabe::util::platform::Platform; +use shirabe_php_shim::PhpMixed; +use std::path::PathBuf; +use tempfile::TempDir; -fn tear_down() { - Platform::clear_env("COMPOSER_HOME"); - Platform::clear_env("COMPOSER"); -} - -struct TearDown; +/// ref: GlobalCommandTest::tearDown (the COMPOSER part; COMPOSER_HOME is restored by the +/// `init_temp_composer` guard). +struct EnvGuard; -impl Drop for TearDown { +impl Drop for EnvGuard { fn drop(&mut self) { - tear_down(); + Platform::clear_env("COMPOSER"); } } +/// ref: TestCase::getUniqueTmpDirectory followed by `chdir($dir)`. +/// +/// Returns the temp dir guard (kept alive by the caller so it is removed at end of scope). +fn chdir_unique_tmp_directory() -> TempDir { + let test_dir = TempDir::new().unwrap(); + std::env::set_current_dir(test_dir.path()).unwrap(); + test_dir +} + #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer/getUniqueTmpDirectory harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let script = r#"@php -r "echo 'COMPOSER SCRIPT OUTPUT: '.getenv('COMPOSER') . PHP_EOL;""#; + let fake_composer = "TMP_COMPOSER.JSON"; + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "scripts": { + "test-script": script, + }, + })), + None, + None, + true, + ); + let composer_home: PathBuf = tear_down.working_dir(); + let composer_home_str = composer_home.to_string_lossy().to_string(); - todo!() + Platform::put_env("COMPOSER_HOME", &composer_home_str); + Platform::put_env("COMPOSER", fake_composer); + + let _test_dir = chdir_unique_tmp_directory(); + + let mut app_tester = get_application_tester(); + let _ = app_tester.run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + ( + PhpMixed::from("command-name"), + PhpMixed::from("test-script"), + ), + (PhpMixed::from("--no-interaction"), PhpMixed::from(true)), + ], + RunOptions::default(), + ); + + let display = app_tester.get_display(); + + assert_eq!( + format!( + "Changed current directory to {}\nCOMPOSER SCRIPT OUTPUT: \n", + composer_home_str + ), + display + ); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::getUniqueTmpDirectory harness (not implemented)"] +#[serial] fn test_cannot_create_home() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let dir = TempDir::new().unwrap(); + let filename = dir.path().join("file"); + std::fs::write(&filename, "").unwrap(); + let filename_str = filename.to_string_lossy().to_string(); - todo!() + Platform::put_env("COMPOSER_HOME", &filename_str); + + let mut app_tester = get_application_tester(); + let err = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + ( + PhpMixed::from("command-name"), + PhpMixed::from("test-script"), + ), + (PhpMixed::from("--no-interaction"), PhpMixed::from(true)), + ], + RunOptions::default(), + ) + .expect_err("expected RuntimeException for a non-directory COMPOSER_HOME"); + + assert!( + err.to_string() + .contains(&format!("{} exists and is not a directory.", filename_str)), + "got: {}", + err + ); + + Platform::clear_env("COMPOSER_HOME"); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer/createInstalledJson harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global_show() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "repositories": { + "packages": { + "type": "package", + "package": [ + {"name": "vendor/global-tool", "version": "1.0.0"}, + ], + }, + }, + "require": { + "vendor/global-tool": "1.0.0", + }, + })), + None, + None, + true, + ); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + let pkg = get_complete_package("vendor/global-tool", "1.0.0"); + pkg.set_description("A globally installed tool".to_string()); + create_installed_json(&[pkg.into()], &[], true); - todo!() + Platform::put_env("COMPOSER_HOME", &composer_home_str); + + let _test_dir = chdir_unique_tmp_directory(); + + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let _ = app_tester.run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + (PhpMixed::from("command-name"), PhpMixed::from("show")), + ], + RunOptions::default(), + ); + + let output = app_tester.get_display(); + assert!(output.contains("vendor/global-tool"), "got: {}", output); + assert!(output.contains("1.0.0"), "got: {}", output); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer/createInstalledJson harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global_show_without_packages() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer(None, None, None, true); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + create_installed_json(&[], &[], true); - todo!() + Platform::put_env("COMPOSER_HOME", &composer_home_str); + + let _test_dir = chdir_unique_tmp_directory(); + + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + (PhpMixed::from("command-name"), PhpMixed::from("show")), + ], + RunOptions::default(), + ) + .unwrap(); + + assert_eq!(0, status_code); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global_require() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "repositories": { + "packages": { + "type": "package", + "package": [ + { + "name": "vendor/required-pkg", + "version": "2.0.0", + "dist": {"type": "file", "url": file!()}, + }, + ], + }, + }, + })), + None, + None, + true, + ); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + Platform::put_env("COMPOSER_HOME", &composer_home_str); - todo!() + let _test_dir = chdir_unique_tmp_directory(); + + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + (PhpMixed::from("command-name"), PhpMixed::from("require")), + ( + PhpMixed::from("packages"), + PhpMixed::List(vec![PhpMixed::from("vendor/required-pkg:2.0.0")]), + ), + ], + RunOptions::default(), + ) + .unwrap(); + + assert_eq!(0, status_code); + assert!( + app_tester + .get_display() + .contains("Installing vendor/required-pkg"), + "got: {}", + app_tester.get_display() + ); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer/createInstalledJson/createComposerLock harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global_update() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "repositories": { + "packages": { + "type": "package", + "package": [ + {"name": "vendor/pkg", "version": "1.0.0"}, + ], + }, + }, + "require": { + "vendor/pkg": "1.0.0", + }, + })), + None, + None, + true, + ); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + let pkg = get_package("vendor/pkg", "1.0.0"); + create_installed_json(&[pkg.clone()], &[], true); + create_composer_lock(&[pkg], &[]); + + Platform::put_env("COMPOSER_HOME", &composer_home_str); - todo!() + let _test_dir = chdir_unique_tmp_directory(); + + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + (PhpMixed::from("command-name"), PhpMixed::from("update")), + ], + RunOptions::default(), + ) + .unwrap(); + + assert_eq!(0, status_code); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer harness (not implemented)"] +#[serial] +#[ignore = "GlobalCommand::run proxies to Application::run via todo!() at crates/shirabe/src/command/global_command.rs:190 (pending shared Application handle)"] fn test_global_changes_directory() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "name": "test/global", + })), + None, + None, + true, + ); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + Platform::put_env("COMPOSER_HOME", &composer_home_str); + + let _test_dir = chdir_unique_tmp_directory(); - todo!() + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let _ = app_tester.run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("global")), + (PhpMixed::from("command-name"), PhpMixed::from("config")), + (PhpMixed::from("setting-key"), PhpMixed::from("name")), + ], + RunOptions::default(), + ); + + let output = app_tester.get_display(); + assert!( + output.contains(&format!( + "Changed current directory to {}", + composer_home_str + )), + "got: {}", + output + ); + + drop(tear_down); } #[test] -#[ignore = "requires ApplicationTester and TestCase::initTempComposer harness (not implemented)"] +#[serial] fn test_global_missing_command_name() { - let _tear_down = TearDown; + let _env_guard = EnvGuard; + + let tear_down = init_temp_composer(None, None, None, true); + let composer_home_str = tear_down.working_dir().to_string_lossy().to_string(); + + Platform::put_env("COMPOSER_HOME", &composer_home_str); + + let mut app_tester = get_application_tester(); + app_tester.set_inputs(vec!["".to_string()]); + let err = app_tester + .run( + vec![(PhpMixed::from("command"), PhpMixed::from("global"))], + RunOptions::default(), + ) + .expect_err("expected a RuntimeException for the missing command-name argument"); + + assert!( + err.to_string() + .contains("Not enough arguments (missing: \"command-name\")"), + "got: {}", + err + ); - todo!() + drop(tear_down); } |
