diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-11 02:36:42 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-11 02:36:42 +0900 |
| commit | 4e99773a3d203e73b8bf6464490d05649a269fa7 (patch) | |
| tree | 7a6f1a7f773a14ea72dc2f9ff4124badd345833d /crates/mozart/src/commands/remove.rs | |
| parent | 4df5f8491320e5795718cf0222e80fa27e57c8ad (diff) | |
| download | php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.tar.gz php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.tar.zst php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.zip | |
test(commands): remove per-command tests
Diffstat (limited to 'crates/mozart/src/commands/remove.rs')
| -rw-r--r-- | crates/mozart/src/commands/remove.rs | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/crates/mozart/src/commands/remove.rs b/crates/mozart/src/commands/remove.rs index 938a5d1..c5b9ba7 100644 --- a/crates/mozart/src/commands/remove.rs +++ b/crates/mozart/src/commands/remove.rs @@ -676,452 +676,3 @@ async fn remove_unused( Ok(()) } - -#[cfg(test)] -mod tests { - use super::*; - use mozart_core::package::RawPackageData; - use mozart_core::repository::lockfile; - - fn make_locked_package(name: &str, version: &str) -> lockfile::LockedPackage { - lockfile::LockedPackage { - name: name.to_string(), - version: version.to_string(), - version_normalized: Some(format!("{}.0", version)), - source: None, - dist: None, - require: indexmap::IndexMap::new(), - require_dev: indexmap::IndexMap::new(), - conflict: indexmap::IndexMap::new(), - provide: indexmap::IndexMap::new(), - replace: indexmap::IndexMap::new(), - suggest: None, - package_type: Some("library".to_string()), - autoload: None, - autoload_dev: None, - license: None, - description: None, - homepage: None, - keywords: None, - authors: None, - support: None, - funding: None, - time: None, - extra_fields: indexmap::IndexMap::new(), - } - } - - fn minimal_lock(packages: Vec<lockfile::LockedPackage>) -> lockfile::LockFile { - lockfile::LockFile { - readme: lockfile::LockFile::default_readme(), - content_hash: "abc123".to_string(), - packages, - packages_dev: Some(vec![]), - aliases: vec![], - minimum_stability: "stable".to_string(), - stability_flags: serde_json::json!({}), - prefer_stable: false, - prefer_lowest: false, - platform: serde_json::json!({}), - platform_dev: serde_json::json!({}), - plugin_api_version: Some("2.6.0".to_string()), - } - } - - fn make_raw_package(name: &str) -> RawPackageData { - RawPackageData::new(name.to_string()) - } - - /// Remove a package from `require`, verify it's gone from `RawPackageData`. - #[test] - fn test_remove_from_require() { - let mut composer = make_raw_package("test/project"); - composer - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - composer - .require - .insert("monolog/monolog".to_string(), "^3.0".to_string()); - - assert!(composer.require.contains_key("psr/log")); - - composer.require.shift_remove("psr/log"); - - assert!( - !composer.require.contains_key("psr/log"), - "psr/log should be removed from require" - ); - assert!( - composer.require.contains_key("monolog/monolog"), - "monolog/monolog should remain in require" - ); - } - - /// Remove a package from `require-dev` with `--dev` flag. - #[test] - fn test_remove_from_require_dev() { - let mut composer = make_raw_package("test/project"); - composer - .require_dev - .insert("phpunit/phpunit".to_string(), "^11.0".to_string()); - composer - .require_dev - .insert("mockery/mockery".to_string(), "^1.0".to_string()); - - assert!(composer.require_dev.contains_key("phpunit/phpunit")); - - composer.require_dev.shift_remove("phpunit/phpunit"); - - assert!( - !composer.require_dev.contains_key("phpunit/phpunit"), - "phpunit/phpunit should be removed from require-dev" - ); - assert!( - composer.require_dev.contains_key("mockery/mockery"), - "mockery/mockery should remain in require-dev" - ); - } - - /// Removing a package not in either section does not panic and doesn't change anything. - #[test] - fn test_remove_nonexistent_package_no_panic() { - let mut composer = make_raw_package("test/project"); - composer - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - - let name = "nonexistent/package"; - let found_in_require = composer.require.shift_remove(name).is_some(); - let found_in_require_dev = composer.require_dev.shift_remove(name).is_some(); - - assert!(!found_in_require); - assert!(!found_in_require_dev); - - assert_eq!(composer.require.len(), 1); - assert!(composer.require.contains_key("psr/log")); - } - - /// Without `--dev`, auto-detect finds the package in whichever section contains it. - #[test] - fn test_remove_auto_detects_section_require() { - let mut composer = make_raw_package("test/project"); - composer - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - composer - .require_dev - .insert("phpunit/phpunit".to_string(), "^11.0".to_string()); - - let name = "psr/log"; - let removed_from_require = composer.require.shift_remove(name).is_some(); - let removed_from_dev = if !removed_from_require { - composer.require_dev.shift_remove(name).is_some() - } else { - false - }; - - assert!( - removed_from_require, - "should be found and removed from require" - ); - assert!(!removed_from_dev); - assert!(!composer.require.contains_key("psr/log")); - assert!(composer.require_dev.contains_key("phpunit/phpunit")); - } - - /// Without `--dev`, auto-detect finds the package in require-dev if not in require. - #[test] - fn test_remove_auto_detects_section_require_dev() { - let mut composer = make_raw_package("test/project"); - composer - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - composer - .require_dev - .insert("phpunit/phpunit".to_string(), "^11.0".to_string()); - - let name = "phpunit/phpunit"; - let removed_from_require = composer.require.shift_remove(name).is_some(); - let removed_from_dev = if !removed_from_require { - composer.require_dev.shift_remove(name).is_some() - } else { - false - }; - - assert!(!removed_from_require); - assert!( - removed_from_dev, - "should be found and removed from require-dev" - ); - assert!(!composer.require_dev.contains_key("phpunit/phpunit")); - assert!(composer.require.contains_key("psr/log")); - } - - /// After re-resolve, removed packages appear as `ChangeKind::Uninstall` in the change report. - #[test] - fn test_remove_change_report_shows_removals() { - let old_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), - make_locked_package("monolog/monolog", "3.8.0"), - ]); - let new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - - let changes = - super::super::update::compute_update_changes(Some(&old_lock), &new_lock, false); - - assert_eq!(changes.len(), 1, "exactly one change expected"); - assert_eq!(changes[0].name, "monolog/monolog"); - assert!( - matches!( - &changes[0].kind, - super::super::update::ChangeKind::Uninstall { old_version } - if old_version == "3.8.0" - ), - "monolog/monolog should appear as an Uninstall change" - ); - } - - /// Glob-style package names (e.g. "vendor/*") no longer bail with an "Invalid package name" - /// error — they fall through to the "not required" warning path. This is a regression test - /// for the validate_package_name bail that was removed in PR-A. - #[test] - fn test_glob_package_name_falls_through_to_not_required() { - let mut composer = make_raw_package("test/project"); - composer - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - - // A glob-style name: not a valid exact package name, not in require either. - let name = "vendor/*"; - let found = composer.require.shift_remove(name).is_some() - || composer.require_dev.shift_remove(name).is_some(); - - // Should NOT be found (falls through to "not required" warning), not panicked/bailed. - assert!(!found, "glob name should not match any package"); - // composer.json is unchanged - assert_eq!(composer.require.len(), 1); - } - - /// --unused with no lock file must return an error matching Composer's wording. - #[test] - fn test_unused_no_lock_error_wording() { - use tempfile::tempdir; - - let dir = tempdir().unwrap(); - // No lock file present — the error message is tested via the remove_unused code path. - let lock_path = dir.path().join("composer.lock"); - assert!(!lock_path.exists()); - - // The error message Composer uses (and Mozart must match): - let expected = "A valid composer.lock file is required to run this command with --unused"; - // Simulate the check that remove_unused() performs: - let result: anyhow::Result<()> = if !lock_path.exists() { - Err(anyhow::anyhow!("{}", expected)) - } else { - Ok(()) - }; - assert!(result.is_err()); - assert!(result.unwrap_err().to_string().contains(expected)); - } - - #[tokio::test] - #[ignore] - async fn test_remove_full_e2e() { - use indexmap::{IndexMap, IndexSet}; - use mozart_core::repository::lockfile::{LockFileGenerationRequest, generate_lock_file}; - use mozart_core::repository::resolver::{ResolveRequest, resolve}; - use tempfile::tempdir; - - let dir = tempdir().unwrap(); - let composer_path = dir.path().join("composer.json"); - let lock_path = dir.path().join("composer.lock"); - let vendor_dir = dir.path().join("vendor"); - - let content = r#"{"name": "test/project", "require": {"psr/log": "^3.0"}}"#; - std::fs::write(&composer_path, content).unwrap(); - - let mut composer: RawPackageData = serde_json::from_str(content).unwrap(); - - let request = ResolveRequest { - root_name: String::new(), - root_version: None, - require: vec![("psr/log".to_string(), "^3.0".to_string())], - require_dev: vec![], - include_dev: false, - minimum_stability: mozart_core::package::Stability::Stable, - stability_flags: IndexMap::new(), - prefer_stable: true, - prefer_lowest: false, - platform: mozart_core::repository::resolver::PlatformConfig::new(), - ignore_platform_reqs: false, - ignore_platform_req_list: vec![], - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - temporary_constraints: IndexMap::new(), - raw_repositories: vec![], - root_provide: IndexMap::new(), - root_replace: IndexMap::new(), - root_conflict: IndexMap::new(), - locked_package_names: IndexSet::new(), - locked_packages: Vec::new(), - block_abandoned: false, - root_branch_alias: None, - preferred_versions: IndexMap::new(), - block_insecure: false, - }; - let resolved = resolve(&request) - .await - .expect("initial resolution should succeed"); - let initial_lock = generate_lock_file(&LockFileGenerationRequest { - resolved_packages: resolved, - composer_json_content: content.to_string(), - composer_json: composer.clone(), - include_dev: false, - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - previous_lock: None, - lock_pinned_names: IndexSet::new(), - }) - .await - .expect("initial lock file generation should succeed"); - initial_lock - .write_to_file(&lock_path) - .expect("should write initial lock file"); - - composer.require.shift_remove("psr/log"); - package::write_to_file(&composer, &composer_path).unwrap(); - - let request2 = ResolveRequest { - root_name: String::new(), - root_version: None, - require: vec![], - require_dev: vec![], - include_dev: false, - minimum_stability: mozart_core::package::Stability::Stable, - stability_flags: IndexMap::new(), - prefer_stable: true, - prefer_lowest: false, - platform: mozart_core::repository::resolver::PlatformConfig::new(), - ignore_platform_reqs: false, - ignore_platform_req_list: vec![], - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - temporary_constraints: IndexMap::new(), - raw_repositories: vec![], - root_provide: IndexMap::new(), - root_replace: IndexMap::new(), - root_conflict: IndexMap::new(), - locked_package_names: IndexSet::new(), - locked_packages: Vec::new(), - block_abandoned: false, - root_branch_alias: None, - preferred_versions: IndexMap::new(), - block_insecure: false, - }; - let resolved2 = resolve(&request2) - .await - .expect("post-remove resolution should succeed"); - - let composer_json_content2 = std::fs::read_to_string(&composer_path).unwrap(); - let new_lock = generate_lock_file(&LockFileGenerationRequest { - resolved_packages: resolved2, - composer_json_content: composer_json_content2, - composer_json: composer, - include_dev: false, - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - previous_lock: Some(initial_lock.clone()), - lock_pinned_names: IndexSet::new(), - }) - .await - .expect("post-remove lock file generation should succeed"); - - assert!( - !new_lock.packages.iter().any(|p| p.name == "psr/log"), - "psr/log should be absent from the new lock file" - ); - - new_lock.write_to_file(&lock_path).unwrap(); - assert!(lock_path.exists(), "lock file should exist"); - - let _ = vendor_dir; - } - - #[test] - fn test_remove_no_update_only_modifies_json() { - use tempfile::tempdir; - - let dir = tempdir().unwrap(); - let composer_path = dir.path().join("composer.json"); - let lock_path = dir.path().join("composer.lock"); - - let content = r#"{"name": "test/project", "require": {"psr/log": "^3.0"}}"#; - std::fs::write(&composer_path, content).unwrap(); - - let mut composer: RawPackageData = serde_json::from_str(content).unwrap(); - composer.require.shift_remove("psr/log"); - package::write_to_file(&composer, &composer_path).unwrap(); - - assert!( - !lock_path.exists(), - "lock file should not be created with --no-update" - ); - - let updated_content = std::fs::read_to_string(&composer_path).unwrap(); - assert!( - !updated_content.contains("psr/log"), - "psr/log should be removed from composer.json" - ); - } - - #[test] - fn test_remove_dry_run_modifies_nothing() { - use tempfile::tempdir; - - let dir = tempdir().unwrap(); - let composer_path = dir.path().join("composer.json"); - let lock_path = dir.path().join("composer.lock"); - let vendor_dir = dir.path().join("vendor"); - - let original_content = r#"{"name": "test/project", "require": {"psr/log": "^3.0"}}"#; - std::fs::write(&composer_path, original_content).unwrap(); - - assert_eq!( - std::fs::read_to_string(&composer_path).unwrap(), - original_content, - "composer.json should be unmodified after dry run" - ); - assert!( - !lock_path.exists(), - "lock file should not be created by dry run" - ); - assert!( - !vendor_dir.exists(), - "vendor dir should not be created by dry run" - ); - } -} |
