#![allow(
clippy::unwrap_used,
clippy::expect_used,
reason = "tests fail by panicking"
)]
use runnerd_core::api::JobPage;
use runnerd_fixtures::{Facts, NOW, TIMED_OUT, daemon, facts};
use super::{Paint, Tone, caches, job, jobs, outcome_tone, records, savings, status};
const PLAIN: Paint = Paint { colour: false };
const COLOUR: Paint = Paint { colour: true };
fn line_of<'text>(text: &'text str, first: &[&str]) -> &'text str {
text.lines()
.find(|line| {
line.split_whitespace()
.take(first.len())
.eq(first.iter().copied())
})
.unwrap_or_else(|| panic!("no line starts with {first:?}:\n{text}"))
}
fn coloured(text: &str, word: &str, tone: Tone) -> bool {
text.contains(&COLOUR.paint(tone, word))
}
fn fixtures() -> (runnerd_fixtures::Daemon, Facts) {
let daemon = daemon();
let facts = facts(&daemon);
(daemon, facts)
}
#[test]
fn status_states_the_budget_each_slot_and_why_each_job_waits_as_core_does() {
let (daemon, facts) = fixtures();
let text = status(&daemon.status, NOW, PLAIN);
let first = text.lines().next().unwrap();
assert!(first.contains(&facts.budget), "{first}");
assert!(first.contains(&facts.cpu), "{first}");
assert!(first.contains(&facts.host), "{first}");
let painted = status(&daemon.status, NOW, COLOUR);
for slot in &facts.slots {
let row = line_of(&text, &[&slot.profile, &slot.slot.to_string()]);
assert!(
row.split_whitespace().any(|word| word == slot.word),
"{}: {row}",
slot.word
);
assert!(
coloured(&painted, slot.word, slot.tone.into()),
"{} {} is {} in {:?}: {painted}",
slot.profile,
slot.slot,
slot.word,
slot.tone
);
}
for wait in &facts.waits {
let row = line_of(&text, &[&wait.job.to_string()]);
assert!(row.ends_with(&wait.reason), "{}: {row}", wait.reason);
}
}
#[test]
fn jobs_state_each_outcome_wait_and_run_time_as_core_does() {
let (daemon, facts) = fixtures();
let page = JobPage {
jobs: daemon.finished(),
next: None,
};
let text = jobs(&page, NOW, PLAIN);
let painted = jobs(&page, NOW, COLOUR);
for row in &facts.rows {
let line = line_of(&text, &[&row.job.to_string()]);
assert!(line.contains(&row.title), "{}: {line}", row.title);
assert!(line.contains(&row.label), "{}: {line}", row.label);
for figure in [&row.waited, &row.ran].into_iter().flatten() {
assert!(line.contains(figure.as_str()), "{figure}: {line}");
}
assert!(
coloured(&painted, &row.label, outcome_tone(row.kind)),
"{} is {:?}: {painted}",
row.label,
row.kind
);
}
}
#[test]
fn a_job_states_its_outcome_steps_caps_and_build_cache_as_core_does() {
let (daemon, facts) = fixtures();
let shown = daemon.job(TIMED_OUT).unwrap();
let text = job(shown, NOW, PLAIN);
let head = text.lines().next().unwrap();
assert!(head.contains(&facts.job.row.title), "{head}");
assert!(
coloured(
&job(shown, NOW, COLOUR),
&facts.job.row.label,
outcome_tone(facts.job.row.kind)
),
"{head}"
);
assert!(text.contains(&facts.job.limits), "{text}");
assert!(text.contains(&facts.job.cpu_time), "{text}");
for part in &facts.job.build_cache {
assert!(text.contains(part.as_str()), "{part}: {text}");
}
for step in &facts.job.steps {
let row = text
.lines()
.find(|line| line.contains(&step.name))
.unwrap_or_else(|| panic!("no row for {}: {text}", step.name));
let after = row.split(&step.name).nth(1).unwrap().trim();
match &step.took {
Some(took) => assert!(after.starts_with(took.as_str()), "{took}: {row}"),
None => assert!(after.is_empty(), "{} shows no duration: {row}", step.name),
}
}
}
#[test]
fn records_and_caches_state_their_limits_as_core_does() {
let (daemon, facts) = fixtures();
let text = records(&daemon.records, NOW, PLAIN);
let summary = text.lines().next().unwrap();
assert!(summary.contains(&facts.records_usage), "{summary}");
assert!(summary.contains(&facts.records_pressure), "{summary}");
assert!(
records(&daemon.records, NOW, COLOUR)
.starts_with(&COLOUR.paint(facts.records_tone.into(), summary)),
"the summary is in {:?}",
facts.records_tone
);
let text = caches(&daemon.caches, NOW, PLAIN);
assert!(text.contains(&facts.build_cache_week), "{text}");
}
#[test]
fn insights_open_with_what_the_job_minutes_would_have_cost_as_core_words_it() {
let (daemon, facts) = fixtures();
let text = savings(&daemon.savings);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(lines[0], facts.savings);
assert!(lines.contains(&facts.savings_30_days.as_str()), "{text}");
}