mod tone;
use super::{
ASH, BRAZEN, BRAZEN_DIM, GATE, HYDRA, ICHOR, SIGIL, SPECTRE, apply, ball_hue, integration_hue,
pulse, visuals,
};
#[test]
fn integration_hues_key_the_three_driven_tools() {
assert_eq!(integration_hue("lernie"), HYDRA);
assert_eq!(integration_hue("bz"), BRAZEN);
assert_eq!(integration_hue("bl"), GATE);
assert_eq!(integration_hue("cthulhu"), super::MOONLIT);
}
#[test]
fn palette_hues_are_pairwise_distinct() {
let hues = [HYDRA, SPECTRE, BRAZEN, BRAZEN_DIM, ICHOR, ASH, SIGIL, GATE];
for (i, a) in hues.iter().enumerate() {
for b in hues.iter().skip(i + 1) {
assert_ne!(a, b);
}
}
}
#[test]
fn verdict_badges_are_distinct_and_name_their_verdict() {
use crate::monitor::Verdict;
let mut carriers = std::collections::HashSet::new();
for verdict in [Verdict::Aligned, Verdict::Drifting, Verdict::Diverged] {
let (glyph, color, phrase) = super::verdict_badge(verdict);
assert!(carriers.insert(glyph), "duplicate glyph {glyph:?}");
assert!(carriers.insert(phrase), "duplicate phrase {phrase:?}");
assert!(
phrase.starts_with(verdict.token()),
"{phrase:?} does not say its verdict"
);
assert!(color.to_array()[3] > 0, "an invisible badge says nothing");
}
assert_eq!(super::verdict_badge(Verdict::Aligned).1, super::MOONLIT);
assert_eq!(super::verdict_badge(Verdict::Diverged).1, super::ICHOR);
}
#[test]
fn flight_badges_are_distinct_in_all_three_carriers() {
use crate::nav::convs::Flight;
let classes = [Flight::Inference, Flight::Tools, Flight::Subagents];
let mut glyphs = std::collections::HashSet::new();
let mut colors = std::collections::HashSet::new();
let mut phrases = std::collections::HashSet::new();
for f in classes {
let (glyph, color, phrase) = super::flight_badge(f);
assert!(glyphs.insert(glyph), "duplicate glyph {glyph:?} for {f:?}");
assert!(colors.insert(color.to_array()), "duplicate hue for {f:?}");
assert!(!phrase.is_empty(), "unsaid class {f:?}");
assert!(phrases.insert(phrase), "duplicate phrase for {f:?}");
}
assert_eq!(super::flight_badge(Flight::Inference).1, SPECTRE);
assert_eq!(super::flight_badge(Flight::Tools).1, HYDRA);
assert_eq!(super::flight_badge(Flight::Subagents).1, BRAZEN);
}
#[test]
fn state_badges_are_distinct_per_state() {
use crate::git_tree::AgentState;
let states = [
AgentState::Live,
AgentState::InFlight,
AgentState::Quiescent,
AgentState::Stopped,
];
let mut glyphs = std::collections::HashSet::new();
let mut colors = std::collections::HashSet::new();
let mut phrases = std::collections::HashSet::new();
for s in states {
let (glyph, color, phrase) = super::state_badge(s);
assert!(glyphs.insert(glyph), "duplicate glyph {glyph:?} for {s:?}");
assert!(
colors.insert(color.to_array()),
"duplicate colour for {s:?}"
);
assert!(!phrase.is_empty(), "unsaid state {s:?}");
assert!(
phrases.insert(phrase),
"duplicate phrase {phrase:?} for {s:?}"
);
}
let (glyph, color, phrase) = super::state_badge(AgentState::Live);
assert_eq!((glyph, color), ("●", HYDRA));
assert!(phrase.starts_with("live —"));
let (glyph, color, phrase) = super::state_badge(AgentState::InFlight);
assert_eq!((glyph, color), ("◐", SPECTRE));
assert!(phrase.starts_with("in flight —"));
let (glyph, color, phrase) = super::state_badge(AgentState::Quiescent);
assert_eq!((glyph, color), ("○", BRAZEN_DIM));
assert!(phrase.starts_with("quiescent —"));
let (glyph, color, phrase) = super::state_badge(AgentState::Stopped);
assert_eq!((glyph, color), ("■", ASH));
assert!(phrase.starts_with("stopped —"));
assert!(super::STATE_UNCERTAIN.starts_with("uncertain —"));
assert!(super::NAME_DISPLAY_ONLY.starts_with("display-only name —"));
assert!(super::NAME_DISPLAY_ONLY.contains("agent id"));
}
#[test]
fn every_agent_mark_says_itself_in_a_label_and_a_sentence() {
use crate::git_tree::AgentMark;
let marks = [
AgentMark::Notified,
AgentMark::BudgetExhausted,
AgentMark::Conflicted,
AgentMark::Held,
AgentMark::Abandoned,
];
let mut labels = std::collections::HashSet::new();
let mut phrases = std::collections::HashSet::new();
for m in marks {
let (label, _, phrase) = super::mark_badge(m);
assert!(labels.insert(label), "duplicate label {label:?} for {m:?}");
assert!(
phrase.starts_with(label) && phrase.len() > label.len(),
"unexplained mark {m:?}: {phrase:?}"
);
assert!(phrases.insert(phrase), "duplicate phrase for {m:?}");
}
assert_eq!(super::mark_badge(AgentMark::Notified).1, BRAZEN);
assert_eq!(super::mark_badge(AgentMark::BudgetExhausted).1, BRAZEN);
assert_eq!(super::mark_badge(AgentMark::Conflicted).1, ICHOR);
assert_eq!(super::mark_badge(AgentMark::Held).1, BRAZEN);
assert_eq!(super::mark_badge(AgentMark::Abandoned).1, ASH);
}
#[test]
fn op_badges_say_their_outcome_in_words() {
use crate::opslog::OpOutcome;
let mut colors = std::collections::HashSet::new();
let mut phrases = std::collections::HashSet::new();
for o in [
OpOutcome::Clean,
OpOutcome::Failed,
OpOutcome::Retired,
OpOutcome::Detached,
OpOutcome::Notice,
] {
let (glyph, color, phrase) = super::op_badge(o);
assert!(!glyph.is_empty(), "unmarked outcome {o:?}");
assert!(
colors.insert(color.to_array()),
"duplicate colour for {o:?}"
);
assert!(!phrase.is_empty(), "unsaid outcome {o:?}");
assert!(
phrases.insert(phrase),
"duplicate phrase {phrase:?} for {o:?}"
);
}
let (failed_glyph, failed_hue, failed_phrase) = super::op_badge(OpOutcome::Failed);
assert_eq!(
(failed_glyph, failed_hue, failed_phrase),
("⚠", ICHOR, "failed")
);
let (retired_glyph, retired_hue, retired_phrase) = super::op_badge(OpOutcome::Retired);
assert_eq!((retired_glyph, retired_hue), ("⚠", ASH));
assert!(retired_phrase.starts_with("failed, retired by"));
assert_eq!(
super::op_badge(OpOutcome::Clean),
("·", super::MOONLIT, "ran clean")
);
let (detached_glyph, detached_hue, detached_phrase) = super::op_badge(OpOutcome::Detached);
assert_ne!(detached_glyph, "·", "must not read as clean");
assert_ne!(detached_glyph, "⚠", "must not read as failed");
assert_eq!(detached_hue, BRAZEN);
assert_eq!(detached_phrase, "detached — handed off, no exit to observe");
let (notice_glyph, notice_hue, notice_phrase) = super::op_badge(OpOutcome::Notice);
assert_ne!(notice_hue, ICHOR, "a notice must never read as a wound");
assert_eq!(notice_hue, super::BRAZEN_DIM);
assert_ne!(notice_glyph, "⚠", "must not read as failed");
assert_ne!(notice_glyph, "·", "must not read as clean");
assert!(notice_phrase.starts_with("notice"));
}
#[test]
fn tool_result_badges_say_the_outcome() {
let ok = super::tool_result_badge(false);
let err = super::tool_result_badge(true);
assert_eq!((ok.0, ok.1), ("✔", HYDRA));
assert_eq!((err.0, err.1), ("✖", ICHOR));
assert!(!ok.2.is_empty(), "unsaid ok outcome");
assert!(!err.2.is_empty(), "unsaid error outcome");
assert_ne!(ok.2, err.2, "one phrase for both outcomes says neither");
}
#[test]
fn ball_hues_key_the_derived_join_status() {
use crate::projects::join::JoinState;
assert_eq!(ball_hue(JoinState::Bound), HYDRA);
assert_eq!(ball_hue(JoinState::Delivered), ASH);
assert_eq!(ball_hue(JoinState::Blocked), BRAZEN);
assert_eq!(ball_hue(JoinState::ClaimedElsewhere), BRAZEN);
assert_eq!(ball_hue(JoinState::OrphanedProject), ICHOR);
assert_eq!(ball_hue(JoinState::ReadyStartable), super::MOONLIT);
assert_eq!(ball_hue(JoinState::UnassignedWorkspace), super::MOONLIT);
}
#[test]
fn visuals_reground_the_dark_theme_in_the_void() {
let v = visuals();
assert!(v.dark_mode);
assert_eq!(v.panel_fill, egui::Color32::from_rgb(19, 15, 27));
assert_eq!(v.window_fill, egui::Color32::from_rgb(15, 12, 22));
assert_eq!(v.extreme_bg_color, egui::Color32::from_rgb(10, 8, 15));
assert_eq!(v.code_bg_color, v.extreme_bg_color);
assert_eq!(v.faint_bg_color, egui::Color32::from_rgb(30, 24, 43));
assert_eq!(v.selection.stroke.color, GATE);
assert_eq!(v.selection.bg_fill, GATE.gamma_multiply(0.35));
assert_eq!(v.hyperlink_color, SPECTRE);
assert_eq!(v.warn_fg_color, BRAZEN);
assert_eq!(v.error_fg_color, ICHOR);
let base = v.widgets.noninteractive.fg_stroke.color;
let hover = v.widgets.hovered.fg_stroke.color;
assert_eq!(base, egui::Color32::from_rgb(198, 190, 216));
assert_eq!(hover, egui::Color32::from_rgb(240, 234, 250));
assert_eq!(v.widgets.active.bg_stroke.color, GATE);
}
#[test]
fn apply_installs_the_visuals_on_a_context() {
let ctx = egui::Context::default();
apply(&ctx);
assert_eq!(ctx.style().visuals.panel_fill, visuals().panel_fill);
assert_eq!(ctx.style().visuals.selection.stroke.color, GATE);
}
#[test]
fn pulse_breathes_its_hue_between_dim_and_full() {
use std::f64::consts::PI;
let full = pulse(SPECTRE, PI / 8.0);
let dim = pulse(SPECTRE, 3.0 * PI / 8.0);
assert_eq!(full, SPECTRE.gamma_multiply(1.0));
assert_eq!(dim, SPECTRE.gamma_multiply(0.35));
assert!(dim.r() < full.r());
assert_eq!(pulse(HYDRA, PI / 8.0), HYDRA.gamma_multiply(1.0));
assert_ne!(pulse(HYDRA, PI / 8.0), full);
}