Call this PR "Raid" cause it's squashin bugs! (#843)
* tests: adds tests for default values triggering conditional requirements
* fix: fixes a bug where default values should have triggered a conditional requirement but didnt
Closes #831
* tests: adds tests for missing conditional requirements in usage string of errors
* fix: fixes a bug where conditionally required args werent appearing in errors
* tests: adds tests for completion generators
* tests: adds tests for completions with binaries names that have underscores
* fix: fixes a bug where ZSH completions would panic if the binary name had an underscore in it
Closes #581
* fix: fixes bash completions for commands that have an underscore in the name
Closes #581
* chore: fix the category for crates.io
* docs(Macros): adds a warning about changing values in Cargo.toml not triggering a rebuild automatically
Closes #838
* fix(Completions): fixes a bug where global args weren't included in the generated completion scripts
Closes #841
* fix: fixes a println->debugln typo
* chore: increase version
diff --git a/tests/require.rs b/tests/require.rs
index 987c45a..f8eb410 100644
--- a/tests/require.rs
+++ b/tests/require.rs
@@ -14,11 +14,18 @@
For more information try --help";
+static COND_REQ_IN_USAGE: &'static str = "error: The following required arguments were not provided:
+ --output <output>
+
+USAGE:
+ test --target <target> --input <input> --output <output>
+
+For more information try --help";
+
#[test]
fn flag_required() {
let result = App::new("flag_required")
- .arg(Arg::from_usage("-f, --flag 'some flag'")
- .requires("color"))
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("color"))
.arg(Arg::from_usage("-c, --color 'third flag'"))
.get_matches_from_safe(vec!["", "-f"]);
assert!(result.is_err());
@@ -29,8 +36,7 @@
#[test]
fn flag_required_2() {
let m = App::new("flag_required")
- .arg(Arg::from_usage("-f, --flag 'some flag'")
- .requires("color"))
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("color"))
.arg(Arg::from_usage("-c, --color 'third flag'"))
.get_matches_from(vec!["", "-f", "-c"]);
assert!(m.is_present("color"));
@@ -40,8 +46,7 @@
#[test]
fn option_required() {
let result = App::new("option_required")
- .arg(Arg::from_usage("-f [flag] 'some flag'")
- .requires("color"))
+ .arg(Arg::from_usage("-f [flag] 'some flag'").requires("color"))
.arg(Arg::from_usage("-c [color] 'third flag'"))
.get_matches_from_safe(vec!["", "-f", "val"]);
assert!(result.is_err());
@@ -52,8 +57,7 @@
#[test]
fn option_required_2() {
let m = App::new("option_required")
- .arg(Arg::from_usage("-f [flag] 'some flag'")
- .requires("c"))
+ .arg(Arg::from_usage("-f [flag] 'some flag'").requires("c"))
.arg(Arg::from_usage("-c [color] 'third flag'"))
.get_matches_from(vec!["", "-f", "val", "-c", "other_val"]);
assert!(m.is_present("c"));
@@ -136,8 +140,7 @@
#[test]
fn arg_require_group() {
let result = App::new("arg_require_group")
- .arg(Arg::from_usage("-f, --flag 'some flag'")
- .requires("gr"))
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
.group(ArgGroup::with_name("gr")
.arg("some")
.arg("other"))
@@ -152,8 +155,7 @@
#[test]
fn arg_require_group_2() {
let m = App::new("arg_require_group")
- .arg(Arg::from_usage("-f, --flag 'some flag'")
- .requires("gr"))
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
.group(ArgGroup::with_name("gr")
.arg("some")
.arg("other"))
@@ -168,8 +170,7 @@
#[test]
fn arg_require_group_3() {
let m = App::new("arg_require_group")
- .arg(Arg::from_usage("-f, --flag 'some flag'")
- .requires("gr"))
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
.group(ArgGroup::with_name("gr")
.arg("some")
.arg("other"))
@@ -197,7 +198,7 @@
.arg(Arg::from_usage("-p, --port=[SERVER_PORT] 'NTP server port'")
.default_value("123"))
.get_matches_from_safe(vec!["test", "--list"]);
- assert!(m.is_ok());
+ assert!(m.is_ok());
}
#[test]
@@ -207,11 +208,8 @@
.required_unless("dbg")
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
- .get_matches_from_safe(vec![
- "unlesstest", "--debug"
- ]);
+ .arg(Arg::with_name("dbg").long("debug"))
+ .get_matches_from_safe(vec!["unlesstest", "--debug"]);
assert!(res.is_ok());
let m = res.unwrap();
@@ -226,11 +224,8 @@
.required_unless("dbg")
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
- .get_matches_from_safe(vec![
- "unlesstest"
- ]);
+ .arg(Arg::with_name("dbg").long("debug"))
+ .get_matches_from_safe(vec!["unlesstest"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -245,14 +240,11 @@
.required_unless_all(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessall", "--debug", "-i", "file"
- ]);
+ .get_matches_from_safe(vec!["unlessall", "--debug", "-i", "file"]);
assert!(res.is_ok());
let m = res.unwrap();
@@ -268,14 +260,11 @@
.required_unless_all(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessall", "--debug"
- ]);
+ .get_matches_from_safe(vec!["unlessall", "--debug"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -290,14 +279,11 @@
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessone", "--debug"
- ]);
+ .get_matches_from_safe(vec!["unlessone", "--debug"]);
assert!(res.is_ok());
let m = res.unwrap();
@@ -314,14 +300,11 @@
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessone", "-i", "file"
- ]);
+ .get_matches_from_safe(vec!["unlessone", "-i", "file"]);
assert!(res.is_ok());
let m = res.unwrap();
@@ -336,14 +319,11 @@
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessone", "--debug"
- ]);
+ .get_matches_from_safe(vec!["unlessone", "--debug"]);
assert!(res.is_ok());
let m = res.unwrap();
@@ -359,14 +339,11 @@
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("dbg")
- .long("debug"))
+ .arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
- .get_matches_from_safe(vec![
- "unlessone"
- ]);
+ .get_matches_from_safe(vec!["unlessone"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -386,11 +363,8 @@
.requires_if("my.cfg", "extra")
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("extra")
- .long("extra"))
- .get_matches_from_safe(vec![
- "unlessone", "--config=my.cfg"
- ]);
+ .arg(Arg::with_name("extra").long("extra"))
+ .get_matches_from_safe(vec!["unlessone", "--config=my.cfg"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -400,19 +374,12 @@
fn requires_if_present_mult() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
- .requires_ifs(&[
- ("my.cfg", "extra"),
- ("other.cfg", "other"),
- ])
+ .requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("extra")
- .long("extra"))
- .arg(Arg::with_name("other")
- .long("other"))
- .get_matches_from_safe(vec![
- "unlessone", "--config=other.cfg"
- ]);
+ .arg(Arg::with_name("extra").long("extra"))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from_safe(vec!["unlessone", "--config=other.cfg"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -422,19 +389,12 @@
fn requires_if_present_mult_pass() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
- .requires_ifs(&[
- ("my.cfg", "extra"),
- ("other.cfg", "other"),
- ])
+ .requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("extra")
- .long("extra"))
- .arg(Arg::with_name("other")
- .long("other"))
- .get_matches_from_safe(vec![
- "unlessone", "--config=some.cfg"
- ]);
+ .arg(Arg::with_name("extra").long("extra"))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from_safe(vec!["unlessone", "--config=some.cfg"]);
assert!(res.is_ok());
// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -447,11 +407,8 @@
.requires_if("my.cfg", "extra")
.takes_value(true)
.long("config"))
- .arg(Arg::with_name("extra")
- .long("extra"))
- .get_matches_from_safe(vec![
- "unlessone",
- ]);
+ .arg(Arg::with_name("extra").long("extra"))
+ .get_matches_from_safe(vec!["unlessone"]);
assert!(res.is_ok());
}
@@ -468,9 +425,7 @@
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
- .get_matches_from_safe(vec![
- "ri", "--extra", "val", "--config", "my.cfg"
- ]);
+ .get_matches_from_safe(vec!["ri", "--extra", "val", "--config", "my.cfg"]);
assert!(res.is_ok());
}
@@ -485,15 +440,39 @@
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
- .get_matches_from_safe(vec![
- "ri", "--extra", "val"
- ]);
+ .get_matches_from_safe(vec!["ri", "--extra", "val"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}
#[test]
+fn required_if_val_present_fail_error_output() {
+ let app = App::new("Test app")
+ .version("1.0")
+ .author("F0x06")
+ .about("Arg test")
+ .arg(Arg::with_name("target")
+ .takes_value(true)
+ .required(true)
+ .possible_values(&["file", "stdout"])
+ .long("target"))
+ .arg(Arg::with_name("input")
+ .takes_value(true)
+ .required(true)
+ .long("input"))
+ .arg(Arg::with_name("output")
+ .takes_value(true)
+ .required_if("target", "file")
+ .long("output"));
+
+ assert!(test::compare_output(app,
+ "test --input somepath --target file",
+ COND_REQ_IN_USAGE,
+ true));
+}
+
+#[test]
fn required_if_wrong_val() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
@@ -503,9 +482,7 @@
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
- .get_matches_from_safe(vec![
- "ri", "--extra", "other"
- ]);
+ .get_matches_from_safe(vec!["ri", "--extra", "other"]);
assert!(res.is_ok());
}
@@ -514,10 +491,7 @@
fn required_ifs_val_present_pass() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
- .required_ifs(&[
- ("extra", "val"),
- ("option", "spec")
- ])
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
.takes_value(true)
.long("config"))
.arg(Arg::with_name("option")
@@ -526,9 +500,7 @@
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
- .get_matches_from_safe(vec![
- "ri", "--option", "spec", "--config", "my.cfg"
- ]);
+ .get_matches_from_safe(vec!["ri", "--option", "spec", "--config", "my.cfg"]);
assert!(res.is_ok());
// assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -538,10 +510,7 @@
fn required_ifs_val_present_fail() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
- .required_ifs(&[
- ("extra", "val"),
- ("option", "spec")
- ])
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
@@ -550,9 +519,7 @@
.arg(Arg::with_name("option")
.takes_value(true)
.long("option"))
- .get_matches_from_safe(vec![
- "ri", "--option", "spec"
- ]);
+ .get_matches_from_safe(vec!["ri", "--option", "spec"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
@@ -562,10 +529,7 @@
fn required_ifs_wrong_val() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
- .required_ifs(&[
- ("extra", "val"),
- ("option", "spec")
- ])
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
@@ -574,9 +538,7 @@
.arg(Arg::with_name("option")
.takes_value(true)
.long("option"))
- .get_matches_from_safe(vec![
- "ri", "--option", "other"
- ]);
+ .get_matches_from_safe(vec!["ri", "--option", "other"]);
assert!(res.is_ok());
}
@@ -585,10 +547,7 @@
fn required_ifs_wrong_val_mult_fail() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
- .required_ifs(&[
- ("extra", "val"),
- ("option", "spec")
- ])
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
@@ -597,9 +556,7 @@
.arg(Arg::with_name("option")
.takes_value(true)
.long("option"))
- .get_matches_from_safe(vec![
- "ri", "--extra", "other", "--option", "spec"
- ]);
+ .get_matches_from_safe(vec!["ri", "--extra", "other", "--option", "spec"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);