use super::super::Stream;
use super::super::verdict::REFUSED;
use super::said;
#[test]
fn a_misspelled_enrollment_earns_the_row_s_usage() {
let said = said(&["enroll", "home"]);
assert_eq!(said.code, 2);
assert!(
said.text.contains(&crate::verbs::ENROLL.usage()),
"{}",
said.text
);
}
#[test]
fn the_start_word_refuses_by_arity_and_says_what_it_takes() {
for words in [
vec!["start"],
vec!["start", "home"],
vec!["start", "home", "do", "the", "thing"],
] {
let v = said(&words);
assert_eq!(v.code, REFUSED, "{words:?}");
assert_eq!(v.stream, Stream::Err);
let wanted = format!(
"`lernie start` takes 2 argument(s) and got {} — usage: lernie start <workspace> <goal>",
words.len() - 1
);
assert!(v.text.contains(&wanted), "{}", v.text);
}
}
#[test]
fn a_verb_with_the_wrong_arity_refuses_by_name_and_teaches_the_grammar() {
let v = said(&["transcript", "home"]);
assert_eq!(v.code, REFUSED);
assert!(v.text.contains("`lernie transcript`"), "{}", v.text);
assert!(
v.text
.contains("usage: lernie transcript <workspace> <agent>"),
"{}",
v.text
);
}
#[test]
fn a_body_that_is_not_a_gesture_is_refused_with_the_usage() {
for (body, said_what) in [
("not json at all", "not JSON"),
("[1,2]", "a gesture is a JSON object"),
(r#"{"workspace":"home"}"#, "missing field"),
] {
let v = said(&["ask", body]);
assert_eq!(v.code, REFUSED, "{body}");
assert_eq!(v.stream, Stream::Err);
assert!(v.text.contains(said_what), "{body}: {}", v.text);
assert!(v.text.contains("usage: lernie"), "{body}: {}", v.text);
}
}
#[test]
fn a_door_with_the_wrong_arity_refuses_by_name_and_teaches_the_grammar() {
for (words, expected) in [
(
vec!["ask"],
"`lernie ask` takes 1 argument(s) and got 0 — usage: lernie ask <envelope>",
),
(
vec!["ask", "{}", "twice"],
"`lernie ask` takes 1 argument(s) and got 2 — usage: lernie ask <envelope>",
),
(
vec!["entries", "--now"],
"`lernie entries` takes 0 argument(s) and got 1 — usage: lernie entries",
),
(
vec!["help", "a", "b"],
"`lernie help` takes at most 1 argument(s) and got 2 — usage: lernie help [<verb>]",
),
] {
let v = said(&words);
assert_eq!(v.code, REFUSED, "{words:?}");
assert!(v.text.contains(expected), "{words:?}:\n{}", v.text);
}
}
#[test]
fn an_unrecognised_argument_refuses_and_quotes_every_word_of_it() {
let v = said(&["seat", "--ws", "Example"]);
assert_eq!(v.code, REFUSED);
assert!(
v.text.contains("unrecognised argument: seat --ws Example"),
"{}",
v.text
);
}
#[test]
fn a_recognised_word_with_extra_words_is_not_recognised() {
let extra = ["--version", "--now"];
let v = said(&extra);
assert_eq!(v.code, REFUSED);
assert!(
v.text
.contains(&format!("unrecognised argument: {}", extra.join(" "))),
"{}",
v.text
);
}
#[test]
fn a_grade_that_is_not_one_of_the_two_refuses_before_anything_is_dialled() {
for typo in ["notagrade", "OPERATOR", ""] {
let v = said(&["enroll", "home", "phone-1", typo]);
assert_eq!(v.code, REFUSED, "{typo:?}");
assert!(
v.text
.contains(&format!("unknown grade {typo:?} — `lernie enroll` takes")),
"{typo:?}: {}",
v.text
);
for word in crate::ui::Grade::both() {
assert!(
v.text.contains(&format!("{:?}", word.word())),
"it names both words that would have worked: {}",
v.text
);
}
}
}
#[test]
fn no_sentence_this_binary_composes_carries_a_run_of_spaces() {
let mut said: Vec<String> = Vec::new();
for verb in crate::verbs::table() {
said.push(verb.usage());
said.push(crate::verbs::help::page(verb.word).unwrap_or_default());
if let Err(refusal) = verb.envelope(Vec::new()) {
said.push(refusal);
}
}
for door in crate::verbs::doors::table() {
said.push(door.usage());
said.push(door.refused(9));
said.push(crate::verbs::help::page(door.word).unwrap_or_default());
}
let run: Vec<String> = said
.iter()
.flat_map(|text| text.lines())
.filter(|line| line.contains(" "))
.map(str::to_owned)
.collect();
assert_eq!(run, Vec::<String>::new());
}