Feature: WP-CLI Commands Scenario: Registered WP-CLI commands Given an empty directory When I run `wp help --help` Then STDOUT should contain: """ wp help [...] """ Scenario: Invalid class is specified for a command Given an empty directory And a custom-cmd.php file: """ * : An awesome message to display * * @when before_wp_load */ $foo = function( $args ) { WP_CLI::success( $args[0] ); }; WP_CLI::add_command( 'foo', $foo ); """ When I run `wp --require=custom-cmd.php help` Then STDOUT should contain: """ foo """ When I run `wp --require=custom-cmd.php help foo` Then STDOUT should contain: """ My awesome closure command """ When I try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: """ Success: bar """ Scenario: Use a function as a command Given an empty directory And a custom-cmd.php file: """ * : An awesome message to display * * @when before_wp_load */ function foo( $args ) { WP_CLI::success( $args[0] ); } WP_CLI::add_command( 'foo', 'foo' ); """ When I run `wp --require=custom-cmd.php help` Then STDOUT should contain: """ foo """ When I run `wp --require=custom-cmd.php help foo` Then STDOUT should contain: """ My awesome function command """ When I try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: """ Success: bar """ Scenario: Use a class method as a command Given an empty directory And a custom-cmd.php file: """ prefix = $prefix; } /** * My awesome class method command * * * : An awesome message to display * * @when before_wp_load */ function foo( $args ) { WP_CLI::success( $this->prefix . ':' . $args[0] ); } } $foo = new Foo_Class( 'boo' ); WP_CLI::add_command( 'foo', array( $foo, 'foo' ) ); """ When I run `wp --require=custom-cmd.php help` Then STDOUT should contain: """ foo """ When I run `wp --require=custom-cmd.php help foo` Then STDOUT should contain: """ My awesome class method command """ When I try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: """ Success: boo:bar """ Scenario: Use a class method as a command Given an empty directory And a custom-cmd.php file: """ * : An awesome message to display * * @when before_wp_load */ function foo( $args ) { WP_CLI::success( $args[0] ); } } WP_CLI::add_command( 'foo', array( 'Foo_Class', 'foo' ) ); """ When I run `wp --require=custom-cmd.php help` Then STDOUT should contain: """ foo """ When I run `wp --require=custom-cmd.php help foo` Then STDOUT should contain: """ My awesome class method command """ When I try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: """ Success: bar """ Scenario: Use class with __invoke() passed as object Given an empty directory And a custom-cmd.php file: """ message = $message; } /** * My awesome class method command * * @when before_wp_load */ function __invoke( $args ) { WP_CLI::success( $this->message ); } } $foo = new Foo_Class( 'bar' ); WP_CLI::add_command( 'instantiated-command', $foo ); """ When I run `wp --require=custom-cmd.php instantiated-command` Then STDOUT should contain: """ bar """ And STDERR should be empty Scenario: Use an invalid class method as a command Given an empty directory And a custom-cmd.php file: """ * : An awesome message to display * * @when before_wp_load */ function foo( $args ) { WP_CLI::success( $args[0] ); } } $foo = new Foo_Class; WP_CLI::add_command( 'bar', array( $foo, 'bar' ) ); """ When I try `wp --require=custom-cmd.php bar` Then STDERR should contain: """ Error: Callable ["Foo_Class","bar"] does not exist, and cannot be registered as `wp bar`. """ Scenario: Register a synopsis for a given command Given an empty directory And a custom-cmd.php file: """ 'My awesome function command', 'when' => 'before_wp_load', 'synopsis' => array( array( 'type' => 'positional', 'name' => 'message', 'description' => 'An awesome message to display', 'optional' => false, 'options' => array( 'hello', 'goodbye' ), ), array( 'type' => 'assoc', 'name' => 'apple', 'description' => 'A type of fruit.', 'optional' => false, ), array( 'type' => 'assoc', 'name' => 'meal', 'description' => 'A type of meal.', 'optional' => true, 'default' => 'breakfast', 'options' => array( 'breakfast', 'lunch', 'dinner' ), ), ), ) ); """ And a wp-cli.yml file: """ require: - custom-cmd.php """ When I try `wp foo` Then STDOUT should contain: """ usage: wp foo --apple= [--meal=] """ And STDERR should be empty And the return code should be 1 When I run `wp help foo` Then STDOUT should contain: """ My awesome function command """ And STDOUT should contain: """ SYNOPSIS """ And STDOUT should contain: """ wp foo --apple= [--meal=] """ And STDOUT should contain: """ OPTIONS """ And STDOUT should contain: """ An awesome message to display --- options: - hello - goodbye --- """ And STDOUT should contain: """ [--meal=] A type of meal. --- default: breakfast options: - breakfast - lunch - dinner --- """ When I try `wp foo nana --apple=fuji` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ When I try `wp foo hello --apple=fuji --meal=snack` Then STDERR should contain: """ Invalid value specified for 'meal' (A type of meal.) """ When I try `wp foo hello --apple=fuji --meal=breakfast,lunch,dinner` Then STDERR should be empty When I try `wp foo hello --apple=fuji --meal=breakfast,snack,dinner` Then STDERR should contain: """ Invalid value specified for 'meal' (A type of meal.) """ When I run `wp foo hello --apple=fuji` Then STDOUT should be: """ Message is: hello Success: breakfast """ When I run `wp foo hello --apple=fuji --meal=dinner` Then STDOUT should be: """ Message is: hello Success: dinner """ Scenario: Register a synopsis that supports multiple positional arguments Given an empty directory And a test-cmd.php file: """ 'before_wp_load', 'synopsis' => array( array( 'type' => 'positional', 'name' => 'arg', 'repeating' => true, ), ), )); """ And a wp-cli.yml file: """ require: - test-cmd.php """ When I run `wp foo bar` Then STDOUT should be: """ 1 """ When I run `wp foo bar burrito` Then STDOUT should be: """ 2 """ Scenario: Register a synopsis that requires a flag Given an empty directory And a test-cmd.php file: """ 'before_wp_load', 'synopsis' => array( array( 'type' => 'flag', 'name' => 'honk', 'optional' => true, ), ), )); """ And a wp-cli.yml file: """ require: - test-cmd.php """ When I run `wp foo` Then STDOUT should be: """ nohonk """ When I run `wp foo --honk` Then STDOUT should be: """ honked """ When I run `wp foo --honk=1` Then STDOUT should be: """ honked """ When I run `wp foo --no-honk` Then STDOUT should be: """ nohonk """ When I run `wp foo --honk=0` Then STDOUT should be: """ nohonk """ # Note treats "false" as true. When I run `wp foo --honk=false` Then STDOUT should be: """ honked """ Scenario: Register a longdesc for a given command Given an empty directory And a custom-cmd.php file: """ 'My awesome function command', 'when' => 'before_wp_load', 'longdesc' => '## EXAMPLES' . PHP_EOL . PHP_EOL . ' # Run the custom foo command', ) ); """ And a wp-cli.yml file: """ require: - custom-cmd.php """ When I run `wp help foo` Then STDOUT should contain: """ NAME wp foo DESCRIPTION My awesome function command SYNOPSIS wp foo EXAMPLES # Run the custom foo command GLOBAL PARAMETERS """ # With synopsis, appended. Given a hello-command.php file: """ 'Prints a greeting.', 'synopsis' => array( array( 'type' => 'positional', 'name' => 'name', 'description' => 'Name of person to greet.', 'optional' => false, 'repeating' => false, ), array( 'type' => 'assoc', 'name' => 'type', 'optional' => true, 'default' => 'success', 'options' => array( 'success', 'error' ), ), array( 'type' => 'flag', 'name' => 'honk', 'optional' => true, ), ), 'when' => 'after_wp_load', 'longdesc' => "\r\n## EXAMPLES\n\n# Say hello to Newman\nwp example hello Newman\nSuccess: Hello, Newman!", ) ); """ When I run `wp --require=hello-command.php help example hello` Then STDOUT should contain: """ NAME wp example hello DESCRIPTION Prints a greeting. SYNOPSIS wp example hello [--type=] [--honk] OPTIONS Name of person to greet. [--type=] --- default: success options: - success - error --- [--honk] EXAMPLES # Say hello to Newman wp example hello Newman Success: Hello, Newman! GLOBAL PARAMETERS """ Given a test-reordering.php file: """ 'Test reordering of arguments.', 'synopsis' => [ [ 'type' => 'flag', 'name' => 'my-flag', 'description' => 'Flag something', ], [ 'type' => 'assoc', 'name' => 'my-assoc', 'description' => 'Assoc something', 'options' => [ 'a', 'b', 'c' ], 'default' => 'a', ], [ 'type' => 'positional', 'name' => 'my-positional', 'description' => 'Positional something', 'optional' => false, 'repeating' => false, ], ], 'when' => 'before_wp_load', ] ); """ When I run `wp --require=test-reordering.php help test-reordering` Then STDOUT should contain: """ NAME wp test-reordering DESCRIPTION Test reordering of arguments. SYNOPSIS wp test-reordering --my-assoc= --my-flag OPTIONS Positional something --my-assoc= Assoc something --- default: a options: - a - b - c --- --my-flag Flag something """ Scenario: Register a command with default and accepted arguments. Given an empty directory And a test-cmd.php file: """ ] * : This is the bar argument. * --- * default: burrito * --- * * [...] * : This is where you buy burritos. * --- * options: * - left_coast_siesta * - cha cha cha * --- * * [--burrito=] * : This is the burrito argument. * --- * options: * - beans * - veggies * --- * * @when before_wp_load */ $foo = function( $args, $assoc_args ) { $out = array( 'bar' => isset( $args[0] ) ? $args[0] : '', 'shop' => isset( $args[1] ) ? $args[1] : '', 'burrito' => isset( $assoc_args['burrito'] ) ? $assoc_args['burrito'] : '', ); WP_CLI::print_value( $out, array( 'format' => 'yaml' ) ); }; WP_CLI::add_command( 'foo', $foo ); """ When I run `wp --require=test-cmd.php foo --help` Then STDOUT should contain: """ [] This is the bar argument. --- default: burrito --- """ And STDOUT should contain: """ [--burrito=] This is the burrito argument. --- options: - beans - veggies --- """ When I run `wp --require=test-cmd.php foo` Then STDOUT should be YAML containing: """ bar: burrito shop: burrito: """ And STDERR should be empty When I run `wp --require=test-cmd.php foo ''` Then STDOUT should be YAML containing: """ bar: shop: burrito: """ And STDERR should be empty When I run `wp --require=test-cmd.php foo apple --burrito=veggies` Then STDOUT should be YAML containing: """ bar: apple shop: burrito: veggies """ And STDERR should be empty When I try `wp --require=test-cmd.php foo apple --burrito=meat` Then STDERR should contain: """ Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ When I try `wp --require=test-cmd.php foo apple --burrito=''` Then STDERR should contain: """ Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ When I try `wp --require=test-cmd.php foo apple taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ When I try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ When I run `wp --require=test-cmd.php foo apple 'cha cha cha'` Then STDOUT should be YAML containing: """ bar: apple shop: cha cha cha burrito: """ And STDERR should be empty Scenario: Register a command with default and accepted arguments, part two Given an empty directory And a test-cmd.php file: """ ] * : This is the bar argument. * --- * options: * - beans * - veggies * --- * * @when before_wp_load */ $foo = function( $args, $assoc_args ) { $out = array( 'burrito' => isset( $args[0] ) ? $args[0] : '', ); WP_CLI::print_value( $out, array( 'format' => 'yaml' ) ); }; WP_CLI::add_command( 'foo', $foo ); """ When I run `wp --require=test-cmd.php foo` Then STDOUT should be YAML containing: """ burrito: """ And STDERR should be empty When I run `wp --require=test-cmd.php foo beans` Then STDOUT should be YAML containing: """ burrito: beans """ And STDERR should be empty When I try `wp --require=test-cmd.php foo apple` Then STDERR should be: """ Error: Invalid value specified for positional arg. """ Scenario: Removing a subcommand should remove it from the index Given an empty directory And a remove-comment.php file: """ remove_subcommand( 'comment' ); } ); """ When I run `wp` Then STDOUT should contain: """ Creates, updates, deletes, and moderates comments. """ When I run `wp --require=remove-comment.php` Then STDOUT should not contain: """ Creates, updates, deletes, and moderates comments. """ Scenario: before_invoke should call subcommands Given an empty directory And a call-invoke.php file: """ function() { WP_CLI::success( 'before invoke' ); }, 'after_invoke' => function() { WP_CLI::success( 'after invoke' ); }); WP_CLI::add_command( 'before invoke', $before_invoke, $before_invoke_args ); WP_CLI::add_command( 'before-invoke', $before_invoke, $before_invoke_args ); """ When I run `wp --require=call-invoke.php before invoke` Then STDOUT should contain: """ Success: before invoke Success: Invoked Success: after invoke """ When I run `wp --require=call-invoke.php before-invoke` Then STDOUT should contain: """ Success: before invoke Success: Invoked Success: after invoke """ Scenario: Default arguments should respect wp-cli.yml Given a WP installation And a wp-cli.yml file: """ post list: format: count """ When I run `wp post list` Then STDOUT should be a number Scenario: Use class passed as object Given an empty directory And a custom-cmd.php file: """ message = $message; } /** * My awesome class method command * * @when before_wp_load */ function message( $args ) { WP_CLI::success( $this->message ); } } $foo = new Foo_Class( 'bar' ); WP_CLI::add_command( 'instantiated-command', $foo ); """ When I run `wp --require=custom-cmd.php instantiated-command message` Then STDOUT should contain: """ bar """ And STDERR should be empty Scenario: WP-CLI suggests matching commands when user entry contains typos Given a WP installation When I try `wp clu` Then STDERR should contain: """ Did you mean 'cli'? """ When I try `wp cli nfo` Then STDERR should contain: """ Did you mean 'info'? """ When I try `wp cli beyondlevenshteinthreshold` Then STDERR should not contain: """ Did you mean """ Scenario: WP-CLI suggests matching parameters when user entry contains typos Given an empty directory When I try `wp cli info --quie` Then STDERR should contain: """ Did you mean '--quiet'? """ When I try `wp cli info --forma=json` Then STDERR should contain: """ Did you mean '--format'? """ Scenario: Adding a command can be aborted through the hooks system Given an empty directory And a abort-add-command.php file: """ abort( 'Testing hooks.' ); } ); WP_CLI::add_command( 'test-command-1', function () {} ); WP_CLI::add_command( 'test-command-2', function () {} ); """ When I try `wp --require=abort-add-command.php` Then STDOUT should contain: """ test-command-1 """ And STDOUT should not contain: """ test-command-2 """ And STDERR should be: """ Warning: Aborting the addition of the command 'test-command-2' with reason: Testing hooks.. """ And the return code should be 0 Scenario: Adding a command can depend on a previous command having been added before Given an empty directory And a add-dependent-command.php file: """