use super::*;
fn write_settings(project: &Path, contents: &serde_json::Value) -> PathBuf {
let claude_dir = project.join(".claude");
std::fs::create_dir_all(&claude_dir).expect("create .claude");
std::fs::write(
claude_dir.join("settings.json"),
serde_json::to_string_pretty(contents).expect("serialize fixture"),
)
.expect("write settings.json");
project.to_path_buf()
}
fn claude_mpm_hooks_value() -> serde_json::Value {
serde_json::json!({
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "claude-mpm hooks fire SessionStart",
"timeout": 5
}]
}]
}
})
}
#[test]
fn detects_foreign_hooks_in_launch_dir() {
let tmp = tempfile::TempDir::new().expect("temp dir");
let project = write_settings(
&tmp.path().join("foreign-project"),
&claude_mpm_hooks_value(),
);
let found = foreign_harness_files(std::slice::from_ref(&project));
assert_eq!(
found,
vec![project.join(".claude").join("settings.json")],
"a claude-mpm-hooked settings file must be reported"
);
}
#[test]
fn clean_dir_reports_nothing() {
let tmp = tempfile::TempDir::new().expect("temp dir");
let project = write_settings(
&tmp.path().join("clean-project"),
&serde_json::json!({ "outputStyle": "trusty-mpm" }),
);
assert!(
foreign_harness_files(&[project]).is_empty(),
"a settings file with no foreign hooks must produce no finding"
);
}
#[test]
fn malformed_settings_file_is_skipped_not_panicked() {
let tmp = tempfile::TempDir::new().expect("temp dir");
let project = tmp.path().join("broken-project");
std::fs::create_dir_all(project.join(".claude")).expect("create .claude");
std::fs::write(project.join(".claude").join("settings.json"), "{ not json")
.expect("write malformed settings");
assert!(
foreign_harness_files(&[project]).is_empty(),
"an unparseable settings file contributes no finding"
);
}
#[test]
fn launch_and_workspace_dirs_are_deduplicated() {
let launch = Path::new("/tmp/an-unmanaged-clone");
let managed = Path::new("/tmp/projects/an-owner/a-repo");
assert_eq!(
launch_scan_dirs(launch, managed),
vec![launch.to_path_buf(), managed.to_path_buf()],
"a redirected launch scans the launch directory AND the managed checkout"
);
assert_eq!(
launch_scan_dirs(managed, managed),
vec![managed.to_path_buf()],
"an unredirected launch scans one directory, not the same one twice"
);
}