use assert_cmd::Command;
use predicates::prelude::*;
fn help_text(args: &[&str]) -> String {
let output = Command::cargo_bin("truth-mirror")
.unwrap()
.args(args)
.assert()
.success()
.get_output()
.stdout
.clone();
String::from_utf8(output).unwrap()
}
fn help_text_for_bin(bin: &str, args: &[&str]) -> String {
let output = Command::cargo_bin(bin)
.unwrap()
.args(args)
.assert()
.success()
.get_output()
.stdout
.clone();
String::from_utf8(output).unwrap()
}
#[test]
fn root_help_exposes_brief_defined_surface() {
let help = help_text(&["--help"]);
for expected in [
"install-hooks",
"review",
"gate",
"reinject",
"ledger",
"watch",
"status",
] {
assert!(
help.contains(expected),
"missing {expected} in help:\n{help}"
);
}
}
#[test]
fn truth_alias_exposes_same_cli_surface() {
let help = help_text_for_bin("truth", &["--help"]);
assert!(help.contains("Usage: truth"), "wrong alias help:\n{help}");
for expected in [
"install-hooks",
"review",
"gate",
"reinject",
"ledger",
"watch",
"status",
] {
assert!(
help.contains(expected),
"missing {expected} in truth help:\n{help}"
);
}
}
#[test]
fn truth_alias_reports_own_binary_name_in_version() {
let version = help_text_for_bin("truth", &["--version"]);
assert_eq!(
version.trim(),
format!("truth {}", env!("CARGO_PKG_VERSION"))
);
}
#[test]
fn status_help_exposes_repo_diagnostics() {
let help = help_text(&["status", "--help"]);
assert!(
help.contains("hook wiring"),
"missing status diagnostics description in help:\n{help}"
);
}
#[test]
fn watch_once_and_until_empty_are_mutually_exclusive() {
Command::cargo_bin("truth-mirror")
.unwrap()
.args(["watch", "--once", "--until-empty"])
.assert()
.failure()
.stderr(predicate::str::contains(
"the argument '--once' cannot be used with '--until-empty'",
));
}
#[test]
fn install_hooks_help_exposes_agent_and_lifecycle_flags() {
let help = help_text(&["install-hooks", "--help"]);
for expected in [
"--claude",
"--codex",
"--pi",
"--grok",
"--uninstall",
"--dry-run",
"--inject-forwarder",
] {
assert!(
help.contains(expected),
"missing {expected} in help:\n{help}"
);
}
}
#[test]
fn review_help_exposes_model_opposition_and_strict_mode_flags() {
let help = help_text(&["review", "--help"]);
for expected in [
"--staged",
"--watched-agent",
"--reviewer-harness",
"--watched-model",
"--reviewer-model",
"--allow-same-model",
"--strict-two-pass",
"--scope",
"--base",
"status",
"result",
"cancel",
] {
assert!(
help.contains(expected),
"missing {expected} in help:\n{help}"
);
}
}
#[test]
fn gate_help_exposes_pre_push_range() {
let help = help_text(&["gate", "--help"]);
assert!(
help.contains("--pre-push"),
"missing --pre-push in help:\n{help}"
);
assert!(
help.contains("--commit-msg"),
"missing --commit-msg in help:\n{help}"
);
assert!(
help.contains("--claim-file"),
"missing --claim-file in help:\n{help}"
);
assert!(
help.contains("--diff-file"),
"missing --diff-file in help:\n{help}"
);
assert!(
help.contains("RANGE"),
"missing RANGE value name in help:\n{help}"
);
}
#[test]
fn reinject_help_requires_agent_selection() {
let help = help_text(&["reinject", "--help"]);
assert!(help.contains("--agent"), "missing --agent in help:\n{help}");
for expected in ["claude", "codex", "pi", "grok"] {
assert!(
help.contains(expected),
"missing {expected} in help:\n{help}"
);
}
}
#[test]
fn ledger_help_exposes_all_required_subcommands() {
let help = help_text(&["ledger", "--help"]);
for expected in ["list", "show", "history", "stats"] {
assert!(
help.contains(expected),
"missing {expected} in help:\n{help}"
);
}
}