use super::{own, posting, tick};
use crate::state::Link;
use crate::test_support::Scratch;
use crate::test_support::wire::{entry, flat, wired, yes};
use crate::ui::{Aim, Channel, Chunk, Model};
use serde_json::{Value, json};
use std::time::Duration;
fn beside(aim: Option<Aim>, posted: crate::ui::Posted) -> (Link, Model) {
let link = Link::new(Duration::from_millis(1));
let mut model = Model {
roster: vec![
Chunk::of(own()),
Chunk::of(Channel {
name: "b".to_owned(),
named_there: Some("b".to_owned()),
dials: None,
}),
],
aim,
outbox: vec![posted],
..Model::default()
};
link.settle(&mut model);
(link, model)
}
fn asking() -> Value {
json!({"ok": true, "kind": "attention", "rows": [
{"workspace": "b", "agent": "c-2", "display": "Dun", "state": "live",
"uncertain": false, "preview": "", "age_secs": 0, "pending": 0,
"signals": [], "failure": null, "flag": null, "held": null}]})
}
#[test]
fn a_gesture_naming_no_workspace_is_asked_of_every_channel() {
let scratch = Scratch::new();
let engine = wired(
&scratch,
&flat(),
vec![vec![json!({"ok": true, "kind": "help", "rows": [
{"verb": "scan", "usage": "/scan", "summary": "sweep",
"detail": "one sweep", "surface": "control"}]})]],
);
let (link, mut model) = posting(None, crate::ui::Posted::read(crate::verbs::window::help()));
tick(&link, scratch.path());
link.settle(&mut model);
assert!(
engine.heard().contains(&json!({"op": "help"})),
"{:?}",
engine.heard()
);
assert_eq!(
model.pages.len(),
1,
"the answer landed under the channel it came down"
);
assert_eq!(model.pages[0].channel.name, own().name);
}
#[test]
fn a_fanned_leg_that_reached_nothing_is_that_channels_own_sentence() {
let scratch = Scratch::new();
let (link, mut model) = posting(None, crate::ui::Posted::read(crate::verbs::workspaces()));
tick(&link, scratch.path());
link.settle(&mut model);
let crate::ui::Held::Unheld(why) = &model.roster[0].held else {
panic!(
"the leg's failure lands on its own section: {:?}",
model.roster[0].held
);
};
assert!(!why.is_empty(), "{why}");
assert_eq!(model.notice, None, "and not in the shell-wide bar");
}
#[test]
fn a_receipt_is_stamped_with_the_channel_it_crossed_and_not_the_aim() {
let scratch = Scratch::new();
wired(&scratch, &flat(), vec![vec![yes()]]);
wired(&scratch, &entry("b"), vec![vec![asking()]]);
let (link, mut model) = beside(
Some(Aim {
channel: own().name,
address: "home".to_owned(),
}),
crate::ui::Posted::act(crate::verbs::seen("b".to_owned(), "c-1".to_owned())),
);
tick(&link, scratch.path());
link.settle(&mut model);
assert_eq!(
model
.waiting
.iter()
.map(|held| held.channel.name.clone())
.collect::<Vec<String>>(),
vec!["b".to_owned()],
"the slice belongs to the channel that answered it"
);
}
#[test]
fn a_routed_leg_that_reached_nothing_is_that_channels_own_sentence() {
let scratch = Scratch::new();
wired(&scratch, &flat(), vec![vec![yes()]]);
std::fs::create_dir_all(scratch.path().join(entry("b"))).expect("mkdir");
let (link, mut model) = beside(
Some(Aim {
channel: own().name,
address: "home".to_owned(),
}),
crate::ui::Posted::read(crate::verbs::models("b".to_owned(), "vendor".to_owned())),
);
tick(&link, scratch.path());
link.settle(&mut model);
assert!(
matches!(model.roster[1].held, crate::ui::Held::Unheld(_)),
"the hollow entry's own section says so: {:?}",
model.roster[1].held
);
assert!(
matches!(model.roster[0].held, crate::ui::Held::Unheard),
"and the aim's is untouched: {:?}",
model.roster[0].held
);
}
#[test]
fn an_addressed_gesture_goes_down_the_one_channel_and_no_other() {
let scratch = Scratch::new();
let own_engine = wired(&scratch, &flat(), vec![vec![yes()]]);
let other = wired(&scratch, &entry("b"), vec![vec![yes()]]);
let addressed = Channel {
name: "b".to_owned(),
named_there: Some("b".to_owned()),
dials: None,
};
let (link, mut model) = beside(
Some(Aim {
channel: own().name,
address: "home".to_owned(),
}),
crate::ui::Posted::act(crate::verbs::write(
&crate::verbs::Where::Cadence,
"beat: 1\n".to_owned(),
))
.down(addressed),
);
tick(&link, scratch.path());
link.settle(&mut model);
assert!(
other
.heard()
.contains(&json!({"op": "config", "target": {"file": "cadence"},
"text": "beat: 1\n"})),
"the channel it named heard it: {:?}",
other.heard()
);
assert!(
!own_engine
.heard()
.iter()
.any(|said| said.get("op").is_some()),
"and no other engine was told anything at all: {:?}",
own_engine.heard()
);
}