use assert_cmd::prelude::*;
use serde_json::Value;
use std::process::Command;
fn bin() -> Command {
Command::cargo_bin("grex").expect("grex binary")
}
fn parse_json_stdout(out: &std::process::Output) -> Value {
let stdout = String::from_utf8(out.stdout.clone()).expect("valid utf8 stdout");
serde_json::from_str::<Value>(&stdout)
.unwrap_or_else(|e| panic!("stdout is not valid JSON: {e}\n---\n{stdout}\n---"))
}
fn assert_unimplemented(verb: &str, extra_args: &[&str]) {
let mut cmd = bin();
cmd.arg("--json");
cmd.arg(verb);
for a in extra_args {
cmd.arg(a);
}
let out = cmd.assert().success().get_output().clone();
let v = parse_json_stdout(&out);
assert_eq!(v.get("status").and_then(Value::as_str), Some("unimplemented"), "status field");
assert_eq!(v.get("verb").and_then(Value::as_str), Some(verb), "verb field for {verb}");
}
#[test]
fn init_json_emits_unimplemented() {
assert_unimplemented("init", &[]);
}
#[test]
fn add_json_emits_unimplemented() {
assert_unimplemented("add", &["https://example.com/repo.git"]);
}
#[test]
fn rm_json_emits_unimplemented() {
assert_unimplemented("rm", &["some-pack"]);
}
#[test]
fn ls_json_emits_unimplemented() {
assert_unimplemented("ls", &[]);
}
#[test]
fn status_json_emits_unimplemented() {
assert_unimplemented("status", &[]);
}
#[test]
fn update_json_emits_unimplemented() {
assert_unimplemented("update", &[]);
}
#[test]
fn run_json_emits_unimplemented() {
assert_unimplemented("run", &["some-action"]);
}
#[test]
fn exec_json_emits_unimplemented() {
assert_unimplemented("exec", &["echo", "hi"]);
}
fn assert_usage_error(verb: &str) {
let out = bin().args([verb, "--json"]).assert().failure().get_output().clone();
assert_eq!(out.status.code(), Some(2), "{verb} --json must exit 2 on missing pack_root");
let v = parse_json_stdout(&out);
assert_eq!(v.get("verb").and_then(Value::as_str), Some(verb));
assert_eq!(
v.pointer("/error/kind").and_then(Value::as_str),
Some("usage"),
"error.kind must be `usage`"
);
}
#[test]
fn sync_without_pack_root_json_emits_usage_error() {
assert_usage_error("sync");
}
#[test]
fn teardown_without_pack_root_json_emits_usage_error() {
assert_usage_error("teardown");
}
#[test]
fn doctor_json_has_findings_array() {
let dir = tempfile::tempdir().unwrap();
let out =
bin().current_dir(dir.path()).args(["doctor", "--json"]).assert().get_output().clone();
let v: Value = serde_json::from_slice(&out.stdout).expect("doctor --json is valid JSON");
assert!(v.get("findings").is_some(), "doctor JSON must have a `findings` array");
assert!(v.get("exit_code").is_some(), "doctor JSON must have an `exit_code`");
}
#[test]
fn import_json_missing_arg_is_error_but_stays_non_panicking() {
bin().args(["import", "--json"]).assert().failure();
}