aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/command/global_command_test.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-26 02:23:58 +0900
committernsfisis <nsfisis@gmail.com>2026-06-26 02:23:58 +0900
commit6c89c720d9e4728c288e3c66ffb7dcb4cba5121c (patch)
tree4697f897302425df1b57eb87bf9441308530d0bf /crates/shirabe/tests/command/global_command_test.rs
parent4bd544608e4934fff4463fd6b104d06162a51ba0 (diff)
downloadphp-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.rs369
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);
}