use super::*;
fn cfg(precondition: &str, dependency_precondition: Option<&str>) -> BuildCommandConfig {
BuildCommandConfig {
precondition: Some(precondition.to_string()),
dependency_precondition: dependency_precondition.map(str::to_string),
dependency_remediation: dependency_precondition.map(|_| "cd packages/elixir && mix deps.get".to_string()),
before: None,
build: None,
build_release: None,
timeout_seconds: None,
}
}
#[test]
fn should_report_unfetched_dependencies_when_the_tool_is_present_but_deps_are_not() {
let readiness = backend_readiness(Language::Elixir, &cfg("true", Some("false")));
assert_eq!(
readiness,
BackendReadiness::DependenciesUnfetched {
check: "false".to_string(),
remediation: "cd packages/elixir && mix deps.get".to_string(),
}
);
}
#[test]
fn should_stay_ready_when_every_precondition_passes_so_a_real_compile_failure_still_fails() {
assert_eq!(
backend_readiness(Language::Elixir, &cfg("true", Some("true"))),
BackendReadiness::Ready
);
assert_eq!(
backend_readiness(Language::Go, &cfg("true", None)),
BackendReadiness::Ready
);
let error =
build_outcome(&["go: undefined: Foo".to_string()], &[], &[], false).expect_err("compile failure is fatal");
let message = error.to_string();
assert!(message.contains("backend build failed for 1 language(s)"), "{message}");
assert!(!message.contains("preconditions are unmet"), "{message}");
}
#[test]
fn should_report_a_missing_tool_as_a_toolchain_skip_not_as_unfetched_dependencies() {
let readiness = backend_readiness(Language::Elixir, &cfg("false", Some("false")));
assert_eq!(
readiness,
BackendReadiness::ToolchainMissing {
precondition: "false".to_string(),
}
);
}
#[test]
fn should_exit_clean_when_the_only_thing_that_happened_was_a_toolchain_skip() {
assert!(build_outcome(&[], &[], &["elixir".to_string()], false).is_ok());
}
#[test]
fn should_fail_the_run_under_strict_when_a_language_was_skipped_for_a_missing_toolchain() {
let error = build_outcome(&[], &[], &["elixir".to_string(), "kotlin".to_string()], true)
.expect_err("--strict must not exit clean over an unexamined language");
let message = error.to_string();
assert!(message.contains("--strict is set"), "{message}");
assert!(message.contains("2 language(s)"), "{message}");
assert!(message.contains("elixir"), "{message}");
assert!(message.contains("kotlin"), "{message}");
}
#[test]
fn should_stay_clean_without_strict_even_when_toolchain_missing_is_non_empty() {
assert!(build_outcome(&[], &[], &["swift".to_string()], false).is_ok());
}
#[test]
fn should_fail_the_run_for_unmet_preconditions_while_naming_them_separately_from_failures() {
let error = build_outcome(
&[],
&["elixir (run `cd packages/elixir && mix deps.get`)".to_string()],
&[],
false,
)
.expect_err("unmet preconditions must not exit clean");
let message = error.to_string();
assert!(message.contains("1 language(s) not built"), "{message}");
assert!(message.contains("not a compile failure"), "{message}");
assert!(message.contains("mix deps.get"), "{message}");
assert!(!message.contains("backend build failed"), "{message}");
}
#[test]
fn should_keep_failure_and_unmet_counts_separate_when_both_occur() {
let error = build_outcome(
&["go: undefined: Foo".to_string()],
&["elixir (run `mix deps.get`)".to_string()],
&[],
false,
)
.expect_err("either bucket is fatal");
let message = error.to_string();
assert!(message.contains("backend build failed for 1 language(s)"), "{message}");
assert!(message.contains("1 language(s) not built"), "{message}");
}