use assert_cmd::Command;
use predicates::str::contains;
fn ign() -> Command {
let mut cmd = Command::cargo_bin("ign").expect("binary 'ign' not found");
let isolated = std::env::temp_dir().join(format!("ign-chassis-{}.toml", std::process::id()));
cmd.env("IGNITION_CLI_CONFIG", isolated);
cmd
}
#[test]
fn help_lists_all_five_global_flags() {
ign()
.arg("--help")
.assert()
.success()
.stdout(contains("--profile"))
.stdout(contains("--json"))
.stdout(contains("--compact"))
.stdout(contains("--yes"))
.stdout(contains("--verbose"));
}
#[test]
fn version_flag_exits_zero() {
ign()
.arg("--version")
.assert()
.success()
.stdout(contains(env!("CARGO_PKG_VERSION")));
}
#[test]
fn version_subcommand_works_without_config() {
ign()
.arg("version")
.assert()
.success()
.stdout(contains(env!("CARGO_PKG_VERSION")));
}
#[test]
fn env_json_flag_is_accepted() {
ign()
.env("IGNITION_JSON", "1")
.arg("version")
.assert()
.success();
}
#[test]
fn env_yes_flag_is_accepted() {
ign()
.env("IGNITION_YES", "1")
.arg("version")
.assert()
.success();
}
#[test]
fn unknown_flag_exits_two() {
ign().arg("--bogus").assert().failure().code(2);
}
#[test]
fn verbose_keeps_stdout_version_line_only() {
ign()
.arg("version")
.arg("-v")
.assert()
.success()
.stdout(format!(
"ign {} (ignition-cli)\n",
env!("CARGO_PKG_VERSION")
));
}
#[test]
fn completions_bash_generate() {
ign()
.args(["completions", "bash"])
.assert()
.success()
.stdout(contains("_ign"));
}
#[test]
fn completions_zsh_generate() {
ign()
.args(["completions", "zsh"])
.assert()
.success()
.stdout(contains("#compdef ign"));
}
#[test]
fn completions_fish_generate() {
ign()
.args(["completions", "fish"])
.assert()
.success()
.stdout(contains("complete -c ign"));
}
#[test]
fn completions_without_shell_exit_2() {
ign()
.args(["completions"])
.assert()
.failure()
.code(2)
.stderr(contains("SHELL"));
}
#[test]
fn completions_ignore_json_flag() {
ign()
.args(["completions", "bash", "--json"])
.assert()
.success()
.stdout(contains("_ign"))
.stdout(contains("complete -F _ign"));
}
#[test]
fn tui_under_a_pipe_refuses_with_the_interactive_terminal_hint() {
let dir = tempfile::tempdir().expect("tempdir");
let config = dir.path().join("config.toml");
std::fs::write(
&config,
"active = \"dev\"\n\n[profiles.dev]\nurl = \"http://127.0.0.1:1\"\nauth = { token_env = \"IGNITION_TOKEN\" }\n",
)
.expect("write config");
let out = {
let mut cmd = Command::cargo_bin("ign").expect("binary 'ign' not found");
cmd.env("IGNITION_CLI_CONFIG", &config)
.env("IGNITION_TOKEN", "mock:name-key")
.args(["--compact", "tui"])
.output()
.expect("spawn ign")
};
assert_eq!(out.status.code(), Some(2), "usage class");
assert!(
out.stdout.is_empty(),
"no alt-screen escapes, no stdout: {:?}",
String::from_utf8_lossy(&out.stdout)
);
let stderr = String::from_utf8_lossy(&out.stderr);
let start = stderr.find('{').expect("envelope on stderr");
snapbox::Assert::new().action_env("SNAPSHOTS").eq(
stderr[start..].trim_end().to_string(),
snapbox::str![[r#"
{"ok":false,"profile":null,"error":{"code":"invalid_input","message":"invalid input: ign tui requires a terminal (stdout is not a TTY)","endpoint":null,"hint":"run `ign tui` in an interactive terminal (the cockpit needs a TTY on stdout — not a pipe or redirect)"}}
"#]],
);
}