use serde_json::Value;
use tempfile::TempDir;
use super::heddle;
fn setup() -> TempDir {
let temp = TempDir::new().unwrap();
heddle(&["init"], Some(temp.path())).unwrap();
std::fs::write(temp.path().join("main.rs"), "fn main() {}\n").unwrap();
std::fs::write(temp.path().join("other.rs"), "fn f() {}\n").unwrap();
heddle(&["capture", "-m", "seed"], Some(temp.path())).unwrap();
temp
}
fn json(out: &str) -> Value {
serde_json::from_str(out.trim()).expect("valid JSON output")
}
#[test]
fn discussion_survives_context_set_advance() {
let temp = setup();
let dir = Some(temp.path());
let opened = json(
&heddle(
&[
"--output", "json", "discuss", "open", "main.rs", "main", "review q",
],
dir,
)
.unwrap(),
);
let id = opened["id"].as_str().unwrap().to_string();
heddle(
&[
"context",
"set",
"--path",
"other.rs",
"--scope",
"symbol:f",
"--kind",
"rationale",
"-m",
"note",
],
dir,
)
.unwrap();
let shown = json(
&heddle(&["--output", "json", "discuss", "show", &id], dir)
.expect("discuss show must resolve the discussion on the advanced HEAD"),
);
assert_eq!(shown["id"].as_str(), Some(id.as_str()));
let listed = json(&heddle(&["--output", "json", "discuss", "list"], dir).unwrap());
let ids: Vec<&str> = listed["discussions"]
.as_array()
.unwrap()
.iter()
.filter_map(|d| d["id"].as_str())
.collect();
assert!(
ids.contains(&id.as_str()),
"HEAD-default discuss list must include the carried-forward discussion, got {ids:?}"
);
}
#[test]
fn advanced_head_state_carries_the_discussion() {
let temp = setup();
let dir = Some(temp.path());
let opened = json(
&heddle(
&[
"--output", "json", "discuss", "open", "main.rs", "main", "q",
],
dir,
)
.unwrap(),
);
let id = opened["id"].as_str().unwrap().to_string();
heddle(
&[
"context",
"set",
"--path",
"other.rs",
"--scope",
"symbol:f",
"--kind",
"rationale",
"-m",
"note",
],
dir,
)
.unwrap();
let head_listed = json(&heddle(&["--output", "json", "discuss", "list"], dir).unwrap());
let head_state = head_listed["discussions"][0]["opened_against_state"]
.as_str()
.expect("discussion carries its (traveled) anchor state")
.to_string();
let by_state = json(
&heddle(
&[
"--output",
"json",
"discuss",
"list",
"--state",
&head_state,
],
dir,
)
.unwrap(),
);
let ids: Vec<&str> = by_state["discussions"]
.as_array()
.unwrap()
.iter()
.filter_map(|d| d["id"].as_str())
.collect();
assert!(
ids.contains(&id.as_str()),
"per-state list on the advanced HEAD must include the discussion, got {ids:?}"
);
}
#[test]
fn discuss_show_state_flag_resolves_on_prior_state() {
let temp = setup();
let dir = Some(temp.path());
let opened = json(
&heddle(
&[
"--output", "json", "discuss", "open", "main.rs", "main", "q",
],
dir,
)
.unwrap(),
);
let id = opened["id"].as_str().unwrap().to_string();
let prior_state = opened["opened_against_state"].as_str().unwrap().to_string();
heddle(
&[
"context",
"set",
"--path",
"other.rs",
"--scope",
"symbol:f",
"--kind",
"rationale",
"-m",
"note",
],
dir,
)
.unwrap();
let shown = json(
&heddle(
&[
"--output",
"json",
"discuss",
"show",
&id,
"--state",
&prior_state,
],
dir,
)
.expect("discuss show --state must resolve a discussion on the named prior state"),
);
assert_eq!(shown["id"].as_str(), Some(id.as_str()));
}
#[test]
fn discuss_append_works_after_context_set_advance() {
let temp = setup();
let dir = Some(temp.path());
let opened = json(
&heddle(
&[
"--output", "json", "discuss", "open", "main.rs", "main", "first",
],
dir,
)
.unwrap(),
);
let id = opened["id"].as_str().unwrap().to_string();
heddle(
&[
"context",
"set",
"--path",
"other.rs",
"--scope",
"symbol:f",
"--kind",
"rationale",
"-m",
"note",
],
dir,
)
.unwrap();
let appended = json(
&heddle(
&["--output", "json", "discuss", "append", &id, "second"],
dir,
)
.expect("discuss append must find the discussion on HEAD after the advance"),
);
let turns = appended["turns"].as_array().unwrap();
assert_eq!(
turns.len(),
2,
"append should add a second turn: {appended}"
);
assert_eq!(turns[1]["body"].as_str(), Some("second"));
}