use assert_cmd::Command;
use predicates::prelude::*;
#[test]
fn hook_binary_returns_allow_when_daemon_unreachable() {
let input = r#"{"tool_name": "Write", "tool_input": {"path": "test.rs"}}"#;
Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin(input)
.assert()
.success()
.stdout(predicate::str::contains("permissionDecision"))
.stdout(predicate::str::contains("allow"));
}
#[test]
fn hook_binary_handles_empty_stdin() {
Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin("")
.assert()
.success()
.stdout(predicate::str::contains("allow"));
}
#[test]
fn hook_binary_handles_malformed_json() {
Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin("this is not json {{{")
.assert()
.success()
.stdout(predicate::str::contains("allow"));
}
#[test]
fn hook_binary_returns_approve_for_stop_event() {
let input = r#"{"stopReason": "end_turn", "session_id": "abc"}"#;
Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin(input)
.assert()
.success()
.stdout(predicate::str::contains("approve"));
}
#[test]
fn hook_binary_stdout_is_valid_json() {
let input = r#"{"tool_name": "Bash", "tool_input": {"command": "ls"}}"#;
let output = Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin(input)
.output()
.expect("failed to run openlatch-hook");
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).expect("stdout not UTF-8");
let _: serde_json::Value =
serde_json::from_str(stdout.trim()).expect("stdout is not valid JSON");
}
#[test]
fn hook_binary_output_includes_hook_event_name() {
let input = r#"{"tool_name": "Write", "tool_input": {"path": "foo.rs"}}"#;
Command::cargo_bin("openlatch-hook")
.unwrap()
.write_stdin(input)
.assert()
.success()
.stdout(predicate::str::contains("hookEventName"))
.stdout(predicate::str::contains("PreToolUse"));
}
#[test]
#[ignore]
fn hook_binary_size_under_1mb() {
let output = std::process::Command::new("cargo")
.args([
"build",
"--release",
"--bin",
"openlatch-hook",
"--no-default-features",
])
.output()
.expect("cargo build failed");
assert!(output.status.success(), "cargo build --release failed");
let binary_path = if cfg!(windows) {
std::path::PathBuf::from("target/release/openlatch-hook.exe")
} else {
std::path::PathBuf::from("target/release/openlatch-hook")
};
let metadata = std::fs::metadata(&binary_path)
.unwrap_or_else(|_| panic!("binary not found at {:?}", binary_path));
assert!(
metadata.len() < 1_048_576,
"hook binary is {}B, must be < 1MB",
metadata.len()
);
}