//! ref: composer/tests/Composer/Test/Command/RemoveCommandTest.php
use crate::test_case::{
RunOptions, create_composer_lock, create_installed_json, get_application_tester, get_package,
init_temp_composer,
};
use indexmap::IndexMap;
use serial_test::serial;
use shirabe::json::JsonFile;
use shirabe::package::Link;
use shirabe::package::handle::PackageInterfaceHandle;
use shirabe_php_shim::PhpMixed;
use shirabe_semver::constraint::{AnyConstraint, MatchAllConstraint};
// Symfony\Component\Console\Command\Command exit codes.
const SUCCESS: i32 = 0;
const FAILURE: i32 = 1;
const INVALID: i32 = 2;
fn input(pairs: Vec<(&str, PhpMixed)>) -> Vec<(PhpMixed, PhpMixed)> {
pairs
.into_iter()
.map(|(k, v)| (PhpMixed::from(k), v))
.collect()
}
/// Read a JSON file in the CWD and decode it to a `serde_json::Value`.
fn read_json_file(path: &str) -> serde_json::Value {
let mut json = JsonFile::new(path.to_string(), None, None).unwrap();
let read = json.read().unwrap();
serde_json::from_str(&JsonFile::encode(&read)).unwrap()
}
/// Mirrors PHPUnit's assertEmpty for a decoded JSON document (empty object/array/null).
fn is_empty_json(value: &serde_json::Value) -> bool {
match value {
serde_json::Value::Null => true,
serde_json::Value::Object(map) => map.is_empty(),
serde_json::Value::Array(list) => list.is_empty(),
_ => false,
}
}
#[test]
#[serial]
fn test_exception_running_with_no_remove_packages() {
let mut app_tester = get_application_tester();
let err = app_tester
.run(
input(vec![("command", PhpMixed::from("remove"))]),
RunOptions::default(),
)
.expect_err("expected InvalidArgumentException for missing packages argument");
assert!(
err.to_string()
.contains(r#"Not enough arguments (missing: "packages")."#),
"got: {}",
err
);
}
#[test]
#[serial]
fn test_exception_when_running_unused_without_lock_file() {
let tear_down = init_temp_composer(None, None, None, true);
let mut app_tester = get_application_tester();
let err = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("--unused", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.expect_err("expected UnexpectedValueException when --unused without lock file");
assert!(
err.to_string()
.contains("A valid composer.lock file is required to run this command with --unused"),
"got: {}",
err
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_warning_when_removing_non_existent_package() {
let tear_down = init_temp_composer(None, None, None, true);
create_installed_json(&[], &[], true);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
(
"packages",
PhpMixed::List(vec![PhpMixed::from("vendor1/package1")]),
),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert!(
app_tester.get_display().trim().starts_with(
"vendor1/package1 is not required in your composer.json and has not been removed"
),
"got: {}",
app_tester.get_display()
);
drop(tear_down);
}
#[test]
#[serial]
fn test_warning_when_removing_package_from_wrong_type() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--dev", PhpMixed::from(true)),
("--no-update", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
"root/req could not be found in require-dev but it is present in require
./composer.json has been updated",
app_tester.get_display().trim()
);
assert_eq!(
serde_json::json!({ "require": { "root/req": "1.*" } }),
read_json_file("./composer.json")
);
drop(tear_down);
}
#[test]
#[serial]
fn test_warning_when_removing_package_with_deprecated_dependencies_flag() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--update-with-dependencies", PhpMixed::from(true)),
("--no-update", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
"You are using the deprecated option \"update-with-dependencies\". This is now default behaviour. The --no-update-with-dependencies option can be used to remove a package without its dependencies.
./composer.json has been updated",
app_tester.get_display().trim()
);
assert!(
is_empty_json(&read_json_file("./composer.json")),
"expected composer.json to be empty, got: {}",
read_json_file("./composer.json")
);
drop(tear_down);
}
#[test]
#[serial]
fn test_message_output_when_no_unused_packages_to_remove() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "require": {"nested/req": "^1"}},
{"name": "nested/req", "version": "1.1.0"},
],
},
},
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let required_package = get_package("root/req", "1.0.0");
let mut requires = IndexMap::new();
requires.insert(
"nested/req".to_string(),
Link::new(
"root/req".to_string(),
"nested/req".to_string(),
AnyConstraint::MatchAll(MatchAllConstraint::new(None)),
Some(Link::TYPE_REQUIRE.to_string()),
"^1".to_string(),
),
);
required_package.__set_requires(requires);
let nested_package = get_package("nested/req", "1.1.0");
let packages: Vec =
vec![required_package.clone(), nested_package.clone()];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("--unused", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
"No unused packages to remove",
app_tester.get_display().trim()
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_unused_package() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0"},
{"name": "not/req", "version": "1.0.0"},
],
},
},
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let required_package = get_package("root/req", "1.0.0");
let extraneous_package = get_package("not/req", "1.0.0");
create_installed_json(std::slice::from_ref(&required_package), &[], true);
create_composer_lock(&[required_package.clone(), extraneous_package.clone()], &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("--unused", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert!(
app_tester.get_display().starts_with(
"not/req is not required in your composer.json and has not been removed"
),
"got: {}",
app_tester.get_display()
);
assert!(
app_tester
.get_display()
.contains("Running composer update not/req"),
"got: {}",
app_tester.get_display()
);
assert!(
app_tester
.get_display()
.contains("- Removing not/req (1.0.0)"),
"got: {}",
app_tester.get_display()
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_package_by_name() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
{"name": "root/another", "version": "1.0.0", "type": "metapackage"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
// Set as a metapackage so that we can do the whole post-remove update & install process without
// Composer trying to download them (DownloadManager::getDownloaderForPackage).
root_req_package.__set_type("metapackage".to_string());
root_another_package.__set_type("metapackage".to_string());
let packages: Vec =
vec![root_req_package.clone(), root_another_package.clone()];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
let display = app_tester.get_display();
let trimmed = display.trim();
assert!(
trimmed.starts_with("./composer.json has been updated"),
"got: {}",
display
);
assert!(
trimmed.contains("Running composer update root/req"),
"got: {}",
display
);
assert!(
trimmed.contains("Lock file operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert!(
trimmed.contains("- Removing root/req (1.0.0)"),
"got: {}",
display
);
assert!(
trimmed.contains("Package operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert_eq!(
serde_json::json!({ "root/another": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert_eq!(
serde_json::json!([{"name": "root/another", "version": "1.0.0", "type": "metapackage"}]),
read_json_file("./composer.lock")["packages"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_package_by_name_with_dry_run() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
{"name": "root/another", "version": "1.0.0", "type": "metapackage"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
root_req_package.__set_type("metapackage".to_string());
root_another_package.__set_type("metapackage".to_string());
let packages: Vec =
vec![root_req_package.clone(), root_another_package.clone()];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--dry-run", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
let display = app_tester.get_display();
let trimmed = display.trim();
assert!(
trimmed.contains("./composer.json has been updated"),
"got: {}",
display
);
assert!(
trimmed.contains("Running composer update root/req"),
"got: {}",
display
);
assert!(
trimmed.contains("Lock file operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert!(
trimmed.contains("- Removing root/req (1.0.0)"),
"got: {}",
display
);
assert!(
trimmed.contains("Package operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert_eq!(
serde_json::json!({ "root/req": "1.*", "root/another": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert_eq!(
serde_json::json!([
{"name": "root/another", "version": "1.0.0", "type": "metapackage"},
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
]),
read_json_file("./composer.lock")["packages"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_allowed_plugin_package_with_no_other_allowed_plugins() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
{"name": "root/another", "version": "1.0.0", "type": "metapackage"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*" },
"config": { "allow-plugins": { "root/req": true } },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
root_req_package.__set_type("metapackage".to_string());
root_another_package.__set_type("metapackage".to_string());
let packages: Vec =
vec![root_req_package.clone(), root_another_package.clone()];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
serde_json::json!({ "root/another": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert!(
is_empty_json(&read_json_file("./composer.json")["config"]),
"expected config to be empty, got: {}",
read_json_file("./composer.json")["config"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_allowed_plugin_package_with_other_allowed_plugins() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
{"name": "root/another", "version": "1.0.0", "type": "metapackage"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*" },
"config": { "allow-plugins": { "root/another": true, "root/req": true } },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
root_req_package.__set_type("metapackage".to_string());
root_another_package.__set_type("metapackage".to_string());
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
serde_json::json!({ "root/another": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert_eq!(
serde_json::json!({ "allow-plugins": { "root/another": true } }),
read_json_file("./composer.json")["config"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_packages_by_vendor() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0"},
{"name": "root/another", "version": "1.0.0"},
{"name": "another/req", "version": "1.0.0"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*", "another/req": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
let another_req_package = get_package("another/req", "1.0.0");
let packages: Vec = vec![
root_req_package.clone(),
root_another_package.clone(),
another_req_package.clone(),
];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/*")])),
("--no-install", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
let display = app_tester.get_display();
assert!(
display
.trim()
.starts_with("./composer.json has been updated"),
"got: {}",
display
);
assert!(
display.contains("Running composer update root/*"),
"got: {}",
display
);
assert!(
display.contains("- Removing root/another (1.0.0)"),
"got: {}",
display
);
assert!(
display.contains("- Removing root/req (1.0.0)"),
"got: {}",
display
);
assert!(display.contains("Writing lock file"), "got: {}", display);
assert_eq!(
serde_json::json!({ "another/req": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert_eq!(
serde_json::json!([{"name": "another/req", "version": "1.0.0", "type": "library"}]),
read_json_file("./composer.lock")["packages"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_remove_packages_by_vendor_with_dry_run() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0"},
{"name": "root/another", "version": "1.0.0"},
{"name": "another/req", "version": "1.0.0"},
],
},
},
"require": { "root/req": "1.*", "root/another": "1.*", "another/req": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
let root_another_package = get_package("root/another", "1.0.0");
let another_req_package = get_package("another/req", "1.0.0");
let packages: Vec = vec![
root_req_package.clone(),
root_another_package.clone(),
another_req_package.clone(),
];
create_installed_json(&packages, &[], true);
create_composer_lock(&packages, &[]);
let mut app_tester = get_application_tester();
app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/*")])),
("--dry-run", PhpMixed::from(true)),
("--no-install", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, app_tester.get_status_code());
assert_eq!(
"./composer.json has been updated
Running composer update root/*
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 0 updates, 2 removals
- Removing root/another (1.0.0)
- Removing root/req (1.0.0)",
app_tester.get_display().trim()
);
assert!(
!app_tester.get_display().contains("Writing lock file"),
"got: {}",
app_tester.get_display()
);
assert_eq!(
serde_json::json!({ "root/req": "1.*", "root/another": "1.*", "another/req": "1.*" }),
read_json_file("./composer.json")["require"]
);
assert_eq!(
serde_json::json!([
{"name": "another/req", "version": "1.0.0", "type": "library"},
{"name": "root/another", "version": "1.0.0", "type": "library"},
{"name": "root/req", "version": "1.0.0", "type": "library"},
]),
read_json_file("./composer.lock")["packages"]
);
drop(tear_down);
}
#[test]
#[serial]
fn test_warning_when_removing_packages_by_vendor_from_wrong_type() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"require": { "root/req": "1.*", "root/another": "1.*", "another/req": "1.*" },
})),
None,
None,
true,
);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/*")])),
("--dev", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
("--no-update", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
assert_eq!(
"root/req could not be found in require-dev but it is present in require
root/another could not be found in require-dev but it is present in require
./composer.json has been updated",
app_tester.get_display().trim()
);
assert_eq!(
serde_json::json!({
"require": { "root/req": "1.*", "root/another": "1.*", "another/req": "1.*" }
}),
read_json_file("./composer.json")
);
drop(tear_down);
}
#[ignore = "installed.json records install-path: null instead of the expected \"../root/req\": the InstallationManager that writes the local repo in the --no-install (update && !install) flow has no installers registered (n_installers=0), so get_install_path()->get_installer() fails and yields null. Separate from the execute_batch fix; needs the default installers wired onto that manager."]
#[test]
#[serial]
fn test_package_still_present_error_when_no_install_flag_used() {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
create_installed_json(std::slice::from_ref(&root_req_package), &[], true);
create_composer_lock(std::slice::from_ref(&root_req_package), &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
("--no-install", PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(INVALID, status_code);
let display = app_tester.get_display();
assert!(
display.contains("./composer.json has been updated"),
"got: {}",
display
);
assert!(
display.contains("Lock file operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert!(
display.contains("- Removing root/req (1.0.0)"),
"got: {}",
display
);
assert!(display.contains("Writing lock file"), "got: {}", display);
assert!(
display.contains(
"Removal failed, root/req is still present, it may be required by another package. See `composer why root/req`"
),
"got: {}",
display
);
assert!(
is_empty_json(&read_json_file("./composer.json")),
"expected composer.json to be empty, got: {}",
read_json_file("./composer.json")
);
assert!(
is_empty_json(&read_json_file("./composer.lock")["packages"]),
"expected composer.lock packages to be empty, got: {}",
read_json_file("./composer.lock")["packages"]
);
assert_eq!(
serde_json::json!([{
"name": "root/req",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"type": "library",
"install-path": "../root/req"
}]),
read_json_file("./vendor/composer/installed.json")["packages"]
);
drop(tear_down);
}
/// ref: RemoveCommandTest::testUpdateInheritedDependenciesFlagIsPassedToPostRemoveInstaller
/// (data provider provideInheritedDependenciesUpdateFlag).
fn run_update_inherited_dependencies_flag_case(
install_flag_name: &str,
expected_composer_update_command: &str,
) {
let tear_down = init_temp_composer(
Some(&serde_json::json!({
"repositories": {
"packages": {
"type": "package",
"package": [
{"name": "root/req", "version": "1.0.0", "type": "metapackage"},
],
},
},
"require": { "root/req": "1.*" },
})),
None,
None,
true,
);
let root_req_package = get_package("root/req", "1.0.0");
root_req_package.__set_type("metapackage".to_string());
create_installed_json(std::slice::from_ref(&root_req_package), &[], true);
create_composer_lock(std::slice::from_ref(&root_req_package), &[]);
let mut app_tester = get_application_tester();
let status_code = app_tester
.run(
input(vec![
("command", PhpMixed::from("remove")),
("packages", PhpMixed::List(vec![PhpMixed::from("root/req")])),
(install_flag_name, PhpMixed::from(true)),
("--no-audit", PhpMixed::from(true)),
("--no-interaction", PhpMixed::from(true)),
]),
RunOptions::default(),
)
.unwrap();
assert_eq!(SUCCESS, status_code);
let display = app_tester.get_display();
assert!(
display.contains("./composer.json has been updated"),
"got: {}",
display
);
assert!(
display.contains(expected_composer_update_command),
"got: {}",
display
);
assert!(
display.contains("Package operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert!(
display.contains("- Removing root/req (1.0.0)"),
"got: {}",
display
);
assert!(display.contains("Writing lock file"), "got: {}", display);
assert!(
display.contains("Lock file operations: 0 installs, 0 updates, 1 removal"),
"got: {}",
display
);
assert!(
is_empty_json(&read_json_file("./composer.lock")["packages"]),
"expected composer.lock packages to be empty, got: {}",
read_json_file("./composer.lock")["packages"]
);
drop(tear_down);
}
#[test]
#[serial]
#[ignore]
fn test_update_inherited_dependencies_flag_is_passed_to_post_remove_installer() {
// 'update with all dependencies'
run_update_inherited_dependencies_flag_case(
"--update-with-all-dependencies",
"Running composer update root/req --with-all-dependencies",
);
// 'with all dependencies'
run_update_inherited_dependencies_flag_case(
"--with-all-dependencies",
"Running composer update root/req --with-all-dependencies",
);
// 'no update with dependencies'
run_update_inherited_dependencies_flag_case(
"--no-update-with-dependencies",
"Running composer update root/req --with-dependencies",
);
}