use std::time::Duration;
use super::{still_on, tick};
use crate::state::Link;
use crate::test_support::Scratch;
use crate::test_support::wire::{flat, wired};
use crate::ui::{Aim, Channel, Chunk, Login, Model};
use serde_json::json;
fn own() -> Channel {
Channel {
name: crate::seat::OWN.to_owned(),
named_there: None,
dials: None,
}
}
fn watching() -> Model {
Model {
roster: vec![Chunk::of(own())],
aim: Some(Aim {
channel: own().name,
address: "home".to_owned(),
}),
login: Some(Login {
following: Some("housevendor".to_owned()),
asking: None,
}),
..Model::default()
}
}
fn linked(model: &Model) -> Link {
let link = Link::new(Duration::from_millis(1));
let mut model = model.clone();
link.settle(&mut model);
link
}
#[test]
fn every_frame_of_the_held_read_is_absorbed_onto_an_empty_fold() {
let scratch = Scratch::new();
let engine = wired(
&scratch,
&flat(),
vec![vec![
json!({"ok": true, "kind": "login",
"lines": [{"text": "open https://provider.invalid/auth", "err": true}]}),
json!({"ok": true, "kind": "login",
"lines": [{"text": "code ABCD-EFGH", "err": true}]}),
json!({"ok": true, "kind": "login", "lines": [], "outcome": 0}),
]],
);
let mut model = watching();
let link = linked(&model);
tick(&link, scratch.path());
link.settle(&mut model);
let run = model.signin.expect("the accumulated run");
assert_eq!(run.lines.len(), 2, "the two lines accrete in order");
assert_eq!(run.lines[0].text, "open https://provider.invalid/auth");
assert_eq!(run.lines[1].text, "code ABCD-EFGH");
assert_eq!(run.outcome, Some(0));
assert!(run.settled());
assert!(
engine
.heard()
.contains(&json!({"op": "login-tail", "workspace": "home", "provider": "housevendor"})),
"{:?}",
engine.heard()
);
}
#[test]
fn a_second_read_replaces_rather_than_appending() {
let scratch = Scratch::new();
let _engine = wired(
&scratch,
&flat(),
vec![
vec![json!({"ok": true, "kind": "login",
"lines": [{"text": "one", "err": false}]})],
vec![json!({"ok": true, "kind": "login",
"lines": [{"text": "one", "err": false},
{"text": "two", "err": false}]})],
],
);
let mut model = watching();
let link = linked(&model);
tick(&link, scratch.path());
link.settle(&mut model);
tick(&link, scratch.path());
link.settle(&mut model);
assert_eq!(
model.signin.expect("the run").lines.len(),
2,
"the second read's first frame is the whole buffer, absorbed onto nothing"
);
}
#[test]
fn the_read_is_about_a_wall_and_a_provider_row_together() {
let model = watching();
let link = linked(&model);
let aim = model.aim.clone().expect("an aim");
assert!(still_on(&link, &aim, "housevendor"));
assert!(!still_on(&link, &aim, "otherhouse"));
let elsewhere = Aim {
channel: own().name,
address: "other".to_owned(),
};
assert!(!still_on(&link, &elsewhere, "housevendor"));
let idle = linked(&Model::default());
assert!(!still_on(&idle, &aim, "housevendor"));
}
#[test]
fn a_frame_for_a_row_the_operator_left_is_dropped() {
let link = Link::new(Duration::from_millis(1));
let stale = json!({"ok": true, "kind": "login",
"lines": [{"text": "stale", "err": false}]});
let wanted = json!({"ok": true, "kind": "login",
"lines": [{"text": "wanted", "err": false}]});
link.signing(&own(), "otherhouse", crate::reply::read(&stale));
link.signing(&own(), "housevendor", crate::reply::read(&wanted));
let mut model = watching();
link.settle(&mut model);
let run = model.signin.expect("the run");
assert_eq!(run.lines.len(), 1);
assert_eq!(run.lines[0].text, "wanted");
}
#[test]
fn with_no_row_followed_there_is_no_held_read() {
let scratch = Scratch::new();
let mut shut = watching();
shut.login = None;
let mut open = watching();
open.login = Some(Login::default());
for model in [Model::default(), shut, open] {
let link = linked(&model);
tick(&link, scratch.path());
let mut settled = model.clone();
link.settle(&mut settled);
assert_eq!(settled.notice, None);
assert_eq!(settled.signin, None);
}
}
#[test]
fn a_lane_that_cannot_be_opened_says_so_as_unreachable() {
let scratch = Scratch::new();
let model = watching();
let link = linked(&model);
tick(&link, scratch.path());
let mut settled = model.clone();
link.settle(&mut settled);
let crate::ui::Held::Unheld(why) = &settled.roster[0].held else {
panic!("the lane said nothing: {:?}", settled.roster[0].held);
};
assert!(why.contains("no wire provisioned"), "{why}");
assert_eq!(settled.notice, None);
}
#[test]
fn a_held_read_that_answers_something_other_than_a_run_crosses_untouched() {
let scratch = Scratch::new();
let _engine = wired(
&scratch,
&flat(),
vec![vec![
json!({"ok": true, "kind": "login",
"lines": [{"text": "said", "err": false}]}),
json!({"ok": false, "error": "unknown provider"}),
]],
);
let mut model = watching();
let link = linked(&model);
tick(&link, scratch.path());
link.settle(&mut model);
assert_eq!(
model.notice,
Some(crate::ui::Notice::Refused("unknown provider".to_owned())),
"the engine's own words, not a fold"
);
assert_eq!(
model.signin.expect("the run").lines.len(),
1,
"and what the run had already said is still standing"
);
}