use super::*;
use crate::core::config::{Language, NewAlefConfig, ResolvedCrateConfig};
fn make_config() -> ResolvedCrateConfig {
let cfg: NewAlefConfig = toml::from_str(
r#"
[workspace]
languages = ["python"]
[[crates]]
name = "sample-model"
sources = ["src/lib.rs"]
"#,
)
.expect("valid config");
cfg.resolve().unwrap().remove(0)
}
fn write_tree(base: &Path) {
let package = base.join("packages/python");
std::fs::create_dir_all(&package).expect("package dir");
std::fs::write(package.join("sample.py"), "x=1").expect("generated file");
std::fs::write(base.join("Cargo.toml"), "[workspace]\nmembers = []\n").expect("root manifest");
}
#[test]
fn an_uninstalled_package_formatter_is_recorded_and_survived_by_default() {
let dir = tempfile::tempdir().expect("tempdir");
write_tree(dir.path());
let skipped = format_generated_reporting_with(&make_config(), dir.path(), None, false, &|_tool| false)
.expect("a missing formatter must not fail the run without --strict");
let steps: Vec<&str> = skipped.iter().map(|entry| entry.step.as_str()).collect();
assert!(
steps.iter().any(|step| step.starts_with(POLY_FMT_STEP)),
"the skipped `poly fmt --fix` pass must reach the caller, not just a warning: {steps:?}"
);
assert!(
steps.iter().any(|step| step.starts_with(CARGO_FMT_STEP)),
"the skipped workspace `cargo fmt` must reach the caller: {steps:?}"
);
assert!(
steps.iter().any(|step| step.starts_with(CARGO_SORT_STEP)),
"the skipped workspace `cargo sort` must reach the caller: {steps:?}"
);
assert_eq!(
std::fs::read_to_string(dir.path().join("packages/python/sample.py")).unwrap(),
"x=1",
"with no formatter installed the generated file must be left exactly as emitted"
);
}
#[test]
fn an_uninstalled_package_formatter_aborts_the_run_under_strict() {
let dir = tempfile::tempdir().expect("tempdir");
write_tree(dir.path());
let error = format_generated_reporting_with(&make_config(), dir.path(), None, true, &|_tool| false)
.expect_err("--strict must fail the run when a configured formatter is not installed");
let message = format!("{error:#}");
assert!(
message.contains("--strict"),
"the failure must say which flag made it fatal: {message}"
);
assert!(
message.contains(POLY_FMT_STEP),
"the failure must name the step that could not run: {message}"
);
}
#[test]
fn strict_is_inert_when_every_formatter_is_installed() {
let dir = tempfile::tempdir().expect("tempdir");
write_tree(dir.path());
let only: HashSet<Language> = [Language::Python].into_iter().collect();
let skipped = format_generated_reporting_with(
&make_config(),
&dir.path().join("absent"),
Some(&only),
true,
&|_tool| true,
)
.expect("nothing skipped means nothing to escalate");
assert!(skipped.is_empty(), "no step was skipped, so nothing may be recorded");
}
#[test]
fn a_missing_language_residual_records_under_its_own_language() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let elixir = base.join("packages/elixir");
std::fs::create_dir_all(&elixir).expect("elixir package dir");
std::fs::write(elixir.join("mix.exs"), "defmodule Sample.MixProject do\nend\n").expect("mix.exs");
let cfg: NewAlefConfig = toml::from_str(
r#"
[workspace]
languages = ["elixir"]
[[crates]]
name = "sample-model"
sources = ["src/lib.rs"]
"#,
)
.expect("valid config");
let config = cfg.resolve().unwrap().remove(0);
let only: HashSet<Language> = [Language::Elixir].into_iter().collect();
let skipped = format_generated_reporting_with(&config, base, Some(&only), false, &|tool| tool != "mix")
.expect("a missing residual must not fail the run without --strict");
let mix = skipped
.iter()
.find(|entry| entry.step.starts_with("mix format"))
.unwrap_or_else(|| panic!("`mix format` must be recorded when mix is absent: {skipped:?}"));
assert_eq!(
mix.language, "elixir",
"a per-language residual must record under its language, not the whole-tree scope"
);
}
#[test]
fn a_recorded_skip_is_classified_as_a_missing_toolchain() {
let dir = tempfile::tempdir().expect("tempdir");
write_tree(dir.path());
let skipped =
format_generated_reporting_with(&make_config(), dir.path(), None, false, &|_tool| false).expect("lenient run");
assert!(
!skipped.is_empty(),
"the probe reports every tool absent, so steps were skipped"
);
for entry in &skipped {
assert!(
entry.is_missing_toolchain(),
"every recorded package-formatter skip must classify as a missing toolchain, or the \
shared reporter files it under the wrong heading and --strict stops escalating it: \
{entry:?}"
);
assert!(
entry.step.contains("missing: "),
"the record must name the executable to install: {entry:?}"
);
}
}
#[test]
fn poly_lint_fails_loudly_when_poly_is_not_on_path() {
let dir = tempfile::tempdir().expect("tempdir");
let error =
poly_lint_with(dir.path(), &|_tool| false).expect_err("a missing poly must fail alef lint, not report clean");
assert!(
error.to_string().contains("poly"),
"the error must name the missing tool: {error}"
);
}