use super::*;
#[test]
fn a_mixed_project_is_not_painted_as_one_state() {
let out = paint_status_cell("running(1), exited(1)");
let (running, exited) = out.split_once(", ").expect("both segments survive");
assert_ne!(
running.replace("running(1)", ""),
exited.replace("exited(1)", ""),
"each state must carry its own colour: {out:?}"
);
}
#[test]
fn a_clean_exit_is_not_red() {
let red = Style::new().fg_color(Some(AnsiColor::Red.into()));
let clean = paint_status_cell("Exited (0)");
assert!(
!clean.contains(&red.render().to_string()),
"a zero exit must not be red: {clean:?}"
);
let failed = paint_status_cell("Exited (7)");
assert!(
failed.contains(&red.render().to_string()),
"a non-zero exit must stay red: {failed:?}"
);
}
#[test]
fn only_a_bare_zero_counts_as_clean() {
assert!(is_clean_exit("exited (0)"));
assert!(is_clean_exit("exited(0)"));
assert!(!is_clean_exit("exited (10)"));
assert!(!is_clean_exit("exited (07)"));
}
#[test]
fn trailing_padding_survives_colourising() {
let out = paint_status_cell("running ");
assert!(out.ends_with(" "), "{out:?}");
}
#[test]
fn systemd_states_are_coloured() {
for word in ["active", "inactive", "failed", "not-found", "enabled"] {
assert!(status_style(word).is_some(), "{word} should carry a colour");
}
}
#[test]
fn service_colour_is_stable_per_name() {
assert_eq!(palette_index("web"), palette_index("web"));
let distinct: std::collections::HashSet<usize> =
["web", "db", "cache", "worker", "proxy", "queue"]
.iter()
.map(|n| palette_index(n))
.collect();
assert!(distinct.len() > 1, "palette should spread service names");
assert!(palette_index("web") < SERVICE_PALETTE.len());
}
#[test]
fn paint_gates_on_enabled() {
let plain = paint(bold(), "hi", false);
assert_eq!(plain, "hi");
let coloured = paint(bold(), "hi", true);
assert!(coloured.contains("hi"));
assert!(coloured.len() > "hi".len(), "enabled paint adds ANSI codes");
assert!(coloured.starts_with('\u{1b}'), "starts with an ESC");
}
#[test]
fn colour_choice_resolution() {
temp_env::with_var_unset("NO_COLOR", || {
assert!(!colored_with(ColorChoice::Never, true));
assert!(colored_with(ColorChoice::Always, false));
assert!(colored_with(ColorChoice::Auto, true));
assert!(!colored_with(ColorChoice::Auto, false));
});
temp_env::with_var("NO_COLOR", Some("1"), || {
assert!(!colored_with(ColorChoice::Auto, true));
assert!(colored_with(ColorChoice::Always, true));
});
}
#[test]
fn status_style_is_semantic() {
assert_ne!(status_style("running"), status_style("exited (1)"));
assert_ne!(status_style("unhealthy"), status_style("healthy"));
assert!(status_style("Up 2 minutes").is_some());
assert!(status_style("paused").is_some());
assert!(status_style("created").is_some());
assert!(status_style("weird-state").is_none());
}
#[test]
fn progress_toggle_is_observable() {
let prev = progress_enabled();
set_progress(false);
assert!(!progress_enabled());
set_progress(true);
assert!(progress_enabled());
set_progress(prev);
}
#[test]
fn status_cell_pads_and_keeps_status() {
let cell = status_cell("ok", 6);
assert!(cell.contains("ok"));
assert!(cell.len() >= 6);
}
#[test]
fn every_spelling_of_one_container_gets_one_colour() {
set_project("proj");
let from_ps = identity_style("proj-web-1");
let from_logs = identity_style("web-1");
assert_eq!(
from_ps.render().to_string(),
from_logs.render().to_string(),
"the same container must be the same colour in ps and logs"
);
}
#[test]
fn an_unprefixed_label_is_keyed_on_itself() {
set_project("proj");
assert_eq!(
identity_style("web").render().to_string(),
service_style("web").render().to_string()
);
}