feat: separate draft pull requests into their own tab
This commit is contained in:
+80
-1
@@ -445,7 +445,12 @@ fn pull_request_categories_keep_query_and_select_loaded_rows_before_completion()
|
||||
let mut state = DiffState::pull_requests("origin".into());
|
||||
assert_eq!(
|
||||
state.categories(),
|
||||
[Category::Open, Category::Closed, Category::All]
|
||||
[
|
||||
Category::Open,
|
||||
Category::Closed,
|
||||
Category::Drafts,
|
||||
Category::All
|
||||
]
|
||||
);
|
||||
state.take_request();
|
||||
state.handle(Input::Char('\t'));
|
||||
@@ -464,6 +469,7 @@ fn pull_request_categories_keep_query_and_select_loaded_rows_before_completion()
|
||||
assert!(state.pull_request_partial());
|
||||
assert_eq!(state.entries().next().unwrap().label, "#2 Fix Ünicode");
|
||||
state.handle(Input::Char('\t'));
|
||||
state.handle(Input::Char('\t'));
|
||||
state.apply_result(
|
||||
1,
|
||||
Ok(pull_page(
|
||||
@@ -498,6 +504,79 @@ fn pull_request_categories_keep_query_and_select_loaded_rows_before_completion()
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pull_request_drafts_filter_independently_and_share_open_loading_and_retry() {
|
||||
let mut state = DiffState::pull_requests("origin".into());
|
||||
state.take_request();
|
||||
let mut page = pull_page(
|
||||
false,
|
||||
&[
|
||||
(1, "Ready", "2024-01-01T00:00:00Z"),
|
||||
(2, "Draft Ünicode", "2024-01-02T00:00:00Z"),
|
||||
],
|
||||
true,
|
||||
);
|
||||
if let Outcome::PullRequestPage {
|
||||
result: Ok(page), ..
|
||||
} = &mut page
|
||||
{
|
||||
page.entries[1].0.category = Category::Drafts;
|
||||
}
|
||||
state.apply_result(1, Ok(page));
|
||||
state.apply_result(
|
||||
1,
|
||||
Ok(pull_page(
|
||||
true,
|
||||
&[(3, "Closed", "2024-01-03T00:00:00Z")],
|
||||
false,
|
||||
)),
|
||||
);
|
||||
let labels = |state: &DiffState| {
|
||||
state
|
||||
.entries()
|
||||
.map(|entry| entry.label.clone())
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
assert_eq!(labels(&state), ["#1 Ready"]);
|
||||
state.handle(Input::BackTab);
|
||||
assert_eq!(
|
||||
labels(&state),
|
||||
["#3 Closed", "#2 Draft Ünicode", "#1 Ready"]
|
||||
);
|
||||
state.handle(Input::BackTab);
|
||||
assert_eq!(labels(&state), ["#2 Draft Ünicode"]);
|
||||
assert!(state.pull_request_partial());
|
||||
state.apply_result(
|
||||
1,
|
||||
Ok(Outcome::PullRequestPage {
|
||||
closed: false,
|
||||
result: Err("open stream unavailable".into()),
|
||||
}),
|
||||
);
|
||||
assert!(
|
||||
state
|
||||
.pull_request_notice()
|
||||
.unwrap()
|
||||
.contains("open stream unavailable")
|
||||
);
|
||||
state.handle(Input::Ctrl('r'));
|
||||
assert_eq!(state.pull_request_retries, [1, 0]);
|
||||
state.apply_result(1, Ok(pull_page(false, &[], false)));
|
||||
assert!(!state.pull_request_partial());
|
||||
for ch in "Ünicode Alice".chars() {
|
||||
state.handle(Input::Char(ch));
|
||||
}
|
||||
assert_eq!(labels(&state), ["#2 Draft Ünicode"]);
|
||||
state.handle(Input::Enter);
|
||||
assert!(matches!(
|
||||
state.take_request(),
|
||||
Some(Operation::ResolvePullRequest(Revision {
|
||||
target: RevisionTarget::PullRequest { number: 2, .. },
|
||||
..
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pull_request_all_streams_sort_deduplicate_and_preserve_selection_identity() {
|
||||
let mut state = DiffState::pull_requests("origin".into());
|
||||
|
||||
@@ -7,6 +7,42 @@ fn parse(url: &str, provider: Option<&str>) -> Result<Forge, String> {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draft_summaries_keep_open_closed_and_merged_states_distinct() {
|
||||
for provider in [Provider::Github, Provider::Gitlab, Provider::Gitea] {
|
||||
for (closed, merged, expected) in [
|
||||
(false, false, "draft"),
|
||||
(true, false, "closed"),
|
||||
(true, true, "merged"),
|
||||
] {
|
||||
let mut value = json!({
|
||||
"number": 7, "iid": 7, "title": "Unfinished work", "draft": true,
|
||||
"state": if merged && provider == Provider::Gitlab { "merged" }
|
||||
else if closed { "closed" }
|
||||
else if provider == Provider::Gitlab { "opened" } else { "open" },
|
||||
"merged": merged,
|
||||
"merged_at": if merged { Some("2024-01-02T00:00:00Z") } else { None },
|
||||
"user": null, "author": null, "created_at": "2024-01-01T00:00:00Z"
|
||||
});
|
||||
let entry = summary(provider, &value, Some((1, 2))).unwrap();
|
||||
assert!(entry.draft);
|
||||
assert_eq!(entry.closed, closed);
|
||||
assert_eq!(
|
||||
entry.description,
|
||||
format!("deleted user · {expected} · +1 -2")
|
||||
);
|
||||
if !closed {
|
||||
value["draft"] = json!(false);
|
||||
assert!(!summary(provider, &value, None).unwrap().draft);
|
||||
value.as_object_mut().unwrap().remove("draft");
|
||||
assert!(!summary(provider, &value, None).unwrap().draft);
|
||||
value["draft"] = json!("true");
|
||||
assert!(summary(provider, &value, None).is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pull_request_sizes_include_zero_and_preserve_unknown_statistics() {
|
||||
for (url, provider) in [
|
||||
|
||||
+10
-1
@@ -3508,7 +3508,11 @@ fn pull_request_picker_renders_all_rows_without_a_pinned_offset() {
|
||||
},
|
||||
label: format!("#{index:02} Pull request"),
|
||||
description: "open · main ← topic".into(),
|
||||
category: Category::Open,
|
||||
category: if index == 1 {
|
||||
Category::Drafts
|
||||
} else {
|
||||
Category::Open
|
||||
},
|
||||
},
|
||||
format!("2026-01-{:02}T00:00:00Z", 20 - index),
|
||||
)
|
||||
@@ -3548,6 +3552,11 @@ fn pull_request_picker_renders_all_rows_without_a_pinned_offset() {
|
||||
);
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
assert!(screen_text(&terminal).contains("No matching pull requests"));
|
||||
diff.handle(Input::Char('\t'));
|
||||
render_diff(&mut terminal, &diff, &mut panels);
|
||||
let text = screen_text(&terminal);
|
||||
assert!(text.contains("> #01 Pull request"));
|
||||
assert!(!text.contains("#00 Pull request") && !text.contains("#19 Pull request"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user