- Drop fields and functions nothing reads: job and proc tips, fetch time, PR url/author (and their GraphQL fields), spine summaries, diff::commit, unread data attributes, unused CSS and tokens. - One home each for state wording (naming main as the repo does), lane lookup, unseen, outdated, main's tip, the stop wait and the token header. - Narrow visibility; rename render::View to Filter; queue ranking moves to the CLI, its only user. - Token test covers every route; shared checkout snapshot in the fixture. - Client: errors outside Run/Send are toasts, history only after a good load, a drag stays in one file, the agent marker is a ring. - design.md, the skill and AGENTS.md describe what is built.
121 lines
3.2 KiB
Rust
121 lines
3.2 KiB
Rust
use branchgraph::github::{Ci, Pr, Review, State, parse_page, repo_of, state};
|
|
|
|
/// Recorded on 2026-10-08 from `gh api graphql` with `github::QUERY` for tokio-rs/axum.
|
|
const RECORDED: &str = include_str!("data/axum-prs.json");
|
|
|
|
#[test]
|
|
fn recorded_response_gives_same_repo_prs_with_their_states() {
|
|
let (prs, next) = parse_page(RECORDED).unwrap();
|
|
assert_eq!(next, None);
|
|
let got: Vec<(u64, &str, bool, bool, Review, Ci)> = prs
|
|
.iter()
|
|
.map(|p| {
|
|
(
|
|
p.number,
|
|
p.head.as_str(),
|
|
p.draft,
|
|
p.conflicting,
|
|
p.review,
|
|
p.ci,
|
|
)
|
|
})
|
|
.collect();
|
|
assert_eq!(
|
|
got,
|
|
[
|
|
(
|
|
3484,
|
|
"dm/hyper-serve",
|
|
false,
|
|
true,
|
|
Review::Required,
|
|
Ci::Failing
|
|
),
|
|
(
|
|
3510,
|
|
"dm/ci-docs",
|
|
false,
|
|
true,
|
|
Review::Required,
|
|
Ci::Passing
|
|
),
|
|
(
|
|
3808,
|
|
"dependabot/github_actions/actions/checkout-7",
|
|
false,
|
|
true,
|
|
Review::Required,
|
|
Ci::Passing
|
|
),
|
|
(
|
|
3863,
|
|
"release-plz-2026-08-11T07-17-29Z",
|
|
false,
|
|
false,
|
|
Review::Required,
|
|
Ci::None
|
|
),
|
|
]
|
|
);
|
|
let states: Vec<State> = prs.iter().map(|p| state(&[], Some(p))).collect();
|
|
assert_eq!(
|
|
states,
|
|
[
|
|
State::Conflicts,
|
|
State::Conflicts,
|
|
State::Conflicts,
|
|
State::Ready
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn api_errors_surface() {
|
|
let err = parse_page(r#"{"data":null,"errors":[{"message":"Bad credentials"}]}"#).unwrap_err();
|
|
assert!(err.to_string().contains("Bad credentials"));
|
|
}
|
|
|
|
#[test]
|
|
fn lane_state_rules() {
|
|
let pr = |draft, conflicting, ci| Pr {
|
|
number: 1,
|
|
title: String::new(),
|
|
head: "x".into(),
|
|
draft,
|
|
conflicting,
|
|
review: Review::None,
|
|
ci,
|
|
};
|
|
let lock = ["Cargo.lock".to_owned()];
|
|
let code = ["src/a.rs".to_owned()];
|
|
assert_eq!(state(&code, None), State::Conflicts);
|
|
assert_eq!(
|
|
state(&lock, None),
|
|
State::Neutral,
|
|
"a lock-only conflict is not red"
|
|
);
|
|
assert_eq!(
|
|
state(&lock, Some(&pr(false, false, Ci::Passing))),
|
|
State::Ready
|
|
);
|
|
assert_eq!(
|
|
state(&[], Some(&pr(false, false, Ci::Failing))),
|
|
State::CiFailing
|
|
);
|
|
assert_eq!(
|
|
state(&[], Some(&pr(true, false, Ci::Passing))),
|
|
State::Neutral,
|
|
"drafts are neutral"
|
|
);
|
|
assert_eq!(state(&[], None), State::Neutral);
|
|
}
|
|
|
|
#[test]
|
|
fn github_remotes() {
|
|
let want = Some(("tokio-rs".to_owned(), "axum".to_owned()));
|
|
assert_eq!(repo_of("git@github.com:tokio-rs/axum.git"), want);
|
|
assert_eq!(repo_of("https://github.com/tokio-rs/axum"), want);
|
|
assert_eq!(repo_of("ssh://git@github.com/tokio-rs/axum.git"), want);
|
|
assert_eq!(repo_of("https://gitlab.com/a/b"), None);
|
|
}
|