mod composites;
use super::super::verdict::REFUSED;
use super::super::{Decided, run, usage, version};
use super::{argv, asked, fanned, said};
use crate::render::Form;
use serde_json::json;
#[test]
fn both_version_spellings_print_the_version_and_succeed() {
for spelling in ["--version", "-V"] {
let v = said(&[spelling]);
assert_eq!(v.code, 0, "{spelling} did not succeed");
assert_eq!(v.text, version(), "{spelling} printed something else");
}
}
#[test]
fn the_verbs_decide_and_carry_what_they_were_given() {
assert!(matches!(run(argv(&["entries"])), Decided::Entries));
assert_eq!(
asked(&["ask", r#"{"op":"workspaces"}"#]),
json!({"op": "workspaces"})
);
}
#[test]
fn the_trail_defaults_its_depth_to_the_one_the_window_asks_with() {
assert_eq!(
fanned(&["ops"]),
json!({"op": "ops", "max": crate::verbs::DEPTH})
);
assert_eq!(fanned(&["ops", "5"]), json!({"op": "ops", "max": 5}));
assert_eq!(
fanned(&["ops"]),
asked_of_everything(),
"the word and the envelope it stands for decide alike"
);
}
fn asked_of_everything() -> serde_json::Value {
match run(argv(&[
"ask",
&format!(r#"{{"op":"ops","max":{}}}"#, crate::verbs::DEPTH),
])) {
Decided::Ask(envelope, _) | Decided::Fanned(envelope, _) => envelope,
other => panic!("decided {other:?}"),
}
}
#[test]
fn a_typed_verb_and_the_envelope_it_stands_for_decide_alike() {
let typed = asked(&["conversations", "home"]);
let written = asked(&["ask", r#"{"op":"conversations","workspace":"home"}"#]);
assert_eq!(typed, written);
assert_eq!(typed, json!({"op": "conversations", "workspace": "home"}));
}
#[test]
fn every_verb_in_the_table_is_typable() {
for verb in crate::verbs::table() {
let mut words = vec![verb.word];
let filled: Vec<String> = verb
.params
.iter()
.map(|p| {
if *p == "grade" {
crate::ui::Grade::default().word()
} else {
format!("a-{p}")
}
})
.collect();
words.extend(filled.iter().map(String::as_str));
if verb.word == crate::verbs::ENROLL.word {
let Decided::Enroll {
workspace,
name,
grade,
into,
} = run(argv(&words))
else {
panic!("`enroll` renders its answer rather than printing a frame");
};
assert_eq!(
(workspace.as_str(), name.as_str(), grade.as_str()),
(
"a-workspace",
"a-name",
crate::ui::Grade::default().word().as_str()
)
);
assert_eq!(into, None);
continue;
}
if verb.word == crate::verbs::FOLLOW.word {
let Decided::Follow { .. } = run(argv(&words)) else {
panic!("`follow` watches rather than asking once");
};
continue;
}
if verb.word == crate::verbs::MODEL.word {
let Decided::Model { .. } = run(argv(&words)) else {
panic!("`model` checks before it assigns");
};
continue;
}
let sent = if verb.addresses_a_workspace() {
asked(&words)
} else {
fanned(&words)
};
assert_eq!(sent["op"], json!(verb.word), "{}", verb.word);
}
}
#[test]
fn the_roster_word_fans_while_the_hand_written_envelope_does_not() {
assert_eq!(fanned(&["workspaces"]), json!({"op": "workspaces"}));
assert_eq!(
asked(&["ask", r#"{"op":"workspaces"}"#]),
json!({"op": "workspaces"}),
"the raw door is one channel's, always"
);
}
#[test]
fn every_help_spelling_prints_the_one_usage() {
for spelling in ["help", "--help", "-h"] {
let v = said(&[spelling]);
assert_eq!(v.code, 0, "{spelling} did not succeed");
assert_eq!(v.text, usage(), "{spelling} printed something else");
}
}
#[test]
fn help_on_a_verb_answers_its_page_and_refuses_a_word_that_is_not_one() {
let page = said(&["help", "nudge"]);
assert_eq!(page.code, 0);
assert!(
page.text.starts_with("usage: lernie nudge"),
"{}",
page.text
);
let refusal = said(&["help", "nudje"]);
assert_eq!(refusal.code, REFUSED);
assert!(refusal.text.contains("\"nudje\""), "{}", refusal.text);
}
#[test]
fn a_bare_invocation_opens_the_window() {
assert!(matches!(run(argv(&[])), Decided::Window));
}
#[test]
fn the_json_flag_leads_and_leaves_the_gesture_exactly_as_it_was() {
let Decided::Fanned(bare, Form::Rendered) = run(argv(&["workspaces"])) else {
panic!("a bare read renders");
};
let Decided::Fanned(flagged, Form::Json) = run(argv(&["--json", "workspaces"])) else {
panic!("a flagged read is the machine form");
};
assert_eq!(bare, flagged);
let Decided::Ask(_, Form::Json) = run(argv(&["--json", "conversations", "home"])) else {
panic!("a workspace read carries the form too");
};
let Decided::Start { form, .. } = run(argv(&["--json", "start", "home", "go"])) else {
panic!("the composite carries it");
};
assert_eq!(form, Form::Json);
let Decided::Ask(_, Form::Json) = run(argv(&["--json", "ask", "{\"op\":\"workspaces\"}"]))
else {
panic!("the raw door carries it");
};
}
#[test]
fn the_flag_after_the_word_is_the_operators_own_text() {
assert_eq!(
asked(&["message", "home", "Pelican", "--json"]),
json!({"op": "message", "workspace": "home", "agent": "Pelican",
"content": "--json"})
);
}
#[test]
fn the_stop_cascade_is_typed_as_the_word_children() {
assert_eq!(
asked(&["stop", "home", "Pelican"]),
json!({"op": "stop", "workspace": "home", "agent": "Pelican"})
);
assert_eq!(
asked(&["stop", "home", "Pelican", "children"]),
json!({"op": "stop", "workspace": "home", "agent": "Pelican", "children": true})
);
}