use crate::api::change::MergeMethod;
use crate::api::model::{AutoMerge, MergeState, QueueState, Queued};
use super::*;
use crate::act::{By, Subject};
use crate::forms::Answer;
fn choices(s: &State) -> Vec<(&str, &Change)> {
match &s.overlay {
Some(Overlay::Ask(c)) => (c.choices.iter())
.filter_map(|(l, a)| match a {
Answer::Change(c) => Some((l.as_str(), c)),
_ => None,
})
.collect(),
_ => panic!("no confirmation"),
}
}
fn merge_row(s: &State) -> (String, Option<String>) {
let row = s.doables().into_iter().find(|d| d.action == Action::Merge);
let row = row.unwrap();
(row.label, row.unavailable)
}
fn checks_running(d: &mut PrDetail) {
d.checks = Some(ChecksState::Pending);
d.merge_state = MergeState::Blocked;
}
fn alice_squashes() -> Option<AutoMerge> {
Some(AutoMerge {
by: "alice".into(),
method: MergeMethod::Squash,
})
}
#[test]
fn auto_merge_says_who_enabled_it() {
let mut s = pr_with(|d| {
checks_running(d);
d.auto_merge = alice_squashes();
});
press(&mut s, "<End>");
let screen = screen_text(&s);
assert!(screen.contains("Auto-merge enabled by alice"), "{screen}");
}
#[test]
fn a_queued_pull_request_says_its_place() {
let mut s = pr_with(|d| {
d.checks = Some(ChecksState::Passing);
d.merge_queue = true;
d.queued = Some(Queued {
position: 2,
state: QueueState::AwaitingChecks,
});
});
press(&mut s, "<End>");
let screen = screen_text(&s);
assert!(
screen.contains("#2 in the merge queue for main"),
"{screen}"
);
}
#[test]
fn merging_while_checks_run_offers_merge_when_ready() {
let s = pr_with(checks_running);
let (_, why) = merge_row(&s);
assert_eq!(
why.as_deref(),
Some("GitHub says it's blocked: a required review or check is missing")
);
let mut s = pr_with(|d| {
checks_running(d);
d.may.enable_auto_merge = true;
});
press(&mut s, "M");
let labels: Vec<&str> = choices(&s).into_iter().map(|(l, _)| l).collect();
assert_eq!(
labels,
[
"Squash and merge when ready",
"Create a merge commit when ready"
]
);
let enable = Change::EnableAutoMerge {
pr: NodeId::new("PR_12"),
method: MergeMethod::Squash,
head: pr_detail().head_oid,
};
let sent = press(&mut s, "<Enter>");
assert_eq!(
sent,
vec![fixtures::change(enable, By::Confirm(Subject::Pr(pr())))]
);
answer(&mut s, &sent, Ok(()));
says(&s, "Auto-merge enabled");
pr_shows(&mut s, |d| {
checks_running(d);
d.may.enable_auto_merge = true;
});
assert!(s.following.is_some());
pr_shows(&mut s, |d| {
checks_running(d);
d.auto_merge = alice_squashes();
d.may.disable_auto_merge = true;
});
assert!(s.following.is_none());
assert_eq!(merge_row(&s), ("Disable auto-merge".to_owned(), None));
press(&mut s, "M");
let disable = Change::DisableAutoMerge {
pr: NodeId::new("PR_12"),
};
assert_eq!(choices(&s), [("Disable auto-merge", &disable)]);
let sent = press(&mut s, "<Enter>");
answer(&mut s, &sent, Ok(()));
pr_shows(&mut s, checks_running);
assert!(s.following.is_none());
let mut s = pr_with(|d| {
d.checks = Some(ChecksState::Pending);
d.may.enable_auto_merge = true;
});
press(&mut s, "M");
let labels: Vec<&str> = choices(&s).into_iter().map(|(l, _)| l).collect();
assert_eq!(labels.len(), 4);
assert_eq!(labels[0], "Squash and merge when ready");
assert_eq!(labels[2], "Squash and merge");
}
#[test]
fn a_merge_queue_takes_it_in_and_lets_it_go() {
let queue = |d: &mut PrDetail| d.merge_queue = true;
let mut s = pr_with(queue);
assert_eq!(merge_row(&s), ("Add to the merge queue".to_owned(), None));
press(&mut s, "M");
let enqueue = Change::Enqueue {
pr: NodeId::new("PR_12"),
head: pr_detail().head_oid,
};
assert_eq!(choices(&s), [("Add to the merge queue", &enqueue)]);
let sent = press(&mut s, "<Enter>");
answer(&mut s, &sent, Ok(()));
says(&s, "Added to the merge queue");
assert!(s.following.is_some());
let queued = |d: &mut PrDetail| {
d.merge_queue = true;
d.queued = Some(Queued {
position: 1,
state: QueueState::Queued,
});
};
pr_shows(&mut s, queued);
assert!(s.following.is_none());
assert_eq!(
merge_row(&s),
("Remove from the merge queue".to_owned(), None)
);
press(&mut s, "M");
let dequeue = Change::Dequeue {
pr: NodeId::new("PR_12"),
};
assert_eq!(choices(&s), [("Remove from the queue", &dequeue)]);
let sent = press(&mut s, "<Enter>");
answer(&mut s, &sent, Ok(()));
pr_shows(&mut s, queued);
assert!(s.following.is_some());
pr_shows(&mut s, queue);
assert!(s.following.is_none());
let s = pr_with(|d| {
queued(d);
d.may.merge = false;
});
let (_, why) = merge_row(&s);
assert_eq!(
why.as_deref(),
Some("Removing it from the merge queue takes write access to gold-silver-copper/ghtui")
);
}