feat: show line counts in pull request picker

This commit is contained in:
Valdemar Lorenzen
2026-10-21 10:06:48 +02:00
parent 31203889bb
commit cce3b1e469
4 changed files with 234 additions and 22 deletions
+90 -9
View File
@@ -7,6 +7,82 @@ fn parse(url: &str, provider: Option<&str>) -> Result<Forge, String> {
})
}
#[test]
fn pull_request_sizes_include_zero_and_preserve_unknown_statistics() {
for (url, provider) in [
("https://github.com/owner/repo", Provider::Github),
("https://github.enterprise/owner/repo", Provider::Github),
("https://gitlab.com/group/repo", Provider::Gitlab),
("https://codeberg.org/owner/repo", Provider::Gitea),
] {
let forge = parse(
url,
Some(match provider {
Provider::Github => "github",
Provider::Gitlab => "gitlab",
Provider::Gitea => "gitea",
}),
)
.unwrap();
let page = forge
.page_with(false, 1, |url, body| {
if let Some(body) = body {
let query: Value = serde_json::from_str(body).unwrap();
let query = query["query"].as_str().unwrap();
assert!(query.starts_with("query{"));
assert!(!query.contains("mutation"));
if provider == Provider::Github {
assert_eq!(
url,
if forge.host == "github.com" {
"https://api.github.com/graphql"
} else {
"https://github.enterprise/api/graphql"
}
);
assert!(query.contains("p7:pullRequest(number:7)"));
return Ok(json!({"data":{"repository":{
"p7":{"additions":123,"deletions":45},
"p8":{"additions":0,"deletions":0},
"p9":null
}}}));
}
assert_eq!(url, "https://gitlab.com/api/graphql");
assert!(query.contains("p7:mergeRequest(iid:\"7\")"));
return Ok(json!({"data":{"project":{
"p7":{"diffStatsSummary":{"additions":123,"deletions":45}},
"p8":{"diffStatsSummary":{"additions":0,"deletions":0}},
"p9":{"diffStatsSummary":null}
}}}));
}
Ok(Value::Array((7..=9).map(|id| json!({
"merged_at":null, "merged":false,
"number":id, "iid":id, "title":"Sized PR",
"state":if provider == Provider::Gitlab { "opened" } else { "open" },
"user":{"login":"author"}, "author":{"username":"author"},
"created_at":"2024-01-01T00:00:00Z",
"base":{"ref":"main"}, "head":{"ref":"topic"},
"target_branch":"main", "source_branch":"topic",
"additions":match id { 7 => Some(123), 8 => Some(0), _ => None },
"deletions":match id { 7 => Some(45), 8 => Some(0), _ => None }
})).collect()))
})
.unwrap();
let description = |id| {
&page
.entries
.iter()
.find(|entry| entry.number == id)
.unwrap()
.description
};
assert!(description(7).contains("open · +123 -45 · topic → main"));
assert!(description(8).contains("open · +0 -0 · topic → main"));
assert!(description(9).contains("size unavailable"));
assert!(!description(9).contains("+0 -0"));
}
}
#[test]
fn pages_are_bounded_newest_first_summaries_without_historical_metadata() {
for (provider, url, query) in [
@@ -27,9 +103,10 @@ fn pages_are_bounded_newest_first_summaries_without_historical_metadata() {
),
] {
let forge = parse(url, None).unwrap();
let mut calls = 0;
let page = forge.page_with(false, 3, |url| {
calls += 1;
let page = forge.page_with(false, 3, |url, body| {
if body.is_some() {
return Err("statistics unavailable".into());
}
assert_eq!(url, format!("{}?{query}", forge.endpoint));
Ok(json!([
{"number": 1, "iid": 1, "title": "Older", "state": if provider == Provider::Gitlab { "opened" } else { "open" },
@@ -39,22 +116,20 @@ fn pages_are_bounded_newest_first_summaries_without_historical_metadata() {
"created_at": "2024-01-01T00:00:00.001Z", "diff_refs": null, "head": {"sha": "not-a-commit"}}
]))
}).unwrap();
assert_eq!(calls, 1);
assert_eq!(
page.entries.iter().map(|p| p.number).collect::<Vec<_>>(),
[2, 1]
);
assert_eq!(page.entries[0].description, "author · open");
assert!(page.entries[1].description.contains("deleted user"));
assert!(
page.has_more,
"A short, server-capped page is not exhaustion"
);
let empty = forge.page_with(false, 4, |_| Ok(json!([]))).unwrap();
let empty = forge.page_with(false, 4, |_, _| Ok(json!([]))).unwrap();
assert!(empty.entries.is_empty() && !empty.has_more);
assert!(
forge
.page_with(false, 0, |_| panic!("Page zero must not request"))
.page_with(false, 0, |_, _| panic!("Page zero must not request"))
.is_err()
);
}
@@ -67,7 +142,10 @@ fn gitlab_closed_combines_closed_and_merged_pages_without_open_requests() {
for page in 1..=3 {
let mut states = Vec::new();
let result = forge
.page_with(true, page, |url| {
.page_with(true, page, |url, body| {
if body.is_some() {
return Err("statistics unavailable".into());
}
assert!(url.ends_with(&format!("&page={page}")));
let state = if url.contains("?state=closed&") {
"closed"
@@ -100,7 +178,10 @@ fn gitlab_closed_combines_closed_and_merged_pages_without_open_requests() {
}
all.sort_unstable_by(|a, b| b.created_at.cmp(&a.created_at));
assert_eq!(all.iter().map(|p| p.number).collect::<Vec<_>>(), [3, 2, 1]);
let raced = forge.page_with(true, 1, |url| {
let raced = forge.page_with(true, 1, |url, body| {
if body.is_some() {
return Err("statistics unavailable".into());
}
Ok(json!([{"iid": 7, "title": "Raced merge", "state": if url.contains("?state=merged&") { "merged" } else { "closed" },
"author": null, "created_at": "2024-01-01T00:00:00Z"}]))
}).unwrap();