mod detached;
use super::{append_op, banner, model, world};
use crate::AppModel;
use crate::opslog::{self, Origin};
fn prime(m: &AppModel, cwd: &str, exit: i32, origin: Origin) {
opslog::append(
m.state_root(),
&opslog::OpEntry {
ts: "TS".into(),
argv: vec!["litany".into(), "prime".into()],
cwd: cwd.into(),
exit,
stdout: String::new(),
stderr: if exit == 0 {
String::new()
} else {
"unrecognized subcommand\n".into()
},
origin,
},
)
.unwrap();
}
#[test]
fn a_banner_projects_only_a_failed_last_op() {
let w = world();
let (_c, mut m) = model(&w);
assert!(banner(&m, Origin::Balls).is_none());
append_op(&m);
m.after_litany_verb();
m.tick(); assert!(banner(&m, Origin::Balls).is_none());
prime(&m, "/proj", 2, Origin::Balls);
m.after_litany_verb();
m.tick(); let f = banner(&m, Origin::Balls).unwrap();
assert_eq!(f.argv, "litany prime");
assert_eq!(
crate::opslog::rows::stderr_tail(&f.stderr),
"unrecognized subcommand"
);
}
#[test]
fn a_failure_banners_on_its_own_origin_and_on_no_other() {
let w = world();
let (_c, mut m) = model(&w);
prime(&m, "/proj", 2, Origin::Balls);
m.after_litany_verb();
m.tick();
assert_eq!(
banner(&m, Origin::Balls).unwrap().argv,
"litany prime",
"the balls fold, where the ▶ Start row that fired it is (§11, bl-6ad8)"
);
assert!(
banner(&m, Origin::Conversation).is_none(),
"the composer (and the bootstrap box) says nothing about someone else's start"
);
assert!(
banner(&m, Origin::World).is_none(),
"and neither does the config/login/delete class"
);
}
#[test]
fn each_origin_class_is_rendered_by_its_own_surface_only() {
let w = world();
let (_c, mut m) = model(&w);
prime(&m, "/ws", 2, Origin::Conversation);
m.after_litany_verb();
m.tick();
assert!(banner(&m, Origin::Conversation).is_some());
assert!(banner(&m, Origin::Balls).is_none());
assert!(banner(&m, Origin::World).is_none());
prime(&m, "/ws", 3, Origin::World);
m.after_litany_verb();
m.tick();
assert!(banner(&m, Origin::World).is_some());
assert!(banner(&m, Origin::Balls).is_none());
assert!(
banner(&m, Origin::Conversation).is_some(),
"and a later World failure does not retire the composer's live one"
);
}
#[test]
fn a_clean_run_clears_only_its_own_surfaces_banner() {
let w = world();
let (_c, mut m) = model(&w);
prime(&m, "/ws", 2, Origin::Conversation);
prime(&m, "/proj", 0, Origin::Balls); m.after_litany_verb();
m.tick();
assert!(
banner(&m, Origin::Conversation).is_some(),
"the composer's failure is still the composer's last word"
);
assert!(banner(&m, Origin::Balls).is_none());
prime(&m, "/ws", 0, Origin::Conversation);
m.after_litany_verb();
m.tick();
assert!(banner(&m, Origin::Conversation).is_none());
assert_eq!(m.snap.ops.len(), 3, "the log keeps every line");
}
#[test]
fn a_re_run_green_verb_retires_its_stale_failure_from_the_chip() {
let w = world();
let (_c, mut m) = model(&w);
prime(&m, "/w", 2, Origin::Balls);
m.after_litany_verb();
m.tick(); assert_eq!(m.activity().errors, 1, "the fresh failure is live");
prime(&m, "/w", 0, Origin::Balls);
m.after_litany_verb();
m.tick(); assert_eq!(
m.activity(),
opslog::Activity {
total: 2,
errors: 0,
drifts: 0
}
);
assert_eq!(m.snap.ops.len(), 2, "the log keeps both lines");
append_op(&m); prime(&m, "/other", 3, Origin::Balls);
m.after_litany_verb();
m.tick(); assert_eq!(m.activity().errors, 1);
assert_eq!(banner(&m, Origin::Balls).unwrap().argv, "litany prime");
}