use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
fn ev() -> Command {
Command::new(env!("CARGO_BIN_EXE_ev"))
}
fn repo() -> std::path::PathBuf {
static N: AtomicU64 = AtomicU64::new(0);
let p = std::env::temp_dir().join(format!(
"ev-brief-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::Relaxed)
));
let _ = std::fs::remove_dir_all(&p);
std::fs::create_dir_all(&p).unwrap();
assert!(ev()
.arg("init")
.current_dir(&p)
.output()
.unwrap()
.status
.success());
p
}
fn decide(repo: &std::path::Path, text: &str, extra: &[&str]) -> String {
let mut args: Vec<&str> = vec!["decide", text, "--assume", "a reason", "--blame", "Wang Yu"];
args.extend_from_slice(extra);
let out = ev().args(&args).current_dir(repo).output().unwrap();
assert!(
out.status.success(),
"decide: {}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout)
.split_whitespace()
.nth(1)
.unwrap()
.to_string()
}
#[test]
fn brief_should_show_a_user_ruled_decision_and_its_rejected_road_when_one_is_recorded() {
let r = repo();
decide(
&r,
"keep the slice locked",
&[
"--authority",
"user-ruled",
"--reject",
"v1.9: re-milestoned without sign-off",
],
);
let out = ev().arg("brief").current_dir(&r).output().unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("keep the slice locked"));
assert!(stdout.contains("[user-ruled]"));
assert!(stdout.contains("rejected v1.9"));
}
#[test]
fn brief_should_omit_a_decision_that_is_not_user_ruled_when_briefing() {
let r = repo();
decide(&r, "a disposable decision", &[]);
let out = ev().arg("brief").current_dir(&r).output().unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(!stdout.contains("a disposable decision"));
assert!(stdout.contains("no user-ruled decisions"));
}
#[test]
fn brief_should_accept_a_limit_flag_when_one_is_passed() {
let r = repo();
decide(&r, "keep the slice locked", &["--authority", "user-ruled"]);
let out = ev()
.args(["brief", "--limit", "1"])
.current_dir(&r)
.output()
.unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("keep the slice locked"));
}
#[test]
fn brief_should_order_user_ruled_decisions_most_recent_first_when_multiple_exist() {
let r = repo();
decide(&r, "decision A", &["--authority", "user-ruled"]);
decide(&r, "decision B", &["--authority", "user-ruled"]);
let out = ev().arg("brief").current_dir(&r).output().unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
let b = stdout.find("decision B").expect("B shown");
let a = stdout.find("decision A").expect("A shown");
assert!(b < a, "B should appear before A:\n{stdout}");
}
#[test]
fn brief_should_cap_and_note_the_remainder_when_over_the_limit() {
let r = repo();
decide(&r, "decision one", &["--authority", "user-ruled"]);
decide(&r, "decision two", &["--authority", "user-ruled"]);
decide(&r, "decision three", &["--authority", "user-ruled"]);
let out = ev()
.args(["brief", "--limit", "2"])
.current_dir(&r)
.output()
.unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
let shown = ["decision one", "decision two", "decision three"]
.iter()
.filter(|d| stdout.contains(**d))
.count();
assert_eq!(shown, 2, "exactly two decisions shown:\n{stdout}");
assert!(stdout.contains("1 more"), "remainder count:\n{stdout}");
assert!(stdout.contains("ev list"), "points at ev list:\n{stdout}");
}
#[test]
fn brief_should_show_all_when_limit_is_zero() {
let r = repo();
decide(&r, "decision one", &["--authority", "user-ruled"]);
decide(&r, "decision two", &["--authority", "user-ruled"]);
decide(&r, "decision three", &["--authority", "user-ruled"]);
let out = ev()
.args(["brief", "--limit", "0"])
.current_dir(&r)
.output()
.unwrap();
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
let shown = ["decision one", "decision two", "decision three"]
.iter()
.filter(|d| stdout.contains(**d))
.count();
assert_eq!(shown, 3, "all three shown:\n{stdout}");
assert!(!stdout.contains("more user-ruled"), "no footer:\n{stdout}");
}
#[test]
fn brief_should_fail_when_there_is_no_store() {
let p = std::env::temp_dir().join(format!("ev-brief-nostore-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&p);
std::fs::create_dir_all(&p).unwrap();
let out = ev().arg("brief").current_dir(&p).output().unwrap();
assert!(!out.status.success());
}