#[cfg(feature = "test-runner")] mod group_test { use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command, HandlerGroup}; use once_cell::sync::Lazy; static LOADED_GROUP: Lazy = Lazy::new(|| { ClapCmd::group("Fruit") .description("Commands to do cool fruit things") .command( do_apple, Command::new("apple").about("do the cool apple thing"), ) .command( do_banana, Command::new("banana").about("do the cool banana thing"), ) .command( do_unload, Command::new("unload").about("unload the cool fruit group"), ) }); static UNLOADED_GROUP: Lazy = Lazy::new(|| { ClapCmd::unnamed_group().command( do_load, Command::new("load").about("load the cool fruit group"), ) }); fn do_load(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.add_group(&LOADED_GROUP.clone()); cmd.remove_group(&UNLOADED_GROUP.clone()); cmd.output("loaded"); Ok(()) } fn do_unload(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.add_group(&UNLOADED_GROUP.clone()); cmd.remove_group(&LOADED_GROUP.clone()); cmd.output("unloaded"); Ok(()) } fn do_apple(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("apple"); Ok(()) } fn do_banana(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("banana"); Ok(()) } #[test] fn groups_load_and_unload_successfully() { let mut cmd = ClapCmd::default(); cmd.add_group(&UNLOADED_GROUP); let _ = cmd.one_cmd("apple"); assert!( cmd.error.contains("unknown command"), "command was detected when it shouldn't be loaded yet", ); let _ = cmd.one_cmd("load"); assert!( cmd.output.contains("loaded"), "load command did not successfully return", ); let _ = cmd.one_cmd("apple"); assert!( !cmd.error.contains("unknown command"), "command wasn't detected after it was loaded", ); assert!( cmd.output.contains("apple"), "command didn't produce the correct output", ); let _ = cmd.one_cmd("unload"); assert!( cmd.output.contains("loaded"), "unload command did not successfully return", ); let _ = cmd.one_cmd("apple"); assert!( cmd.error.contains("unknown command"), "command was detected when it already unloaded", ); assert!( !cmd.output.contains("apple"), "command executed when it should have been unloaded", ); } } #[cfg(feature = "test-runner")] mod command_escape_test { use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command}; fn do_ping(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("pong"); Ok(()) } #[test] fn commands_with_spaces_work_correctly() { let mut cmd = ClapCmd::default(); cmd.add_command(do_ping, Command::new("do ping").about("do a ping")); let _ = cmd.one_cmd("do\\ ping"); assert!( cmd.output.contains("pong"), "command was not detected correctly", ); } } #[cfg(feature = "test-runner")] mod clap_error_test { use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command}; fn do_ping(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("pong"); Ok(()) } #[test] fn clap_errors_display_correctly() { let mut cmd = ClapCmd::default(); cmd.add_command(do_ping, Command::new("ping").about("do a ping")); let _ = cmd.one_cmd("ping -h"); assert!( cmd.output.contains("do a ping"), "help did not display correctly", ); let _ = cmd.one_cmd("ping abc"); assert!( cmd.output.contains("error"), "unknown argument did not catch correctly", ); } } #[cfg(feature = "test-runner")] mod multiple_commands_test { use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command}; fn do_bark(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("woof"); Ok(()) } fn do_meow(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("nyan"); Ok(()) } #[test] fn multiple_commands_in_one_line_work() { let mut cmd = ClapCmd::default(); cmd.add_command(do_bark, Command::new("bark").about("do a bark")); cmd.add_command(do_meow, Command::new("meow").about("do a meow")); let _ = cmd.one_cmd("bark; meow"); assert!( cmd.output.contains("woof"), "command was not detected correctly", ); assert!( cmd.output.contains("nyan"), "command was not detected correctly", ); let _ = cmd.one_cmd("bark"); assert!( cmd.output.contains("woof"), "command was not detected correctly", ); let _ = cmd.one_cmd("meow"); assert!( !cmd.output.contains("woof"), "previous output didn't clear correctly", ); assert!( cmd.output.contains("nyan"), "command was not detected correctly", ); } } //#[cfg(feature = "test-runner")] mod conditional_commands_test { use std::fmt::Display; use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command}; fn do_bark(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("woof"); Ok(()) } fn do_meow(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.output("nyan"); Ok(()) } #[derive(Debug)] struct MyError; impl Display for MyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "oops") } } impl std::error::Error for MyError {} fn do_always_errors(cmd: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult { cmd.error("oops, something bad happened"); Err(Box::new(MyError)) } #[test] fn multiple_commands_in_one_line_work() { let mut cmd = ClapCmd::default(); cmd.add_command(do_bark, Command::new("bark").about("do a bark")); cmd.add_command(do_meow, Command::new("meow").about("do a meow")); cmd.add_command(do_always_errors, Command::new("bad").about("do a error")); let _ = cmd.one_cmd("bark && meow"); assert!( cmd.output.contains("woof"), "command was not detected correctly", ); assert!( cmd.output.contains("nyan"), "command was not detected correctly", ); let _ = cmd.one_cmd("bark || meow"); assert!( cmd.output.contains("woof"), "command was not detected correctly", ); assert!( !cmd.output.contains("nyan"), "previous output didn't clear correctly", ); let _ = cmd.one_cmd("bad && bark"); assert!(cmd.error.contains("oops"), "error didn't print",); assert!( !cmd.output.contains("woof"), "and command executed after error", ); let _ = cmd.one_cmd("bad || bark"); assert!(cmd.error.contains("oops"), "error didn't print",); assert!( cmd.output.contains("woof"), "or executed correctly after error", ); let _ = cmd.one_cmd("bark || bad"); assert!( cmd.output.contains("woof"), "command successfully ran before an or", ); assert!(!cmd.error.contains("oops"), "error printed after an or",); } }