use super::*;
use crate::commands::pr::{EXIT_OK, EXIT_PARTIAL};
const PHASE_ISSUE_JSON: &str = r#"{"number":9572,"title":"[EPIC_12 PHASE_2] wire the thing",
"milestone":{"title":"mpm 1.6"},"projectItems":[{"title":"Harness"}],
"labels":[],"comments":[],"state":"OPEN"}"#;
fn issue_json_titled(title: &str) -> String {
PHASE_ISSUE_JSON.replace("[EPIC_12 PHASE_2] wire the thing", title)
}
fn edited_title(gh: &FakeGh) -> Option<String> {
gh.calls()
.into_iter()
.filter(|c| c.join(" ").starts_with("pr edit"))
.find_map(|c| {
let at = c.iter().position(|a| a == "--title")?;
c.get(at + 1).cloned()
})
}
#[test]
fn pr_9571_open_tags_a_phase_pr_title() {
let (_d, path) = scratch_body(&body_linking("Refs #9572"));
let mut args = open_args(&path.to_string_lossy());
args.title = "feat(trusty-mpm): add X".to_string();
let gh = FakeGh::new()
.on("pr create", "https://github.com/o/r/pull/4242\n")
.on("issue view 9572", PHASE_ISSUE_JSON)
.on("pr edit 4242", "");
let pre = FakePreflight::ok().with_diff(&["crates/trusty-mpm/src/lib.rs"]);
assert_eq!(open::run(&gh, &args, &pre).expect("the PR opens"), EXIT_OK);
assert_eq!(
edited_title(&gh).as_deref(),
Some("feat(trusty-mpm): [EPIC_12 PHASE_2] add X")
);
let edits = gh
.calls()
.iter()
.filter(|c| c.join(" ").starts_with("pr edit"))
.count();
assert_eq!(edits, 1, "the tag rides the one metadata edit");
}
#[test]
fn pr_9571_title_left_unchanged() {
let long = format!("feat(x): {}", "a".repeat(240));
let cases: [(&str, Option<&str>, &str); 6] = [
("no link line", None, "feat(x): add X"),
(
"not a phase issue",
Some("fix: something"),
"feat(x): add X",
),
("a tracker", Some("[EPIC 12] the outcome"), "feat(x): add X"),
(
"already tagged",
Some("[EPIC_12 PHASE_2] wire"),
"feat(x): [EPIC_12 PHASE_2] add X",
),
("not conventional", Some("[EPIC_12 PHASE_2] wire"), "Add X"),
("too long", Some("[EPIC_12 PHASE_2] wire"), long.as_str()),
];
for (case, issue_title, pr_title) in cases {
let body = match issue_title {
Some(_) => body_linking("Refs #9572"),
None => full_body(),
};
let (_d, path) = scratch_body(&body);
let mut args = open_args(&path.to_string_lossy());
args.title = pr_title.to_string();
let json = issue_json_titled(issue_title.unwrap_or(""));
let gh = FakeGh::new()
.on("pr create", "https://github.com/o/r/pull/4242\n")
.on("issue view 9572", &json)
.on("pr edit 4242", "");
let pre = FakePreflight::ok().with_diff(&["crates/trusty-mpm/src/lib.rs"]);
assert_eq!(
open::run(&gh, &args, &pre).expect("the PR opens"),
EXIT_OK,
"{case}"
);
assert_eq!(edited_title(&gh), None, "{case}");
}
}
#[test]
fn pr_9571_an_unreadable_issue_reports_the_title_missing() {
let (_d, path) = scratch_body(&body_linking("Refs #9572"));
let mut args = open_args(&path.to_string_lossy());
args.title = "feat(trusty-mpm): add X".to_string();
let gh = FakeGh::new()
.on("pr create", "https://github.com/o/r/pull/4242\n")
.on_fail("issue view 9572", "HTTP 502 (api.github.com/graphql)")
.on("pr edit 4242", "");
let pre = FakePreflight::ok().with_diff(&["crates/trusty-mpm/src/lib.rs"]);
assert_eq!(
open::run(&gh, &args, &pre).expect("the PR exists"),
EXIT_PARTIAL,
"an unknown phase tag is a partial apply, never a silent success"
);
let missing =
metadata_apply::apply(&gh, &args, &pre, "4242", &body_linking("Refs #9572")).missing();
assert!(
missing.iter().any(|m| m.starts_with("title")),
"`title` is named missing: {missing:?}"
);
}
#[test]
fn pr_9571_a_failed_title_edit_reports_the_title_missing() {
let (_d, path) = scratch_body(&body_linking("Refs #9572"));
let mut args = open_args(&path.to_string_lossy());
args.title = "feat(trusty-mpm): add X".to_string();
let gh = FakeGh::new()
.on("issue view 9572", PHASE_ISSUE_JSON)
.on_fail("pr edit 4242", "GraphQL: something went wrong");
let pre = FakePreflight::ok().with_diff(&["crates/trusty-mpm/src/lib.rs"]);
let missing =
metadata_apply::apply(&gh, &args, &pre, "4242", &body_linking("Refs #9572")).missing();
assert!(
missing
.iter()
.any(|m| m.starts_with("title \"feat(trusty-mpm): [EPIC_12 PHASE_2] add X\"")),
"{missing:?}"
);
}
#[test]
fn pr_9571_dry_run_with_a_phase_link_calls_no_gh() {
let (_d, path) = scratch_body(&body_linking("Refs #9572"));
let mut args = open_args(&path.to_string_lossy());
args.title = "feat(trusty-mpm): add X".to_string();
args.dry_run = true;
let gh = FakeGh::new();
assert_eq!(
open::run(&gh, &args, &FakePreflight::ok()).expect("dry run"),
EXIT_OK
);
assert!(gh.calls().is_empty(), "a dry run must not spawn gh");
}