clap/tests/macros.rs
Ed Page 9b23a09f7a fix(help): Don't rely on ALL CAPS for headers
I see them fulfilling two roles
- A form of bolding
- As a callback to their placeholder in usage

However, it is a bit of an unpolished look and no other CLI seems to do
it.  This looks a bit more proefessional.  We have colored help for
formatting and I think the sections relation to usage will be clear
enough.
2022-08-26 10:21:18 -05:00

398 lines
14 KiB
Rust

mod arg {
#[test]
fn name_explicit() {
let arg = clap::arg!(foo: --bar <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
#[test]
fn name_from_long() {
let arg = clap::arg!(--bar <NUM>);
assert_eq!(arg.get_id(), "bar");
assert_eq!(arg.get_long(), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
#[test]
fn name_from_value() {
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_long(), None);
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
#[test]
#[should_panic]
fn name_none_fails() {
clap::arg!("Help");
}
#[test]
#[should_panic]
fn short_only_fails() {
clap::arg!(-b);
}
#[test]
fn short() {
let arg = clap::arg!(foo: -b);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b');
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b ...);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b "How to use it");
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
fn short_and_long() {
let arg = clap::arg!(foo: -b --hello);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b' --hello);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b --hello ...);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b --hello "How to use it");
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
fn short_help() {
let arg = clap::arg!(help: -b);
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
let mut cmd = clap::Command::new("cmd")
.disable_help_flag(true)
.arg(clap::arg!(help: -b).action(clap::ArgAction::Help));
cmd.build();
let arg = cmd
.get_arguments()
.find(|arg| arg.get_id() == "help")
.unwrap();
assert!(matches!(arg.get_action(), clap::ArgAction::Help));
}
#[test]
fn long_help() {
let arg = clap::arg!(-'?' - -help);
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
let mut cmd = clap::Command::new("cmd")
.disable_help_flag(true)
.arg(clap::arg!(-'?' - -help).action(clap::ArgAction::Help));
cmd.build();
let arg = cmd
.get_arguments()
.find(|arg| arg.get_id() == "help")
.unwrap();
assert!(matches!(arg.get_action(), clap::ArgAction::Help));
}
#[test]
fn short_version() {
let arg = clap::arg!(version: -b);
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
let mut cmd = clap::Command::new("cmd")
.disable_version_flag(true)
.version("1.0.0")
.arg(clap::arg!(version: -b).action(clap::ArgAction::Version));
cmd.build();
let arg = cmd
.get_arguments()
.find(|arg| arg.get_id() == "version")
.unwrap();
assert!(matches!(arg.get_action(), clap::ArgAction::Version));
}
#[test]
fn long_version() {
let arg = clap::arg!(-'?' - -version);
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
let mut cmd = clap::Command::new("cmd")
.disable_version_flag(true)
.version("1.0.0")
.arg(clap::arg!(-'?' - -version).action(clap::ArgAction::Version));
cmd.build();
let arg = cmd
.get_arguments()
.find(|arg| arg.get_id() == "version")
.unwrap();
assert!(matches!(arg.get_action(), clap::ArgAction::Version));
}
#[test]
fn short_with_value() {
let arg = clap::arg!(foo: -b <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -'b' <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b <NUM> ...);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: -b <NUM> "How to use it");
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
fn positional() {
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!([NUM]);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(foo: <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM> ...);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), Some((1..).into()));
assert!(arg.is_required_set());
assert_eq!(arg.get_help().map(|s| s.to_string()), None);
let arg = clap::arg!(<NUM> "How to use it");
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(
arg.get_help().map(|s| s.to_string()),
Some("How to use it".to_owned())
);
}
#[test]
fn optional_value() {
let mut cmd = clap::Command::new("test").arg(clap::arg!(port: -p [NUM]));
let r = cmd.try_get_matches_from_mut(["test", "-p42"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.contains_id("port"));
assert_eq!(m.get_one::<String>("port").unwrap(), "42");
let r = cmd.try_get_matches_from_mut(["test", "-p"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.contains_id("port"));
assert!(m.get_one::<String>("port").is_none());
let r = cmd.try_get_matches_from_mut(["test", "-p", "24", "-p", "42"]);
assert!(r.is_ok(), "{}", r.unwrap_err());
let m = r.unwrap();
assert!(m.contains_id("port"));
assert_eq!(m.get_one::<String>("port").unwrap(), "42");
let mut help = Vec::new();
cmd.write_help(&mut help).unwrap();
const HELP: &str = "\
test
Usage:
test [OPTIONS]
Options:
-p [<NUM>]
-h, --help Print help information
";
snapbox::assert_eq(HELP, help);
}
}
mod arg_impl {
#[test]
fn string_ident() {
let expected = "one";
let actual = clap::arg_impl! { @string one };
assert_eq!(actual, expected);
}
#[test]
fn string_literal() {
let expected = "one";
let actual = clap::arg_impl! { @string "one" };
assert_eq!(actual, expected);
}
#[test]
fn char_ident() {
let expected = 'o';
let actual = clap::arg_impl! { @char o };
assert_eq!(actual, expected);
}
#[test]
fn char_literal() {
let expected = 'o';
let actual = clap::arg_impl! { @char 'o' };
assert_eq!(actual, expected);
}
#[test]
// allow double quoted dashed arg name in square brackets (e.g ["some-arg"])
fn arg_name_dashed() {
let arg = clap::arg!(["some-arg"] "some arg");
assert_eq!(arg, clap::Arg::new("some-arg").help("some arg"));
let m = clap::Command::new("flag")
.arg(arg)
.try_get_matches_from(vec!["", "some-val"])
.unwrap();
assert_eq!(m.get_one::<String>("some-arg").unwrap(), "some-val");
}
#[test]
// allow double quoted dashed arg value in triangle brackets (e.g <"some-val">)
// test in combination with short argument name (e.g. -v)
fn arg_value_dashed_with_short_arg() {
let arg = clap::arg!(-a <"some-val"> "some arg");
assert_eq!(
arg,
clap::Arg::new("some-val")
.short('a')
.long("arg")
.value_name("some-val")
);
let m = clap::Command::new("cmd")
.arg(arg)
.try_get_matches_from(vec!["", "-a", "val"])
.unwrap();
assert_eq!(m.get_one::<String>("some-val").unwrap(), "val");
}
#[test]
// allow double quoted dashed arg value in triangle brackets (e.g <"some-val">)
// test in combination with long argument name (e.g. --value)
fn arg_value_dashed_with_long_arg() {
let arg = clap::arg!(-a --arg <"some-val"> "some arg");
assert_eq!(
arg,
clap::Arg::new("arg")
.short('a')
.long("arg")
.value_name("some-val")
);
let m = clap::Command::new("cmd")
.arg(arg)
.try_get_matches_from(vec!["", "--arg", "some-val"])
.unwrap();
assert_eq!(m.get_one::<String>("arg").unwrap(), "some-val");
}
}