use super::*;
use crate::route::runs;
use crate::ui::form::Row;
use crate::ui::page::Link;
use crate::workflows::{Dispatch, SaveArtifact};
fn select_link(s: &mut State, link: &Link) {
let height = s.page_height();
let Screen::Page(p) = s.screen_mut() else {
panic!("not on a page")
};
let page = p.page();
let i = (0..page.items.len())
.find(|&i| page.target(page.items[i].link) == Some(link))
.unwrap_or_else(|| panic!("no {link:?} row"));
p.select(i, height);
}
const WORKFLOW: &str = "name: CI\non:\n workflow_dispatch:\n inputs:\n outcome:\n type: choice\n options: [fail, pass]\n default: fail\n seconds:\n type: string\n default: \"60\"\n";
#[test]
fn a_workflow_runs_by_hand_with_its_inputs_and_is_followed() {
let mut s = with_workflow();
act(&mut s, Action::RunWorkflow);
let dispatch = Route::Runs(runs::Dispatch {
repo: ghtui(),
file: "ci.yml".into(),
});
assert_eq!(route(&s), dispatch);
let blob = crate::fixtures::file(".github/workflows/ci.yml", WORKFLOW);
let key = DataKey::Blob(ghtui(), "HEAD".into(), ".github/workflows/ci.yml".into());
fetched(&mut s, key, Data::Blob(Box::new(blob)));
select_link(&mut s, &Link::Form(Row::Input("outcome".into())));
press(&mut s, "<Enter>");
press(&mut s, "pass<Enter>");
let cmds = act(&mut s, Action::RunWorkflow);
let dispatch = Dispatch {
repo: ghtui(),
file: "ci.yml".into(),
git_ref: "main".into(),
inputs: vec![
("outcome".into(), "pass".into()),
("seconds".into(), "60".into()),
],
};
assert_eq!(crate::fixtures::sent::<Dispatch>(&cmds), dispatch);
crate::fixtures::done(&mut s, dispatch, Ok(Some(55)));
let run = Route::Runs(runs::WorkflowRun {
repo: ghtui(),
run: 55,
attempt: None,
});
assert_eq!(route(&s), run);
says(&s, "Started ci.yml: following its run");
}
#[test]
fn a_workflow_that_cant_run_by_hand_says_so() {
let mut s = with_workflow();
act(&mut s, Action::RunWorkflow);
let blob = crate::fixtures::file(".github/workflows/ci.yml", "on: push\n");
let key = DataKey::Blob(ghtui(), "HEAD".into(), ".github/workflows/ci.yml".into());
fetched(&mut s, key, Data::Blob(Box::new(blob)));
assert!(fetches(act(&mut s, Action::RunWorkflow)).is_empty());
says(&s, "can't be run by hand");
}
#[test]
fn an_artifact_is_saved_where_you_say() {
let mut s = with_run();
let artifact = Link::Artifact {
id: 31,
name: "coverage-report".into(),
};
select_link(&mut s, &artifact);
press(&mut s, "<Enter>");
let cmds = press(&mut s, "<Enter>");
let saved = SaveArtifact {
repo: ghtui(),
id: 31,
name: "coverage-report".into(),
path: std::path::Path::new(".").join("coverage-report.zip"),
replace: false,
};
assert_eq!(crate::fixtures::sent::<SaveArtifact>(&cmds), saved);
select_link(&mut s, &artifact);
press(&mut s, "<Enter>");
press(&mut s, "Cargo.toml");
let Some(Overlay::Picker(p)) = &s.overlay else {
panic!("no picker")
};
let rows = s.picker_rows(p);
assert_eq!(rows[0].0.label, "Replace Cargo.toml");
let cmds = press(&mut s, "<Enter>");
assert!(crate::fixtures::sent::<SaveArtifact>(&cmds).replace);
}
#[test]
fn check_annotations_show_on_their_lines_in_files_changed() {
use crate::ui::annotations::{AnnotationKey, Place};
let (mut s, pr) = super::diff::diff_state(120);
let mut checks = crate::fixtures::checks();
let mut on_run = crate::fixtures::check_annotation();
on_run.path = None;
let mut on_file = crate::fixtures::check_annotation();
on_file.path = Some("src/point.rs".into());
checks.items.items[0].annotations = vec![on_file, on_run].into();
fetched(
&mut s,
DataKey::PrChecks(pr.clone()),
Data::Checks(Box::new(checks)),
);
let anns = s.diffs[&crate::diff_screen::DiffOf::Pr(pr)]
.doc
.annotations();
let shown: Vec<_> = (anns.iter())
.filter(|a| matches!(a.key, AnnotationKey::Check(_)))
.collect();
assert_eq!(shown.len(), 1);
assert_eq!(shown[0].path, "src/point.rs");
assert!(matches!(shown[0].place, Place::Line { at, .. } if at.line == 3));
assert!(shown[0].comments[0].author.contains("test (ubuntu)"));
}