From 0a78a3291668565563598dd5d7f6199bd79c7243 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Sun, 31 May 2026 16:25:58 -0600 Subject: [PATCH] test: Collapse integration test matrices --- crates/turborepo/tests/continue_test.rs | 50 +------ crates/turborepo/tests/force_test.rs | 112 +++------------ .../turborepo/tests/one_script_error_test.rs | 29 +--- .../tests/persistent_dependencies.rs | 129 ++++++------------ ...pendencies__test_10_concurrency_1_env.snap | 2 +- ...endencies__test_10_concurrency_1_flag.snap | 2 +- ...pendencies__test_10_concurrency_2_env.snap | 2 +- ...endencies__test_10_concurrency_2_flag.snap | 2 +- .../tests/workspace_config_override_test.rs | 97 ++----------- 9 files changed, 84 insertions(+), 341 deletions(-) diff --git a/crates/turborepo/tests/continue_test.rs b/crates/turborepo/tests/continue_test.rs index 01daaab03882c..e1025adfd15bf 100644 --- a/crates/turborepo/tests/continue_test.rs +++ b/crates/turborepo/tests/continue_test.rs @@ -5,7 +5,7 @@ mod common; use common::{run_turbo, setup}; #[test] -fn test_without_continue_stops_on_error() { +fn test_continue_modes() { let tempdir = tempfile::tempdir().unwrap(); setup::setup_integration_test( tempdir.path(), @@ -36,24 +36,6 @@ fn test_without_continue_stops_on_error() { !stdout.contains("my-app:build"), "my-app should not run when dependency fails, got: {stdout}" ); -} - -#[test] -fn test_without_continue_errors_only() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test( - tempdir.path(), - "monorepo_dependency_error", - "npm@10.5.0", - true, - ) - .unwrap(); - - // Prime base-lib cache - run_turbo( - tempdir.path(), - &["build", "--filter", "my-app...", "--log-order", "grouped"], - ); let output = run_turbo( tempdir.path(), @@ -72,24 +54,6 @@ fn test_without_continue_errors_only() { // Only error output should appear assert!(stdout.contains("some-lib:build")); assert!(stdout.contains("Failed:")); -} - -#[test] -fn test_with_continue_runs_independent_tasks() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test( - tempdir.path(), - "monorepo_dependency_error", - "npm@10.5.0", - true, - ) - .unwrap(); - - // Prime base-lib cache - run_turbo( - tempdir.path(), - &["build", "--filter", "my-app...", "--log-order", "grouped"], - ); let output = run_turbo( tempdir.path(), @@ -111,18 +75,6 @@ fn test_with_continue_runs_independent_tasks() { stdout.contains("2 successful, 3 total"), "expected 2 successes with --continue, got: {stdout}" ); -} - -#[test] -fn test_continue_dependencies_successful() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test( - tempdir.path(), - "monorepo_dependency_error", - "npm@10.5.0", - true, - ) - .unwrap(); let output = run_turbo( tempdir.path(), diff --git a/crates/turborepo/tests/force_test.rs b/crates/turborepo/tests/force_test.rs index 6af39249bc1ee..d98cf87fee2af 100644 --- a/crates/turborepo/tests/force_test.rs +++ b/crates/turborepo/tests/force_test.rs @@ -51,98 +51,30 @@ fn run_force_test( } } -// env var=true, missing flag: bypass #[test] -fn test_force_env_true_no_flag() { +fn test_force_env_and_flag_precedence() { let tempdir = tempfile::tempdir().unwrap(); setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("true"), None, true); -} - -// env var=true, --force=true: bypass -#[test] -fn test_force_env_true_flag_true() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("true"), Some("--force=true"), true); -} - -// env var=true, --force=false: cache hit (flag wins) -#[test] -fn test_force_env_true_flag_false() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("true"), Some("--force=false"), false); -} - -// env var=true, --force (no value): bypass -#[test] -fn test_force_env_true_flag_no_value() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("true"), Some("--force"), true); -} - -// env var=false, missing flag: cache hit -#[test] -fn test_force_env_false_no_flag() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("false"), None, false); -} -// env var=false, --force=true: bypass -#[test] -fn test_force_env_false_flag_true() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("false"), Some("--force=true"), true); -} - -// env var=false, --force=false: cache hit -#[test] -fn test_force_env_false_flag_false() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("false"), Some("--force=false"), false); -} - -// env var=false, --force (no value): bypass -#[test] -fn test_force_env_false_flag_no_value() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), Some("false"), Some("--force"), true); -} - -// missing env var, missing flag: cache hit -#[test] -fn test_force_no_env_no_flag() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), None, None, false); -} - -// missing env var, --force=true: bypass -#[test] -fn test_force_no_env_flag_true() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), None, Some("--force=true"), true); -} - -// missing env var, --force=false: cache hit -#[test] -fn test_force_no_env_flag_false() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), None, Some("--force=false"), false); -} - -// missing env var, --force (no value): bypass -#[test] -fn test_force_no_env_flag_no_value() { - let tempdir = tempfile::tempdir().unwrap(); - setup_and_prime_cache(tempdir.path()); - run_force_test(tempdir.path(), None, Some("--force"), true); + let cases = [ + // env var=true + (Some("true"), None, true), + (Some("true"), Some("--force=true"), true), + (Some("true"), Some("--force=false"), false), + (Some("true"), Some("--force"), true), + // env var=false + (Some("false"), None, false), + (Some("false"), Some("--force=true"), true), + (Some("false"), Some("--force=false"), false), + (Some("false"), Some("--force"), true), + // missing env var + (None, None, false), + (None, Some("--force=true"), true), + (None, Some("--force=false"), false), + (None, Some("--force"), true), + ]; + + for (env_force, flag, expect_bypass) in cases { + run_force_test(tempdir.path(), env_force, flag, expect_bypass); + } } diff --git a/crates/turborepo/tests/one_script_error_test.rs b/crates/turborepo/tests/one_script_error_test.rs index 69900ab0730e6..eadf082450263 100644 --- a/crates/turborepo/tests/one_script_error_test.rs +++ b/crates/turborepo/tests/one_script_error_test.rs @@ -5,7 +5,7 @@ mod common; use common::{run_turbo, setup}; #[test] -fn test_script_error_reported_with_exit_code() { +fn test_script_error_behavior() { let tempdir = tempfile::tempdir().unwrap(); setup::setup_integration_test( tempdir.path(), @@ -31,21 +31,6 @@ fn test_script_error_reported_with_exit_code() { stdout.contains("Failed:"), "expected Failed summary, got: {stdout}" ); -} - -#[test] -fn test_script_error_not_cached() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test( - tempdir.path(), - "monorepo_one_script_error", - "npm@10.5.0", - true, - ) - .unwrap(); - - // First run - run_turbo(tempdir.path(), &["error"]); // Second run: error should not be cached, but okay should be let output = run_turbo(tempdir.path(), &["error"]); @@ -59,18 +44,6 @@ fn test_script_error_not_cached() { stdout.contains("my-app:error: cache miss"), "error task should not be cached, got: {stdout}" ); -} - -#[test] -fn test_continue_preserves_error_exit_code() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test( - tempdir.path(), - "monorepo_one_script_error", - "npm@10.5.0", - true, - ) - .unwrap(); let output = run_turbo(tempdir.path(), &["okay2", "--continue"]); assert!( diff --git a/crates/turborepo/tests/persistent_dependencies.rs b/crates/turborepo/tests/persistent_dependencies.rs index 08cbe09d2501f..1add01e39b0ca 100644 --- a/crates/turborepo/tests/persistent_dependencies.rs +++ b/crates/turborepo/tests/persistent_dependencies.rs @@ -2,7 +2,7 @@ mod common; -use common::{run_turbo, setup, turbo_output_filters}; +use common::{run_turbo, run_turbo_with_env, setup, turbo_output_filters}; fn setup_persistent_deps(fixture_suffix: &str) -> tempfile::TempDir { let tempdir = tempfile::tempdir().unwrap(); @@ -82,102 +82,61 @@ fn test_6_topological_unimplemented() { // Test 10: concurrency checks — persistent tasks require enough concurrency // slots #[test] -fn test_10_too_many_concurrency_1_flag() { +fn test_10_too_many_concurrency() { let tempdir = setup_persistent_deps("10-too-many"); - let output = run_turbo(tempdir.path(), &["run", "build", "--concurrency=1"]); - assert!(!output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr); - insta::assert_snapshot!("test_10_concurrency_1_flag", stderr.to_string()); -} -#[test] -fn test_10_too_many_concurrency_1_env() { - let tempdir = setup_persistent_deps("10-too-many"); - let config_dir = tempfile::tempdir().unwrap(); - let mut cmd = assert_cmd::Command::cargo_bin("turbo").unwrap(); - let output = cmd - .env("TURBO_TELEMETRY_MESSAGE_DISABLED", "1") - .env("TURBO_GLOBAL_WARNING_DISABLED", "1") - .env("TURBO_PRINT_VERSION_DISABLED", "1") - .env("TURBO_CONFIG_DIR_PATH", config_dir.path()) - .env("DO_NOT_TRACK", "1") - .env("TURBO_CONCURRENCY", "1") - .env_remove("CI") - .env_remove("GITHUB_ACTIONS") - .args(["run", "build"]) - .current_dir(tempdir.path()) - .output() - .unwrap(); + let output = run_turbo(tempdir.path(), &["run", "build", "--concurrency=1"]); + assert_concurrency_error(&output); + insta::assert_snapshot!( + "test_10_concurrency_1_flag", + String::from_utf8_lossy(&output.stderr).to_string() + ); - assert!(!output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr); - insta::assert_snapshot!("test_10_concurrency_1_env", stderr.to_string()); -} + let output = run_turbo_with_env( + tempdir.path(), + &["run", "build"], + &[("TURBO_CONCURRENCY", "1")], + ); + assert_concurrency_error(&output); + insta::assert_snapshot!( + "test_10_concurrency_1_env", + String::from_utf8_lossy(&output.stderr).to_string() + ); -#[test] -fn test_10_too_many_concurrency_2_flag() { - let tempdir = setup_persistent_deps("10-too-many"); let output = run_turbo(tempdir.path(), &["run", "build", "--concurrency=2"]); - assert!(!output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr); - insta::assert_snapshot!("test_10_concurrency_2_flag", stderr.to_string()); -} - -#[test] -fn test_10_too_many_concurrency_2_env() { - let tempdir = setup_persistent_deps("10-too-many"); - let config_dir = tempfile::tempdir().unwrap(); - let mut cmd = assert_cmd::Command::cargo_bin("turbo").unwrap(); - let output = cmd - .env("TURBO_TELEMETRY_MESSAGE_DISABLED", "1") - .env("TURBO_GLOBAL_WARNING_DISABLED", "1") - .env("TURBO_PRINT_VERSION_DISABLED", "1") - .env("TURBO_CONFIG_DIR_PATH", config_dir.path()) - .env("DO_NOT_TRACK", "1") - .env("TURBO_CONCURRENCY", "2") - .env_remove("CI") - .env_remove("GITHUB_ACTIONS") - .args(["run", "build"]) - .current_dir(tempdir.path()) - .output() - .unwrap(); + assert_concurrency_error(&output); + insta::assert_snapshot!( + "test_10_concurrency_2_flag", + String::from_utf8_lossy(&output.stderr).to_string() + ); - assert!(!output.status.success()); - let stderr = String::from_utf8_lossy(&output.stderr); - insta::assert_snapshot!("test_10_concurrency_2_env", stderr.to_string()); -} + let output = run_turbo_with_env( + tempdir.path(), + &["run", "build"], + &[("TURBO_CONCURRENCY", "2")], + ); + assert_concurrency_error(&output); + insta::assert_snapshot!( + "test_10_concurrency_2_env", + String::from_utf8_lossy(&output.stderr).to_string() + ); -#[test] -fn test_10_too_many_concurrency_3_flag() { - let tempdir = setup_persistent_deps("10-too-many"); let output = run_turbo(tempdir.path(), &["run", "build", "--concurrency=3"]); - assert!(output.status.success()); - let stdout = String::from_utf8_lossy(&output.stdout); - assert!( - stdout.contains("2 successful, 2 total"), - "expected output to contain '2 successful, 2 total', got:\n{stdout}" + assert_concurrency_success(&output); + + let output = run_turbo_with_env( + tempdir.path(), + &["run", "build"], + &[("TURBO_CONCURRENCY", "3")], ); + assert_concurrency_success(&output); } -#[test] -fn test_10_too_many_concurrency_3_env() { - let tempdir = setup_persistent_deps("10-too-many"); - let config_dir = tempfile::tempdir().unwrap(); - let mut cmd = assert_cmd::Command::cargo_bin("turbo").unwrap(); - let output = cmd - .env("TURBO_TELEMETRY_MESSAGE_DISABLED", "1") - .env("TURBO_GLOBAL_WARNING_DISABLED", "1") - .env("TURBO_PRINT_VERSION_DISABLED", "1") - .env("TURBO_CONFIG_DIR_PATH", config_dir.path()) - .env("DO_NOT_TRACK", "1") - .env("TURBO_CONCURRENCY", "3") - .env_remove("CI") - .env_remove("GITHUB_ACTIONS") - .args(["run", "build"]) - .current_dir(tempdir.path()) - .output() - .unwrap(); +fn assert_concurrency_error(output: &std::process::Output) { + assert!(!output.status.success()); +} +fn assert_concurrency_success(output: &std::process::Output) { assert!(output.status.success()); let stdout = String::from_utf8_lossy(&output.stdout); assert!( diff --git a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_env.snap b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_env.snap index 5e2336161c076..edc657459f6aa 100644 --- a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_env.snap +++ b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_env.snap @@ -1,6 +1,6 @@ --- source: crates/turborepo/tests/persistent_dependencies.rs -expression: stderr.to_string() +expression: String::from_utf8_lossy(&output.stderr).to_string() --- x Invalid task configuration `-> x You have 2 persistent tasks but `turbo` is configured for diff --git a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_flag.snap b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_flag.snap index 5e2336161c076..edc657459f6aa 100644 --- a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_flag.snap +++ b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_1_flag.snap @@ -1,6 +1,6 @@ --- source: crates/turborepo/tests/persistent_dependencies.rs -expression: stderr.to_string() +expression: String::from_utf8_lossy(&output.stderr).to_string() --- x Invalid task configuration `-> x You have 2 persistent tasks but `turbo` is configured for diff --git a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_env.snap b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_env.snap index 491e77b5e4c97..9fa9fb19eb542 100644 --- a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_env.snap +++ b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_env.snap @@ -1,6 +1,6 @@ --- source: crates/turborepo/tests/persistent_dependencies.rs -expression: stderr.to_string() +expression: String::from_utf8_lossy(&output.stderr).to_string() --- x Invalid task configuration `-> x You have 2 persistent tasks but `turbo` is configured for diff --git a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_flag.snap b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_flag.snap index 491e77b5e4c97..9fa9fb19eb542 100644 --- a/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_flag.snap +++ b/crates/turborepo/tests/snapshots/persistent_dependencies__test_10_concurrency_2_flag.snap @@ -1,6 +1,6 @@ --- source: crates/turborepo/tests/persistent_dependencies.rs -expression: stderr.to_string() +expression: String::from_utf8_lossy(&output.stderr).to_string() --- x Invalid task configuration `-> x You have 2 persistent tasks but `turbo` is configured for diff --git a/crates/turborepo/tests/workspace_config_override_test.rs b/crates/turborepo/tests/workspace_config_override_test.rs index 06c1aa45d2a9c..81197fb73b162 100644 --- a/crates/turborepo/tests/workspace_config_override_test.rs +++ b/crates/turborepo/tests/workspace_config_override_test.rs @@ -10,7 +10,7 @@ use common::{run_turbo, run_turbo_with_env, setup}; // outputLogs. #[test] -fn test_override_values_outputs() { +fn test_override_values() { let tempdir = tempfile::tempdir().unwrap(); setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) .unwrap(); @@ -38,45 +38,6 @@ fn test_override_values_outputs() { stdout2.contains("replaying logs"), "expected full replay with overridden outputLogs: {stdout2}" ); -} - -#[test] -fn test_override_values_inputs() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); - - run_turbo( - tempdir.path(), - &["run", "override-values-task", "--filter=override-values"], - ); - - // Change the workspace input (bar.txt, not foo.txt which is the root input) - let bar_path = tempdir.path().join("apps/override-values/src/bar.txt"); - let contents = fs::read_to_string(&bar_path).unwrap_or_default(); - fs::write(&bar_path, format!("{contents}\nmore text")).unwrap(); - - let output = run_turbo( - tempdir.path(), - &["run", "override-values-task", "--filter=override-values"], - ); - let stdout = String::from_utf8_lossy(&output.stdout); - assert!( - stdout.contains("cache miss"), - "workspace input change should miss: {stdout}" - ); -} - -#[test] -fn test_override_values_root_input_no_miss() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); - - run_turbo( - tempdir.path(), - &["run", "override-values-task", "--filter=override-values"], - ); // Change the ROOT input (foo.txt) — should NOT cause miss because workspace // overrides inputs @@ -94,18 +55,21 @@ fn test_override_values_root_input_no_miss() { stdout.contains("FULL TURBO"), "root input should be overridden, no miss: {stdout}" ); -} -#[test] -fn test_override_values_env() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); + // Change the workspace input (bar.txt, not foo.txt which is the root input) + let bar_path = tempdir.path().join("apps/override-values/src/bar.txt"); + let contents = fs::read_to_string(&bar_path).unwrap_or_default(); + fs::write(&bar_path, format!("{contents}\nmore text")).unwrap(); - run_turbo( + let output = run_turbo( tempdir.path(), &["run", "override-values-task", "--filter=override-values"], ); + let stdout = String::from_utf8_lossy(&output.stdout); + assert!( + stdout.contains("cache miss"), + "workspace input change should miss: {stdout}" + ); // Workspace overrides env to OTHER_VAR (not SOME_VAR from root) let output = run_turbo_with_env( @@ -123,7 +87,7 @@ fn test_override_values_env() { // Tests that a workspace can add keys when root task has empty config. #[test] -fn test_add_keys_deps_and_outputs() { +fn test_add_keys() { let tempdir = tempfile::tempdir().unwrap(); setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) .unwrap(); @@ -140,19 +104,6 @@ fn test_add_keys_deps_and_outputs() { "dependent task should run: {stdout}" ); assert!(stdout.contains("2 successful, 2 total")); -} - -#[test] -fn test_add_keys_cache_and_output_logs() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); - - // Prime cache - run_turbo( - tempdir.path(), - &["run", "add-keys-task", "--filter=add-keys"], - ); // Second run: cache hit, outputLogs "new-only" means add-keys-task logs // suppressed @@ -169,18 +120,6 @@ fn test_add_keys_cache_and_output_logs() { stdout.contains("add-keys:add-keys-task: cache hit, suppressing logs"), "outputLogs new-only should suppress on hit: {stdout}" ); -} - -#[test] -fn test_add_keys_input_change() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); - - run_turbo( - tempdir.path(), - &["run", "add-keys-task", "--filter=add-keys"], - ); let foo_path = tempdir.path().join("apps/add-keys/src/foo.txt"); let mut contents = fs::read_to_string(&foo_path).unwrap(); @@ -196,18 +135,6 @@ fn test_add_keys_input_change() { stdout.contains("0 cached, 2 total"), "input change should miss: {stdout}" ); -} - -#[test] -fn test_add_keys_env_change() { - let tempdir = tempfile::tempdir().unwrap(); - setup::setup_integration_test(tempdir.path(), "composable_config", "npm@10.5.0", false) - .unwrap(); - - run_turbo( - tempdir.path(), - &["run", "add-keys-task", "--filter=add-keys"], - ); let output = run_turbo_with_env( tempdir.path(),