1use super::utils; 2 3use clap::{arg, error::Error, error::ErrorKind, value_parser, Arg, Command}; 4 5#[track_caller] 6fn assert_error<F: clap::error::ErrorFormatter>( 7 err: Error<F>, 8 expected_kind: ErrorKind, 9 expected_output: &str, 10 stderr: bool, 11) { 12 let actual_output = err.to_string(); 13 assert_eq!( 14 stderr, 15 err.use_stderr(), 16 "Should Use STDERR failed. Should be {} but is {}", 17 stderr, 18 err.use_stderr() 19 ); 20 assert_eq!(expected_kind, err.kind()); 21 utils::assert_eq(expected_output, actual_output) 22} 23 24#[test] 25fn app_error() { 26 static MESSAGE: &str = "error: failed for mysterious reasons 27 28Usage: test [OPTIONS] --all 29 30For more information, try '--help'. 31"; 32 let cmd = Command::new("test") 33 .arg( 34 Arg::new("all") 35 .short('a') 36 .long("all") 37 .required(true) 38 .action(clap::ArgAction::SetTrue) 39 .help("Also do versioning for private crates (will not be published)"), 40 ) 41 .arg( 42 Arg::new("exact") 43 .long("exact") 44 .help("Specify inter dependency version numbers exactly with `=`"), 45 ) 46 .arg( 47 Arg::new("no_git_commit") 48 .long("no-git-commit") 49 .help("Do not commit version changes"), 50 ) 51 .arg( 52 Arg::new("no_git_push") 53 .long("no-git-push") 54 .help("Do not push generated commit and tags to git remote"), 55 ); 56 let mut cmd = cmd; 57 let expected_kind = ErrorKind::InvalidValue; 58 let err = cmd.error(expected_kind, "failed for mysterious reasons"); 59 assert_error(err, expected_kind, MESSAGE, true); 60} 61 62#[test] 63fn value_validation_has_newline() { 64 let res = Command::new("test") 65 .arg( 66 arg!(<PORT>) 67 .value_parser(value_parser!(usize)) 68 .help("Network port to use"), 69 ) 70 .try_get_matches_from(["test", "foo"]); 71 72 assert!(res.is_err()); 73 let err = res.unwrap_err(); 74 assert!( 75 err.to_string().ends_with('\n'), 76 "Errors should have a trailing newline, got {:?}", 77 err.to_string() 78 ); 79} 80 81#[test] 82fn kind_prints_help() { 83 let cmd = Command::new("test"); 84 let res = cmd 85 .try_get_matches_from(["test", "--help"]) 86 .map_err(|e| e.apply::<clap::error::KindFormatter>()); 87 assert!(res.is_err()); 88 let err = res.unwrap_err(); 89 let expected_kind = ErrorKind::DisplayHelp; 90 static MESSAGE: &str = "\ 91Usage: test 92 93Options: 94 -h, --help Print help 95"; 96 assert_error(err, expected_kind, MESSAGE, false); 97} 98 99#[test] 100fn kind_formats_validation_error() { 101 let cmd = Command::new("test"); 102 let res = cmd 103 .try_get_matches_from(["test", "unused"]) 104 .map_err(|e| e.apply::<clap::error::KindFormatter>()); 105 assert!(res.is_err()); 106 let err = res.unwrap_err(); 107 let expected_kind = ErrorKind::UnknownArgument; 108 static MESSAGE: &str = "\ 109error: unexpected argument found 110"; 111 assert_error(err, expected_kind, MESSAGE, true); 112} 113 114#[test] 115#[cfg(feature = "error-context")] 116fn rich_formats_validation_error() { 117 let cmd = Command::new("test"); 118 let res = cmd.try_get_matches_from(["test", "unused"]); 119 assert!(res.is_err()); 120 let err = res.unwrap_err(); 121 let expected_kind = ErrorKind::UnknownArgument; 122 static MESSAGE: &str = "\ 123error: unexpected argument 'unused' found 124 125Usage: test 126 127For more information, try '--help'. 128"; 129 assert_error(err, expected_kind, MESSAGE, true); 130} 131 132#[test] 133#[cfg(feature = "error-context")] 134fn suggest_trailing() { 135 let cmd = Command::new("rg").arg(arg!([PATTERN])); 136 137 let res = cmd.try_get_matches_from(["rg", "--foo"]); 138 assert!(res.is_err()); 139 let err = res.unwrap_err(); 140 let expected_kind = ErrorKind::UnknownArgument; 141 static MESSAGE: &str = "\ 142error: unexpected argument '--foo' found 143 144 note: to pass '--foo' as a value, use '-- --foo' 145 146Usage: rg [PATTERN] 147 148For more information, try '--help'. 149"; 150 assert_error(err, expected_kind, MESSAGE, true); 151} 152 153#[test] 154#[cfg(feature = "error-context")] 155fn trailing_already_in_use() { 156 let cmd = Command::new("rg").arg(arg!([PATTERN])); 157 158 let res = cmd.try_get_matches_from(["rg", "--", "--foo", "--foo"]); 159 assert!(res.is_err()); 160 let err = res.unwrap_err(); 161 let expected_kind = ErrorKind::UnknownArgument; 162 static MESSAGE: &str = "\ 163error: unexpected argument '--foo' found 164 165Usage: rg [PATTERN] 166 167For more information, try '--help'. 168"; 169 assert_error(err, expected_kind, MESSAGE, true); 170} 171 172#[test] 173#[cfg(feature = "error-context")] 174fn cant_use_trailing() { 175 let cmd = Command::new("test"); 176 177 let res = cmd.try_get_matches_from(["test", "--foo"]); 178 assert!(res.is_err()); 179 let err = res.unwrap_err(); 180 let expected_kind = ErrorKind::UnknownArgument; 181 static MESSAGE: &str = "\ 182error: unexpected argument '--foo' found 183 184Usage: test 185 186For more information, try '--help'. 187"; 188 assert_error(err, expected_kind, MESSAGE, true); 189} 190