diff options
Diffstat (limited to 'crates/shirabe/tests/command/licenses_command_test.rs')
| -rw-r--r-- | crates/shirabe/tests/command/licenses_command_test.rs | 321 |
1 files changed, 293 insertions, 28 deletions
diff --git a/crates/shirabe/tests/command/licenses_command_test.rs b/crates/shirabe/tests/command/licenses_command_test.rs index 6bfe832..f680621 100644 --- a/crates/shirabe/tests/command/licenses_command_test.rs +++ b/crates/shirabe/tests/command/licenses_command_test.rs @@ -1,71 +1,336 @@ //! ref: composer/tests/Composer/Test/Command/LicensesCommandTest.php -fn set_up() { - // Builds the temp project and installed.json/composer.lock fixtures via - // initTempComposer/createInstalledJson/createComposerLock, none of which are ported yet. - todo!() +use crate::test_case::{ + RunOptions, TearDown, create_composer_lock, create_installed_json, get_application_tester, + get_complete_package, init_temp_composer, +}; +use serial_test::serial; +use shirabe::package::handle::PackageInterfaceHandle; +use shirabe_php_shim::PhpMixed; + +/// ref: LicensesCommandTest::setUp +fn set_up() -> TearDown { + let tear_down = init_temp_composer( + Some(&serde_json::json!({ + "name": "test/pkg", + "version": "1.2.3", + "license": "MIT", + "require": { + "first/pkg": "^2.0", + "second/pkg": "3.*", + "third/pkg": "^1.3", + }, + "require-dev": { + "dev/pkg": "~2.0", + }, + })), + None, + None, + true, + ); + + let first = get_complete_package("first/pkg", "2.3.4"); + first.set_license(vec!["MIT".to_string()]); + + let second = get_complete_package("second/pkg", "3.4.0"); + second.set_license(vec!["LGPL-2.0-only".to_string()]); + second.set_homepage("https://example.org".to_string()); + + let third = get_complete_package("third/pkg", "1.5.4"); + + let dev = get_complete_package("dev/pkg", "2.3.4.5"); + dev.set_license(vec!["MIT".to_string()]); + + let packages: Vec<PackageInterfaceHandle> = vec![first.into(), second.into(), third.into()]; + let dev_packages: Vec<PackageInterfaceHandle> = vec![dev.into()]; + + create_installed_json(&packages, &dev_packages, true); + create_composer_lock(&packages, &dev_packages); + + tear_down +} + +/// Asserts each non-blank line of `display` matches the regex built from `expected[i]` +/// (`implode("\s+", expected[i])` in PHP). +fn assert_lines(display: &str, expected: &[Vec<&str>]) { + let mut i = 0usize; + for line in display.split('\n') { + if line.trim().is_empty() { + i += 1; + continue; + } + assert!(i < expected.len(), "Got more output lines than expected"); + let pattern = expected[i] + .iter() + .map(|s| regex::escape(s)) + .collect::<Vec<_>>() + .join(r"\s+"); + let re = regex::Regex::new(&pattern).unwrap(); + assert!( + re.is_match(line), + "line {} {:?} did not match {:?}", + i, + line, + pattern + ); + i += 1; + } } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] +#[ignore = "renders the text-format Table, which reaches shirabe_php_shim::instance_of (var.rs todo!()); \ + PhpMixed::Object carries no runtime class tag, so the Symfony Table helper cannot \ + distinguish TableSeparator/TableCell rows yet"] fn test_basic_run() { - set_up(); + let _tear_down = set_up(); - todo!() + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![(PhpMixed::from("command"), PhpMixed::from("license"))], + RunOptions::default(), + ) + .unwrap(); + assert_eq!(0, status_code); + + let expected = vec![ + vec!["Name:", "test/pkg"], + vec!["Version:", "1.2.3"], + vec!["Licenses:", "MIT"], + vec!["Dependencies:"], + vec![], + vec!["Name", "Version", "Licenses"], + vec!["dev/pkg", "2.3.4.5", "MIT"], + vec!["first/pkg", "2.3.4", "MIT"], + vec!["second/pkg", "3.4.0", "LGPL-2.0-only"], + vec!["third/pkg", "1.5.4", "none"], + ]; + assert_lines(&app_tester.get_display(), &expected); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] +#[ignore = "renders the text-format Table, which reaches shirabe_php_shim::instance_of (var.rs todo!()); \ + see test_basic_run"] fn test_no_dev() { - set_up(); + let _tear_down = set_up(); + + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--no-dev"), PhpMixed::from(true)), + ], + RunOptions::default(), + ) + .unwrap(); + assert_eq!(0, status_code); - todo!() + let expected = vec![ + vec!["Name:", "test/pkg"], + vec!["Version:", "1.2.3"], + vec!["Licenses:", "MIT"], + vec!["Dependencies:"], + vec![], + vec!["Name", "Version", "Licenses"], + vec!["first/pkg", "2.3.4", "MIT"], + vec!["second/pkg", "3.4.0", "LGPL-2.0-only"], + vec!["third/pkg", "1.5.4", "none"], + ]; + assert_lines(&app_tester.get_display(), &expected); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] fn test_format_json() { - set_up(); + let _tear_down = set_up(); + + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--format"), PhpMixed::from("json")), + ], + RunOptions { + capture_stderr_separately: true, + ..RunOptions::default() + }, + ) + .unwrap(); + assert_eq!(0, status_code); - todo!() + let expected = serde_json::json!({ + "name": "test/pkg", + "version": "1.2.3", + "license": ["MIT"], + "dependencies": { + "dev/pkg": { "version": "2.3.4.5", "license": ["MIT"] }, + "first/pkg": { "version": "2.3.4", "license": ["MIT"] }, + "second/pkg": { "version": "3.4.0", "license": ["LGPL-2.0-only"] }, + "third/pkg": { "version": "1.5.4", "license": [] }, + }, + }); + + let actual: serde_json::Value = serde_json::from_str(&app_tester.get_display()).unwrap(); + assert_eq!(expected, actual); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] +#[ignore = "renders a Table via SymfonyStyle::table, which reaches shirabe_php_shim::instance_of \ + (var.rs todo!()); see test_basic_run"] fn test_format_summary() { - set_up(); + let _tear_down = set_up(); + + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--format"), PhpMixed::from("summary")), + ], + RunOptions::default(), + ) + .unwrap(); + assert_eq!(0, status_code); - todo!() + let expected = vec![ + ("-", "-"), + ("License", "Number of dependencies"), + ("-", "-"), + ("MIT", "2"), + ("LGPL-2.0-only", "1"), + ("none", "1"), + ("-", "-"), + ]; + + let display = app_tester.get_display(); + let lines: Vec<&str> = display.split('\n').collect(); + for (i, (key, value)) in expected.iter().enumerate() { + let pattern = format!(r"{}\s+{}", regex::escape(key), regex::escape(value)); + let re = regex::Regex::new(&pattern).unwrap(); + assert!( + re.is_match(lines[i]), + "line {} {:?} did not match {:?}", + i, + lines[i], + pattern + ); + } } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] fn test_format_unknown() { - set_up(); + let _tear_down = set_up(); - todo!() + let mut app_tester = get_application_tester(); + let result = app_tester.run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--format"), PhpMixed::from("unknown")), + ], + RunOptions::default(), + ); + assert!( + result.is_err(), + "expected a RuntimeException, got {:?}", + result + ); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] +#[ignore = "renders the text-format Table, which reaches shirabe_php_shim::instance_of (var.rs todo!()); \ + see test_basic_run"] fn test_locked() { - set_up(); + let _tear_down = set_up(); + + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--locked"), PhpMixed::from(true)), + ], + RunOptions::default(), + ) + .unwrap(); + assert_eq!(0, status_code); - todo!() + let expected = vec![ + vec!["Name:", "test/pkg"], + vec!["Version:", "1.2.3"], + vec!["Licenses:", "MIT"], + vec!["Dependencies:"], + vec![], + vec!["Name", "Version", "Licenses"], + vec!["dev/pkg", "2.3.4.5", "MIT"], + vec!["first/pkg", "2.3.4", "MIT"], + vec!["second/pkg", "3.4.0", "LGPL-2.0-only"], + vec!["third/pkg", "1.5.4", "none"], + ]; + assert_lines(&app_tester.get_display(), &expected); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] +#[ignore = "renders the text-format Table, which reaches shirabe_php_shim::instance_of (var.rs todo!()); \ + see test_basic_run"] fn test_locked_no_dev() { - set_up(); + let _tear_down = set_up(); - todo!() + let mut app_tester = get_application_tester(); + let status_code = app_tester + .run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--locked"), PhpMixed::from(true)), + (PhpMixed::from("--no-dev"), PhpMixed::from(true)), + ], + RunOptions::default(), + ) + .unwrap(); + assert_eq!(0, status_code); + + let expected = vec![ + vec!["Name:", "test/pkg"], + vec!["Version:", "1.2.3"], + vec!["Licenses:", "MIT"], + vec!["Dependencies:"], + vec![], + vec!["Name", "Version", "Licenses"], + vec!["first/pkg", "2.3.4", "MIT"], + vec!["second/pkg", "3.4.0", "LGPL-2.0-only"], + vec!["third/pkg", "1.5.4", "none"], + ]; + assert_lines(&app_tester.get_display(), &expected); } #[test] -#[ignore = "missing TestCase::init_temp_composer / create_installed_json / create_composer_lock and get_application_tester (ApplicationTester) infrastructure"] +#[serial] fn test_locked_without_lock_file() { - set_up(); + let _tear_down = set_up(); + + // Remove the lock file + let _ = std::fs::remove_file("./composer.lock"); - todo!() + let mut app_tester = get_application_tester(); + let result = app_tester.run( + vec![ + (PhpMixed::from("command"), PhpMixed::from("license")), + (PhpMixed::from("--locked"), PhpMixed::from(true)), + ], + RunOptions::default(), + ); + let err = result.expect_err("expected an UnexpectedValueException"); + assert!( + err.to_string() + .contains("Valid composer.json and composer.lock files are required to run this command with --locked"), + "unexpected error: {}", + err + ); } |
