use super::{Choice, HEADING, HINT, answer, choices, confirm, moved, pick, row, words};
use crate::paint_probe::frame::{Window, press};
use crate::test_support::window::{asked, click, painted, seated};
use crate::ui::{Model, theme};
use serde_json::json;
fn last_op(model: &Model) -> Option<serde_json::Value> {
model.outbox.last().map(|p| p.envelope["op"].clone())
}
#[test]
fn it_stands_on_the_selected_conversation_s_row_and_not_otherwise() {
assert!(row(&seated()).is_none());
let mut model = asked();
assert!(row(&model).is_some());
let window = Window::new();
window.text(|ctx| crate::ui::render(ctx, &mut model));
let text = window.text(|ctx| crate::ui::render(ctx, &mut model));
for word in [
HEADING,
HINT,
"1. seen",
"2. pass",
"6. hold",
"held at the boundary",
] {
assert!(text.contains(word), "{word:?}:\n{text}");
}
model.conversation = Some("c-9".to_owned());
assert!(row(&model).is_none());
let text = painted(&mut model);
assert!(!text.contains(HEADING), "{text}");
}
#[test]
fn the_choices_are_the_queue_s_acts() {
let model = asked();
let (_, held) = row(&model).expect("a row");
let offered: Vec<String> = choices(&held).into_iter().map(Choice::word).collect();
assert_eq!(
offered,
vec![
"seen",
"pass",
"pass for this conversation",
"pass for this workspace",
"refuse",
"hold"
]
);
assert_eq!(Choice::Seen.op(), "seen");
assert_eq!(Choice::Verdict("pass", "call").op(), "answer");
let quiet = crate::reply::queue::QueueRow {
held: None,
..held.clone()
};
assert_eq!(choices(&quiet), vec![Choice::Seen]);
let said: Vec<String> = words(&held).into_iter().map(|(s, _)| s).collect();
assert!(said.iter().any(|s| s.starts_with("held at the boundary")));
assert!(said.iter().any(|s| s.starts_with("flagged")));
assert!(said.contains(&"Unauthorized".to_owned()));
}
#[test]
fn a_digit_the_arrows_and_a_click_each_answer() {
let mut model = asked();
assert!(pick(&mut model, 1));
assert_eq!(last_op(&model), Some(json!("seen")));
assert!(pick(&mut model, 3));
assert_eq!(last_op(&model), Some(json!("answer")));
assert_eq!(
model.outbox.last().map(|p| p.envelope["scope"].clone()),
Some(json!("conversation"))
);
assert!(!pick(&mut model, 9), "no ninth row");
assert!(!pick(&mut model, 0), "the digits count from one");
let window = Window::new();
let key = |model: &mut Model, key| {
window.frame(vec![press(key)], |ctx| crate::ui::render(ctx, model));
};
let mut model = asked();
key(&mut model, egui::Key::ArrowDown);
key(&mut model, egui::Key::ArrowDown);
key(&mut model, egui::Key::ArrowUp);
key(&mut model, egui::Key::Enter);
assert_eq!(last_op(&model), Some(json!("answer")));
assert_eq!(
model.outbox.last().map(|p| p.envelope["verdict"].clone()),
Some(json!("pass"))
);
key(&mut model, egui::Key::Num5);
assert_eq!(
model.outbox.last().map(|p| p.envelope["verdict"].clone()),
Some(json!("refuse"))
);
let mut model = asked();
click(&window, "6. hold", |ctx| crate::ui::render(ctx, &mut model));
assert_eq!(
model.outbox.last().map(|p| p.envelope["verdict"].clone()),
Some(json!("hold"))
);
}
#[test]
fn a_digit_in_the_box_picks_nothing() {
let mut model = asked();
let window = Window::new();
window.frame(Vec::new(), |ctx| crate::ui::render(ctx, &mut model));
window.focus(egui::Id::new(crate::ui::keys::BOX_ID));
window.frame(vec![press(egui::Key::Num1)], |ctx| {
crate::ui::render(ctx, &mut model);
});
assert!(model.outbox.is_empty(), "{:?}", model.outbox);
window.focus(egui::Id::new("a control the Tab landed on"));
window.frame(vec![press(egui::Key::Num1)], |ctx| {
crate::ui::render(ctx, &mut model);
});
assert!(model.outbox.is_empty(), "{:?}", model.outbox);
}
#[test]
fn nothing_asks_nothing_answers() {
let mut model = seated();
let window = Window::new();
window.frame(Vec::new(), |ctx| {
moved(ctx, &model, 1);
confirm(ctx, &mut model);
});
assert!(model.outbox.is_empty());
assert!(!pick(&mut model, 1));
let held = row(&asked()).expect("a row");
answer(&mut model, &held, Choice::Seen);
assert_eq!(last_op(&model), Some(json!("seen")));
}
#[test]
fn the_box_wears_the_attention_accent() {
let mut model = asked();
let window = Window::new();
let output = window.frame(Vec::new(), |ctx| crate::ui::render(ctx, &mut model));
let accent = theme::accent(theme::State::Attention);
let name = crate::paint_probe::seen_of(&output)
.into_iter()
.find(|run| run.text == HEADING)
.expect("the name is on the glass");
assert_eq!(name.ink, accent);
assert!(
crate::paint_probe::strokes_of(&output)
.iter()
.any(|(_, ink)| *ink == accent),
"the frame is green"
);
}
#[test]
fn the_box_goes_down_on_the_frame_the_receipt_lands() {
let mut model = asked();
let text = painted(&mut model);
assert!(text.contains(HEADING), "{text}");
let selected = row(&model).expect("a row").1.agent;
let remains = json!({
"workspace": "home", "agent": "c-2", "display": "c-2", "state": "quiescent",
"uncertain": true, "preview": "", "age_secs": 7, "pending": 0, "says": "",
"signals": [], "failure": null, "flag": null, "held": null,
});
let receipt = crate::reply::read(&json!({
"ok": true, "kind": "acknowledged", "workspace": "home", "agent": selected,
"rows": [remains],
}));
model.receipt(&crate::test_support::window::own().channel, "seen", receipt);
assert!(row(&model).is_none());
let text = painted(&mut model);
assert!(!text.contains(HEADING), "{text}");
assert!(text.contains(&format!("seen home/{selected}")), "{text}");
assert!(!text.contains("could not read"), "{text}");
}
#[test]
fn a_seen_row_that_still_asks_is_said_to() {
let acked = crate::reply::queue::Acknowledged {
workspace: "home".to_owned(),
agent: "c-2".to_owned(),
rows: vec![crate::test_support::window::waiting("home", "c-2")],
};
let said = crate::ui::model::Notice::seen(&acked).line();
assert!(said.contains("still asking"), "{said}");
}