use super::{agent, nothing, tips_acked};
use crate::attention::*;
use crate::git_tree::{Agent, AgentState};
fn roster(ags: &[Agent]) -> Vec<RosterKey> {
ags.iter()
.map(|a| RosterKey {
ws: "/w".to_string(),
agent_id: a.agent_id.clone(),
attention: attention(a, ags, "/w", ¬hing).any(),
})
.collect()
}
fn focus(id: &str) -> (&str, &str) {
("/w", id)
}
fn jump_fixture() -> [Agent; 3] {
let mut a1 = agent("a1");
a1.state = AgentState::Stopped;
let mut a3 = agent("a3");
a3.notify_oid = Some("n".into());
[a1, agent("a2"), a3]
}
#[test]
fn workspace_count_and_strip_total() {
let mut needs = agent("a");
needs.notify_oid = Some("n".into());
let mut needs2 = agent("c");
needs2.state = AgentState::Stopped;
let ws_a = [needs, agent("b")];
let ws_b = [needs2];
assert_eq!(workspace_count(&ws_a, "/w/a", ¬hing), 1);
assert_eq!(workspace_count(&ws_b, "/w/b", ¬hing), 1);
assert_eq!(
strip_total(
&[("/w/a", ws_a.as_slice()), ("/w/b", ws_b.as_slice())],
¬hing
),
2
);
}
#[test]
fn roster_sorts_attention_then_running_then_idle_then_descent() {
let running = agent("r-live"); let mut attn = agent("r-attn");
attn.state = AgentState::Stopped; let (mut idle, mut idle2) = (agent("r"), agent("r-idle"));
idle.state = AgentState::Quiescent;
idle2.state = AgentState::Quiescent;
let agents = [idle, running, attn, idle2];
let ids: Vec<&str> = sorted_roster(&agents, "/w", &tips_acked(&["r", "r-idle"]))
.iter()
.map(|&i| agents[i].agent_id.as_str())
.collect();
assert_eq!(ids, vec!["r-attn", "r-live", "r", "r-idle"]);
}
#[test]
fn roster_order_is_path_order_across_and_sorted_within() {
let mut attn = agent("z");
attn.state = AgentState::Stopped;
let ws_b = [attn, agent("y")]; let solo = [agent("s")];
let order = roster_order(
&[("/w/b", ws_b.as_slice()), ("/w/a", solo.as_slice())],
¬hing,
);
let flat: Vec<(&str, &str)> = order
.iter()
.map(|e| (e.ws.as_str(), e.agent_id.as_str()))
.collect();
assert_eq!(flat, vec![("/w/a", "s"), ("/w/b", "z"), ("/w/b", "y")]);
}
#[test]
fn jump_empty_roster_is_none() {
assert!(next_attention(&[], None).is_none());
}
#[test]
fn jump_from_none_finds_first_attention() {
let ags = jump_fixture();
let hit = next_attention(&roster(&ags), None).unwrap();
assert_eq!(hit.agent_id, "a1");
}
#[test]
fn jump_none_when_nothing_has_attention() {
let ags = [agent("a1"), agent("a2")];
assert!(next_attention(&roster(&ags), None).is_none());
}
#[test]
fn jump_wraps_past_the_end() {
let ags = jump_fixture();
let hit = next_attention(&roster(&ags), Some(focus("a3"))).unwrap();
assert_eq!(hit.agent_id, "a1");
}
#[test]
fn jump_sole_attention_returns_itself_on_full_wrap() {
let mut only = agent("a1");
only.notify_oid = Some("n".into());
let ags = [only, agent("a2"), agent("a3")];
let hit = next_attention(&roster(&ags), Some(focus("a1"))).unwrap();
assert_eq!(hit.agent_id, "a1");
}
#[test]
fn jump_unknown_focus_starts_from_front() {
let ags = jump_fixture();
let hit = next_attention(&roster(&ags), Some(focus("ghost"))).unwrap();
assert_eq!(hit.agent_id, "a1");
}