use std::path::PathBuf;
use super::super::dd_manifest::{DdManifest, DdManifestError, DdReportSection, DdRepositoryEntry};
use super::merge_into;
const GROUNDED: &str = r#"
[report]
title = "Acme — Technical Due Diligence"
analyst = "J. Reviewer"
gaps = ["jira sync: no JIRA project configured"]
investigate_max_files = 240
investigate_max_bytes = 1200000
attributed_only = true
[[repositories]]
name = "acme-api"
path = "/srv/checkouts/acme-api"
inspect_priority = ["src/auth.rs", "src/billing.rs"]
[repositories.crate_topology]
members = 12
edges = 31
cycles = 0
"#;
fn fresh() -> DdManifest {
DdManifest {
report: DdReportSection {
title: "Acme — Technical Due Diligence".to_string(),
analyst: None,
client: Some("Acme Holdings".to_string()),
gaps: vec!["linear sync: no Linear workspace configured".to_string()],
ticketing: Some(PathBuf::from("ticketing.json")),
},
repositories: vec![DdRepositoryEntry {
name: "acme-api".to_string(),
path: PathBuf::from("/srv/checkouts/acme-api"),
authorship: Some(PathBuf::from("authorship-0.json")),
}],
}
}
#[test]
fn a_rebuilt_manifest_never_destroys_the_grounded_investigation_scope() {
let replacing = fresh().to_toml().expect("serialize");
for key in [
"inspect_priority",
"crate_topology",
"investigate_max_files",
] {
assert!(
!replacing.contains(key),
"the pre-#6190 write carried `{key}` — this baseline is wrong: {replacing}"
);
}
let merged = merge_into(&fresh(), GROUNDED).expect("a grounded manifest is valid TOML");
assert!(
merged.contains("inspect_priority") && merged.contains("src/billing.rs"),
"the evidence ranking must survive a tga re-run: {merged}"
);
assert!(
merged.contains("crate_topology") && merged.contains("edges"),
"the crate topology must survive a tga re-run: {merged}"
);
assert!(
merged.contains("investigate_max_files = 240")
&& merged.contains("investigate_max_bytes = 1200000"),
"the investigation budget must survive a tga re-run: {merged}"
);
assert!(
merged.contains("attributed_only = true"),
"the rule is 'tga rewrites only its own keys', not a preserve-list: {merged}"
);
assert!(
merged.contains(r#"client = "Acme Holdings""#)
&& merged.contains(r#"authorship = "authorship-0.json""#)
&& merged.contains(r#"ticketing = "ticketing.json""#),
"this run's own contributions must reach the file: {merged}"
);
assert_eq!(
merged.matches("[[repositories]]").count(),
1,
"matching by path is what keeps the ranking attached to one entry: {merged}"
);
let reparsed: toml::Value = toml::from_str(&merged).expect("the merge emits valid TOML");
assert_eq!(
reparsed["repositories"][0]["inspect_priority"][0].as_str(),
Some("src/auth.rs")
);
}
#[test]
fn an_absent_flag_keeps_the_value_the_file_already_carries() {
let merged = merge_into(&fresh(), GROUNDED).expect("merge");
assert!(
merged.contains(r#"analyst = "J. Reviewer""#),
"an absent --analyst must not delete the declared one: {merged}"
);
}
#[test]
fn this_runs_gaps_replace_the_files_rather_than_accumulating() {
let merged = merge_into(&fresh(), GROUNDED).expect("merge");
assert!(
merged.contains("no Linear workspace configured"),
"this run's gaps must reach the file: {merged}"
);
assert!(
!merged.contains("no JIRA project configured"),
"a previous run's gap must not be asserted about this one: {merged}"
);
}
#[test]
fn entries_are_added_without_disturbing_the_ones_this_run_does_not_name() {
let mut manifest = fresh();
manifest.repositories[0] = DdRepositoryEntry {
name: "acme-web".to_string(),
path: PathBuf::from("/srv/checkouts/acme-web"),
authorship: None,
};
let merged = merge_into(&manifest, GROUNDED).expect("merge");
let reparsed: toml::Value = toml::from_str(&merged).expect("valid TOML");
let repos = reparsed["repositories"].as_array().expect("array");
assert_eq!(repos.len(), 2, "the new repository is appended: {merged}");
assert_eq!(repos[0]["name"].as_str(), Some("acme-api"));
assert!(
repos[0].get("inspect_priority").is_some(),
"an entry this run does not name keeps everything it had: {merged}"
);
assert_eq!(repos[1]["name"].as_str(), Some("acme-web"));
}
#[test]
fn a_moved_checkout_matches_on_name_when_the_path_changed() {
let no_path = r#"
[[repositories]]
name = "acme-api"
inspect_priority = ["src/auth.rs"]
"#;
let merged = merge_into(&fresh(), no_path).expect("merge");
assert_eq!(
merged.matches("[[repositories]]").count(),
1,
"the name fallback must not produce a second entry: {merged}"
);
assert!(
merged.contains("inspect_priority") && merged.contains("/srv/checkouts/acme-api"),
"the ranking stays and the path is updated: {merged}"
);
}
#[test]
fn an_unparseable_manifest_is_refused_not_replaced() {
let err = merge_into(&fresh(), "this is not = = TOML [[[")
.expect_err("an unparseable manifest must never be silently replaced");
assert!(matches!(err, DdManifestError::MergeSource(_)));
assert!(
format!("{err}").contains("move it aside"),
"the error must tell the operator what to do: {err}"
);
let wrong_shape = merge_into(&fresh(), "report = 3\n")
.expect_err("a `report` that is not a table cannot be merged into");
assert!(matches!(wrong_shape, DdManifestError::MergeSource(_)));
}
#[test]
fn a_first_run_writes_exactly_what_it_always_did() {
let manifest = fresh();
assert_eq!(
manifest.to_toml_merged(None).expect("serialize"),
manifest.to_toml().expect("serialize"),
"a fresh output directory must not change shape"
);
}
#[test]
fn an_empty_manifest_file_yields_a_complete_manifest() {
let merged = merge_into(&fresh(), "").expect("an empty document is valid TOML");
let reparsed: toml::Value = toml::from_str(&merged).expect("valid TOML");
assert_eq!(
reparsed["report"]["title"].as_str(),
Some("Acme — Technical Due Diligence")
);
assert_eq!(
reparsed["repositories"][0]["name"].as_str(),
Some("acme-api")
);
}