use super::support::test_app;
use crate::app::{HelpTopic, Mode};
#[test]
fn every_topic_round_trips_through_its_name() {
for &topic in HelpTopic::ALL {
assert_eq!(
HelpTopic::from_arg(topic.arg_name()),
Some(topic),
"{topic:?} does not parse back from its own name"
);
}
}
#[test]
fn topic_names_are_unique() {
let mut names: Vec<&str> = HelpTopic::ALL.iter().map(|t| t.arg_name()).collect();
let before = names.len();
names.sort_unstable();
names.dedup();
assert_eq!(
before,
names.len(),
"two topics answer to the same name, so one of them is unreachable: \
{names:?}"
);
}
#[test]
fn topic_names_are_case_insensitive() {
assert_eq!(HelpTopic::from_arg("SHELL"), Some(HelpTopic::Shell));
assert_eq!(HelpTopic::from_arg("Shell"), Some(HelpTopic::Shell));
}
#[test]
fn an_unknown_topic_is_not_a_topic() {
assert_eq!(HelpTopic::from_arg("shel"), None);
assert_eq!(HelpTopic::from_arg(""), None);
}
#[test]
fn help_shell_opens_the_shell_topic() {
let mut app = test_app();
app.execute_command("help shell");
assert_eq!(app.mode, Mode::Help);
assert_eq!(app.help.topic, HelpTopic::Shell);
}
#[test]
fn an_unknown_topic_reports_instead_of_guessing() {
let mut app = test_app();
app.execute_command("help shel");
assert_eq!(
app.mode,
Mode::Normal,
"a typo'd topic opened the help screen anyway"
);
let msg = app.error_message.clone().unwrap_or_default();
assert!(
msg.contains("shel") && msg.contains("shell"),
"the message should name what was typed and what is available: {msg:?}"
);
super::support::assert_no_run_on_spaces(&msg);
}
#[test]
fn bare_help_still_infers_the_topic() {
let mut app = test_app();
app.execute_command("help");
assert_eq!(app.mode, Mode::Help);
assert_eq!(app.help.topic, HelpTopic::Global);
}
#[test]
fn every_help_topic_variant_is_in_all() {
let src = std::fs::read_to_string("src/app/types.rs").expect("src/app/types.rs");
let file = syn::parse_file(&src).expect("types.rs must parse");
let variants: Vec<String> = file
.items
.iter()
.find_map(|item| match item {
syn::Item::Enum(e) if e.ident == "HelpTopic" => {
Some(e.variants.iter().map(|v| v.ident.to_string()).collect())
}
_ => None,
})
.expect("could not find `enum HelpTopic` in src/app/types.rs");
assert!(
variants.len() >= 5,
"found only {} HelpTopic variants — the enum walk is broken",
variants.len()
);
let reachable: Vec<String> = HelpTopic::ALL.iter().map(|t| format!("{t:?}")).collect();
let missing: Vec<&String> = variants.iter().filter(|v| !reachable.contains(v)).collect();
assert!(
missing.is_empty(),
"HelpTopic::{missing:?} are not in `HelpTopic::ALL`, so `:help <name>` \
cannot reach them and they render only if something assigns the \
variant directly. That is how `Shell` sat unreachable — add them to \
ALL and give each an `arg_name`."
);
}