1use clap::Args; 2use clap::Parser; 3 4#[test] 5fn test_standalone_long_generates_kebab_case() { 6 #[derive(Parser, Debug, PartialEq)] 7 #[allow(non_snake_case)] 8 struct Opt { 9 #[arg(long)] 10 FOO_OPTION: bool, 11 } 12 13 assert_eq!( 14 Opt { FOO_OPTION: true }, 15 Opt::try_parse_from(["test", "--foo-option"]).unwrap() 16 ); 17} 18 19#[test] 20fn test_custom_long_overwrites_default_name() { 21 #[derive(Parser, Debug, PartialEq)] 22 struct Opt { 23 #[arg(long = "foo")] 24 foo_option: bool, 25 } 26 27 assert_eq!( 28 Opt { foo_option: true }, 29 Opt::try_parse_from(["test", "--foo"]).unwrap() 30 ); 31} 32 33#[test] 34fn test_standalone_long_uses_previous_defined_custom_name() { 35 #[derive(Parser, Debug, PartialEq)] 36 struct Opt { 37 #[arg(id = "foo", long)] 38 foo_option: bool, 39 } 40 41 assert_eq!( 42 Opt { foo_option: true }, 43 Opt::try_parse_from(["test", "--foo"]).unwrap() 44 ); 45} 46 47#[test] 48fn test_standalone_long_ignores_afterwards_defined_custom_name() { 49 #[derive(Parser, Debug, PartialEq)] 50 struct Opt { 51 #[arg(long, id = "foo")] 52 foo_option: bool, 53 } 54 55 assert_eq!( 56 Opt { foo_option: true }, 57 Opt::try_parse_from(["test", "--foo-option"]).unwrap() 58 ); 59} 60 61#[test] 62fn test_standalone_long_uses_previous_defined_custom_id() { 63 #[derive(Parser, Debug, PartialEq)] 64 struct Opt { 65 #[arg(id = "foo", long)] 66 foo_option: bool, 67 } 68 69 assert_eq!( 70 Opt { foo_option: true }, 71 Opt::try_parse_from(["test", "--foo"]).unwrap() 72 ); 73} 74 75#[test] 76fn test_standalone_long_ignores_afterwards_defined_custom_id() { 77 #[derive(Parser, Debug, PartialEq)] 78 struct Opt { 79 #[arg(long, id = "foo")] 80 foo_option: bool, 81 } 82 83 assert_eq!( 84 Opt { foo_option: true }, 85 Opt::try_parse_from(["test", "--foo-option"]).unwrap() 86 ); 87} 88 89#[test] 90fn test_standalone_short_generates_kebab_case() { 91 #[derive(Parser, Debug, PartialEq)] 92 #[allow(non_snake_case)] 93 struct Opt { 94 #[arg(short)] 95 FOO_OPTION: bool, 96 } 97 98 assert_eq!( 99 Opt { FOO_OPTION: true }, 100 Opt::try_parse_from(["test", "-f"]).unwrap() 101 ); 102} 103 104#[test] 105fn test_custom_short_overwrites_default_name() { 106 #[derive(Parser, Debug, PartialEq)] 107 struct Opt { 108 #[arg(short = 'o')] 109 foo_option: bool, 110 } 111 112 assert_eq!( 113 Opt { foo_option: true }, 114 Opt::try_parse_from(["test", "-o"]).unwrap() 115 ); 116} 117 118#[test] 119fn test_standalone_short_uses_previous_defined_custom_name() { 120 #[derive(Parser, Debug, PartialEq)] 121 struct Opt { 122 #[arg(id = "option", short)] 123 foo_option: bool, 124 } 125 126 assert_eq!( 127 Opt { foo_option: true }, 128 Opt::try_parse_from(["test", "-o"]).unwrap() 129 ); 130} 131 132#[test] 133fn test_standalone_short_ignores_afterwards_defined_custom_name() { 134 #[derive(Parser, Debug, PartialEq)] 135 struct Opt { 136 #[arg(short, id = "option")] 137 foo_option: bool, 138 } 139 140 assert_eq!( 141 Opt { foo_option: true }, 142 Opt::try_parse_from(["test", "-f"]).unwrap() 143 ); 144} 145 146#[test] 147fn test_standalone_short_uses_previous_defined_custom_id() { 148 #[derive(Parser, Debug, PartialEq)] 149 struct Opt { 150 #[arg(id = "option", short)] 151 foo_option: bool, 152 } 153 154 assert_eq!( 155 Opt { foo_option: true }, 156 Opt::try_parse_from(["test", "-o"]).unwrap() 157 ); 158} 159 160#[test] 161fn test_standalone_short_ignores_afterwards_defined_custom_id() { 162 #[derive(Parser, Debug, PartialEq)] 163 struct Opt { 164 #[arg(short, id = "option")] 165 foo_option: bool, 166 } 167 168 assert_eq!( 169 Opt { foo_option: true }, 170 Opt::try_parse_from(["test", "-f"]).unwrap() 171 ); 172} 173 174#[test] 175fn test_standalone_long_uses_previous_defined_casing() { 176 #[derive(Parser, Debug, PartialEq)] 177 struct Opt { 178 #[arg(rename_all = "screaming_snake", long)] 179 foo_option: bool, 180 } 181 182 assert_eq!( 183 Opt { foo_option: true }, 184 Opt::try_parse_from(["test", "--FOO_OPTION"]).unwrap() 185 ); 186} 187 188#[test] 189fn test_standalone_short_uses_previous_defined_casing() { 190 #[derive(Parser, Debug, PartialEq)] 191 struct Opt { 192 #[arg(rename_all = "screaming_snake", short)] 193 foo_option: bool, 194 } 195 196 assert_eq!( 197 Opt { foo_option: true }, 198 Opt::try_parse_from(["test", "-F"]).unwrap() 199 ); 200} 201 202#[test] 203fn test_standalone_long_works_with_verbatim_casing() { 204 #[derive(Parser, Debug, PartialEq)] 205 #[allow(non_snake_case)] 206 struct Opt { 207 #[arg(rename_all = "verbatim", long)] 208 _fOO_oPtiON: bool, 209 } 210 211 assert_eq!( 212 Opt { _fOO_oPtiON: true }, 213 Opt::try_parse_from(["test", "--_fOO_oPtiON"]).unwrap() 214 ); 215} 216 217#[test] 218fn test_standalone_short_works_with_verbatim_casing() { 219 #[derive(Parser, Debug, PartialEq)] 220 struct Opt { 221 #[arg(rename_all = "verbatim", short)] 222 _foo: bool, 223 } 224 225 assert_eq!( 226 Opt { _foo: true }, 227 Opt::try_parse_from(["test", "-_"]).unwrap() 228 ); 229} 230 231#[test] 232fn test_rename_all_is_propagated_from_struct_to_fields() { 233 #[derive(Parser, Debug, PartialEq)] 234 #[command(rename_all = "screaming_snake")] 235 struct Opt { 236 #[arg(long)] 237 foo: bool, 238 } 239 240 assert_eq!( 241 Opt { foo: true }, 242 Opt::try_parse_from(["test", "--FOO"]).unwrap() 243 ); 244} 245 246#[test] 247fn test_rename_all_is_not_propagated_from_struct_into_flattened() { 248 #[derive(Parser, Debug, PartialEq)] 249 #[command(rename_all = "screaming_snake")] 250 struct Opt { 251 #[command(flatten)] 252 foo: Foo, 253 } 254 255 #[derive(Args, Debug, PartialEq)] 256 struct Foo { 257 #[arg(long)] 258 foo: bool, 259 } 260 261 assert_eq!( 262 Opt { 263 foo: Foo { foo: true } 264 }, 265 Opt::try_parse_from(["test", "--foo"]).unwrap() 266 ); 267} 268 269#[test] 270fn test_lower_is_renamed() { 271 #[derive(Parser, Debug, PartialEq)] 272 struct Opt { 273 #[arg(rename_all = "lower", long)] 274 foo_option: bool, 275 } 276 277 assert_eq!( 278 Opt { foo_option: true }, 279 Opt::try_parse_from(["test", "--foooption"]).unwrap() 280 ); 281} 282 283#[test] 284fn test_upper_is_renamed() { 285 #[derive(Parser, Debug, PartialEq)] 286 struct Opt { 287 #[arg(rename_all = "upper", long)] 288 foo_option: bool, 289 } 290 291 assert_eq!( 292 Opt { foo_option: true }, 293 Opt::try_parse_from(["test", "--FOOOPTION"]).unwrap() 294 ); 295} 296 297#[test] 298fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() { 299 #[derive(Parser, Debug, PartialEq)] 300 enum Opt { 301 Command { foo: u32 }, 302 } 303 304 assert_eq!( 305 Opt::Command { foo: 0 }, 306 Opt::try_parse_from(["test", "command", "0"]).unwrap() 307 ); 308} 309 310#[test] 311fn test_multi_word_enum_variant_is_renamed() { 312 #[derive(Parser, Debug, PartialEq)] 313 enum Opt { 314 FirstCommand { foo: u32 }, 315 } 316 317 assert_eq!( 318 Opt::FirstCommand { foo: 0 }, 319 Opt::try_parse_from(["test", "first-command", "0"]).unwrap() 320 ); 321} 322 323#[test] 324fn test_rename_all_is_not_propagated_from_struct_into_subcommand() { 325 #[derive(Parser, Debug, PartialEq)] 326 #[command(rename_all = "screaming_snake")] 327 struct Opt { 328 #[command(subcommand)] 329 foo: Foo, 330 } 331 332 #[derive(Parser, Debug, PartialEq)] 333 enum Foo { 334 Command { 335 #[arg(long)] 336 foo: bool, 337 }, 338 } 339 340 assert_eq!( 341 Opt { 342 foo: Foo::Command { foo: true } 343 }, 344 Opt::try_parse_from(["test", "command", "--foo"]).unwrap() 345 ); 346} 347 348#[test] 349fn test_rename_all_is_propagated_from_enum_to_variants() { 350 #[derive(Parser, Debug, PartialEq)] 351 #[command(rename_all = "screaming_snake")] 352 enum Opt { 353 FirstVariant, 354 SecondVariant { 355 #[arg(long)] 356 foo: String, 357 }, 358 } 359 360 assert_eq!( 361 Opt::FirstVariant, 362 Opt::try_parse_from(["test", "FIRST_VARIANT"]).unwrap() 363 ); 364} 365 366#[test] 367fn test_rename_all_is_propagated_from_enum_to_variant_fields() { 368 #[derive(Parser, Debug, PartialEq)] 369 #[command(rename_all = "screaming_snake")] 370 enum Opt { 371 FirstVariant, 372 SecondVariant { 373 #[arg(long)] 374 foo: String, 375 }, 376 } 377 378 assert_eq!( 379 Opt::SecondVariant { 380 foo: "value".into() 381 }, 382 Opt::try_parse_from(["test", "SECOND_VARIANT", "--FOO", "value"]).unwrap() 383 ); 384} 385 386#[test] 387fn test_rename_all_is_propagation_can_be_overridden() { 388 #[derive(Parser, Debug, PartialEq)] 389 #[command(rename_all = "screaming_snake")] 390 enum Opt { 391 #[command(rename_all = "kebab_case")] 392 FirstVariant { 393 #[arg(long)] 394 foo_option: bool, 395 }, 396 SecondVariant { 397 #[arg(rename_all = "kebab_case", long)] 398 foo_option: bool, 399 }, 400 } 401 402 assert_eq!( 403 Opt::FirstVariant { foo_option: true }, 404 Opt::try_parse_from(["test", "first-variant", "--foo-option"]).unwrap() 405 ); 406 407 assert_eq!( 408 Opt::SecondVariant { foo_option: true }, 409 Opt::try_parse_from(["test", "SECOND_VARIANT", "--foo-option"]).unwrap() 410 ); 411} 412