use koala_core::invariant::Context;
use koala_drift::{format_report, Registry as DriftRegistry};
use std::fs;
use tempfile::TempDir;
fn write(dir: &std::path::Path, rel: &str, body: &str) {
let p = dir.join(rel);
fs::create_dir_all(p.parent().unwrap()).unwrap();
fs::write(p, body).unwrap();
}
fn run_with_violation() -> (DriftRegistry, Vec<koala_drift::Finding>) {
let tmp = TempDir::new().unwrap();
let body = "---\n\
id: x\n\
status: in-progress\n\
---\n\
# X\n\n\
## Acceptance criteria(机械可验证)\n\n\
- [ ] does the thing\n\
→ crates/x/tests/missing.rs#none\n";
write(tmp.path(), "wiki/features/x.md", body);
let ctx = Context::new(tmp.path().to_path_buf());
let reg = DriftRegistry::builtin();
let findings = reg.run_all(&ctx);
(reg, findings.to_vec())
}
#[test]
fn explain_offers_fix_hints() {
let (reg, findings) = run_with_violation();
let out = format_report(®, &findings, true);
assert!(
out.contains("intent:"),
"explain mode missing intent: {out}"
);
assert!(
out.contains("▶ hint:"),
"should always show fix hint: {out}"
);
assert!(
out.contains("[feature.acceptance-test-ref]"),
"should label finding by check id: {out}"
);
}
#[test]
fn non_explain_truncates_claim_and_omits_intent() {
let (reg, findings) = run_with_violation();
let out = format_report(®, &findings, false);
assert!(
!out.contains("intent:"),
"non-explain mode should not show intent: {out}"
);
assert!(out.contains("▶ hint:"), "fix hint always shown: {out}");
}
#[test]
fn empty_findings_reports_clean() {
let tmp = TempDir::new().unwrap();
let ctx = Context::new(tmp.path().to_path_buf());
let reg = DriftRegistry::builtin();
let findings = reg.run_all(&ctx);
let out = format_report(®, &findings, true);
assert!(
out.starts_with("drift: no findings"),
"empty repo should report clean: {out}"
);
let expected = format!("{} check(s)", reg.len());
assert!(
out.contains(&expected),
"should mention check count ({expected}): {out}"
);
}