use std::fs;
use serde_json::Value;
use tempfile::TempDir;
use super::heddle;
fn setup_repo() -> TempDir {
let temp = TempDir::new().unwrap();
heddle(&["init"], Some(temp.path())).unwrap();
fs::write(temp.path().join("hello.txt"), "world\n").unwrap();
heddle(&["capture", "-m", "init"], Some(temp.path())).unwrap();
temp
}
fn first_short_id(repo: &std::path::Path) -> String {
let raw = heddle(&["--output", "json", "log", "--limit", "1"], Some(repo)).unwrap();
let value: Value = serde_json::from_str(&raw).unwrap();
value["states"][0]["change_id"]
.as_str()
.expect("log --output json should expose change_id")
.to_string()
}
#[test]
fn review_show_accepts_short_id() {
let temp = setup_repo();
let short = first_short_id(temp.path());
let raw = heddle(
&["review", "show", &short, "--output", "json"],
Some(temp.path()),
)
.expect("review show should accept short IDs");
let value: Value = serde_json::from_str(&raw).expect("review show output should be JSON");
let returned = value["change_id"].as_str().expect("change_id present");
assert!(
returned.starts_with(&short),
"round-trip should resolve to the same state: short={short}, returned={returned}"
);
}
#[test]
fn review_show_respects_global_repo_argument() {
let temp = setup_repo();
let repo_arg = format!("--repo={}", temp.path().display());
let raw = heddle(
&[repo_arg.as_str(), "--output=json", "review", "show", "HEAD"],
None,
)
.expect("review show --repo should inspect the selected repository");
let value: Value = serde_json::from_str(&raw).expect("review show output should be JSON");
assert_eq!(value["headline"], "init");
assert_eq!(
value["files_changed"], 1,
"review show --repo HEAD should summarize the selected repo's captured change: {value}"
);
}
#[test]
fn show_accepts_short_id() {
let temp = setup_repo();
let short = first_short_id(temp.path());
let raw = heddle(&["show", &short, "--output", "json"], Some(temp.path()))
.expect("show should accept short IDs");
let value: Value = serde_json::from_str(&raw).expect("show output should be JSON");
assert_eq!(value["change_id"].as_str(), Some(short.as_str()));
}
#[test]
fn diff_accepts_short_id() {
let temp = setup_repo();
let short = first_short_id(temp.path());
let raw = heddle(&["--output", "json", "diff", &short], Some(temp.path()))
.expect("diff should accept short IDs");
let value: Value = serde_json::from_str(&raw).expect("diff output should be JSON");
assert_eq!(value["from_state"].as_str(), Some(short.as_str()));
}
#[test]
fn compare_accepts_short_id() {
let temp = setup_repo();
fs::write(temp.path().join("two.txt"), "two\n").unwrap();
heddle(&["capture", "-m", "second"], Some(temp.path())).unwrap();
let short_b = first_short_id(temp.path());
let raw = heddle(
&["--output", "json", "log", "--limit", "5"],
Some(temp.path()),
)
.unwrap();
let log_val: Value = serde_json::from_str(&raw).unwrap();
let short_a = log_val["states"][1]["change_id"].as_str().unwrap();
let _output = heddle(
&["--output", "json", "diff", short_a, &short_b],
Some(temp.path()),
)
.expect("diff should accept short IDs on both sides");
}
#[test]
fn discuss_list_accepts_short_id() {
let temp = setup_repo();
let short = first_short_id(temp.path());
let raw = heddle(
&["--output", "json", "discuss", "list", "--state", &short],
Some(temp.path()),
)
.expect("discuss list --state should accept short IDs");
let value: Value = serde_json::from_str(&raw).expect("discuss list output should be JSON");
assert!(value["discussions"].is_array());
}
#[test]
fn cherry_pick_accepts_short_id() {
let temp = setup_repo();
fs::write(temp.path().join("two.txt"), "two\n").unwrap();
heddle(&["capture", "-m", "second"], Some(temp.path())).unwrap();
let raw = heddle(
&["--output", "json", "log", "--limit", "5"],
Some(temp.path()),
)
.unwrap();
let log_val: Value = serde_json::from_str(&raw).unwrap();
let older_short = log_val["states"][1]["change_id"].as_str().unwrap();
heddle(
&["cherry-pick", older_short, "--no-commit"],
Some(temp.path()),
)
.expect("cherry-pick should accept short IDs");
}
#[test]
fn revert_accepts_short_id() {
let temp = setup_repo();
fs::write(temp.path().join("two.txt"), "two\n").unwrap();
heddle(&["capture", "-m", "second"], Some(temp.path())).unwrap();
let short = first_short_id(temp.path());
heddle(&["revert", &short, "--no-commit"], Some(temp.path()))
.expect("revert should accept short IDs");
}
#[test]
fn blame_accepts_short_id() {
let temp = setup_repo();
let short = first_short_id(temp.path());
let _ = heddle(
&["query", "--attribution", "hello.txt", "--state", &short],
Some(temp.path()),
)
.expect("query --attribution --state should accept short IDs");
}
#[test]
fn log_since_accepts_short_id() {
let temp = setup_repo();
fs::write(temp.path().join("two.txt"), "two\n").unwrap();
heddle(&["capture", "-m", "second"], Some(temp.path())).unwrap();
let raw = heddle(
&["--output", "json", "log", "--limit", "5"],
Some(temp.path()),
)
.unwrap();
let log_val: Value = serde_json::from_str(&raw).unwrap();
let oldest_short = log_val["states"][1]["change_id"].as_str().unwrap();
heddle(
&["--output", "json", "log", "--since", oldest_short],
Some(temp.path()),
)
.expect("log --since should accept short IDs");
}
#[test]
fn marker_then_show_accepts_marker_name() {
let temp = setup_repo();
heddle(
&["thread", "marker", "create", "milestone-1"],
Some(temp.path()),
)
.unwrap();
let raw = heddle(
&["show", "milestone-1", "--output", "json"],
Some(temp.path()),
)
.expect("show should accept marker names");
let value: Value = serde_json::from_str(&raw).expect("show output should be JSON");
assert!(value["change_id"].is_string());
}
#[test]
fn unknown_state_id_yields_state_not_found() {
let temp = setup_repo();
let result = heddle(&["show", "hd-zzzzzzzzzzzz"], Some(temp.path()));
let err = result.expect_err("unknown id should fail");
assert!(
err.contains("State not found"),
"expected `State not found` message, got: {err}"
);
}