#![allow(clippy::panic)]
use super::super::verbs::{Effect, VERBS, Verb};
use super::{Invocation, LineError, parse};
fn words(line: &[&str]) -> Vec<String> {
line.iter().map(|word| (*word).to_owned()).collect()
}
#[test]
fn help_wins_over_every_verb_that_changes_something() {
for row in VERBS.iter().filter(|row| row.effect == Effect::Changes) {
for asked in ["--help", "-h"] {
assert_eq!(
parse(&words(&[row.name, asked])),
Ok(Invocation::Help(row.verb)),
"{} {asked} would run the verb",
row.name
);
}
}
assert_eq!(
parse(&words(&["install", "--help"])),
Ok(Invocation::Help(Verb::Install))
);
assert_eq!(
parse(&words(&["up", "--help"])),
Ok(Invocation::Help(Verb::Up))
);
}
#[test]
fn a_flag_value_is_not_an_address() {
let Ok(Invocation::Run(Verb::Serve, read)) =
parse(&words(&["serve", "city", "--log", "debug"]))
else {
panic!("serve city --log debug did not parse as serve");
};
assert_eq!(read.value("--log"), Some("debug"));
assert_eq!(read.positional(1).map(String::as_str), Some("city"));
assert_eq!(read.positional(2), None, "the address took the log level");
}
#[test]
fn a_short_flag_reads_as_its_long_name() {
for spelled in ["-m", "--model"] {
let line = ["dispatch", "lab/room1", "write it", spelled, "m-other"];
let Ok(Invocation::Run(Verb::Dispatch, read)) = parse(&words(&line)) else {
panic!("{line:?} did not parse as dispatch");
};
assert_eq!(read.value("--model"), Some("m-other"), "{line:?}");
assert_eq!(
read.positional(3),
None,
"{line:?}: the model id is no positional"
);
}
}
#[test]
fn a_mistyped_verb_names_the_nearest() {
assert_eq!(
parse(&words(&["stauts"])),
Err(LineError::UnknownVerb {
given: "stauts".to_owned(),
nearest: vec!["status"],
})
);
}
#[test]
fn an_unknown_flag_is_refused() {
assert!(matches!(
parse(&words(&["replay", "dir", "--jsno"])),
Err(LineError::UnknownFlag { verb: "replay", .. })
));
}
#[test]
fn every_flag_a_body_reads_passes_the_table() {
let served: &[&[&str]] = &[
&["--open"],
&["--no-open"],
&["--console"],
&["--no-console"],
&["--log", "debug"],
&["--web-dir", "dir"],
];
for verb in ["up", "serve"] {
for flag in served {
let line = [&[verb, "city"][..], flag].concat();
assert!(
matches!(parse(&words(&line)), Ok(Invocation::Run(..))),
"{line:?} is refused"
);
}
}
for flag in [&["--install"][..], &["--explain", "E1"], &["--no-color"]] {
let line = [&["doctor"][..], flag].concat();
assert!(
matches!(parse(&words(&line)), Ok(Invocation::Run(..))),
"{line:?} is refused"
);
}
}
#[test]
fn a_verb_of_two_words_is_read_from_two_words() {
let exported = parse(&words(&["playback", "export", "city", "--run", "r"]));
let helped = parse(&words(&["help", "playback", "check"]));
let alone = parse(&words(&["playback"]));
let mistyped = parse(&words(&["playback", "expot"]));
let under = vec!["playback export", "playback check"];
assert_eq!(
(
exported.map(|invocation| {
let Invocation::Run(verb, read) = invocation else {
panic!("{invocation:?} is not a run");
};
(
Some(verb),
read.positional(1).cloned(),
read.value("--run").map(str::to_owned),
)
}),
helped,
alone,
mistyped,
),
(
Ok((
Some(Verb::PlaybackExport),
Some("city".to_owned()),
Some("r".to_owned())
)),
Ok(Invocation::Help(Verb::PlaybackCheck)),
Err(LineError::UnknownVerb {
given: "playback".to_owned(),
nearest: under.clone(),
}),
Err(LineError::UnknownVerb {
given: "playback expot".to_owned(),
nearest: under,
}),
)
);
}
#[test]
fn the_words_after_two_dashes_are_not_read_as_sprawlings_own() {
let parsed = parse(&words(&["top", "--", "cargo", "--version", "--help"]));
assert!(matches!(parsed, Ok(Invocation::Run(_, _))), "{parsed:?}");
let Ok(Invocation::Run(_, read)) = parsed else {
return;
};
assert_eq!(
read.after_dashes(),
Some(&words(&["cargo", "--version", "--help"])[..])
);
}
#[test]
fn gauge_and_top_name_one_verb() {
let verb = |line: &[&str]| match parse(&words(line)) {
Ok(Invocation::Run(verb, _)) => Some(verb),
Ok(_) | Err(_) => None,
};
assert_eq!(
(verb(&["gauge"]).is_some(), verb(&["gauge"])),
(true, verb(&["top"]))
);
}