diff --git a/src/Context/GivenStepDefinitions.php b/src/Context/GivenStepDefinitions.php index 615999b7b..d4e8b5fb8 100644 --- a/src/Context/GivenStepDefinitions.php +++ b/src/Context/GivenStepDefinitions.php @@ -11,6 +11,16 @@ trait GivenStepDefinitions { /** + * Creates an empty directory. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * ... + * ``` + * + * @access public + * * @Given an empty directory */ public function given_an_empty_directory() { @@ -18,6 +28,17 @@ public function given_an_empty_directory() { } /** + * Creates or deletes a specific directory. + * + * ``` + * Scenario: My example scenario + * Given an empty foo-plugin directory + * And a non-existent bar-plugin directory + * ... + * ``` + * + * @access public + * * @Given /^an? (empty|non-existent) ([^\s]+) directory$/ */ public function given_a_specific_directory( $empty_or_nonexistent, $dir ) { @@ -49,6 +70,16 @@ public function given_a_specific_directory( $empty_or_nonexistent, $dir ) { } /** + * Clears the WP-CLI cache directory. + * + * ``` + * Scenario: My example scenario + * Given an empty cache + * ... + * ``` + * + * @access public + * * @Given an empty cache */ public function given_an_empty_cache() { @@ -56,6 +87,23 @@ public function given_an_empty_cache() { } /** + * Creates a file with the given contents. + * + * The file can be created either in the current working directory + * or in the cache directory. + * + * ``` + * Scenario: My example scenario + * Given a wp-cli.yml file: + * """ + * @foo: + * path: foo + * user: admin + * """ + * ``` + * + * @access public + * * @Given /^an? ([^\s]+) (file|cache file):$/ */ public function given_a_specific_file( $path, $type, PyStringNode $content ) { @@ -72,6 +120,16 @@ public function given_a_specific_file( $path, $type, PyStringNode $content ) { } /** + * Search and replace a string in a file using regex. + * + * ``` + * Scenario: My example scenario + * Given "Foo" replaced with "Bar" in the readme.html file + * ... + * ``` + * + * @access public + * * @Given /^"([^"]+)" replaced with "([^"]+)" in the ([^\s]+) file$/ */ public function given_string_replaced_with_string_in_a_specific_file( $search, $replace, $path ) { @@ -82,6 +140,21 @@ public function given_string_replaced_with_string_in_a_specific_file( $search, $ } /** + * Mock HTTP requests to a given URL. + * + * ``` + * Scenario: My example scenario + * Given that HTTP requests to https://api.github.com/repos/wp-cli/wp-cli/releases?per_page=100 will respond with: + * """ + * HTTP/1.1 200 + * Content-Type: application/json + * + * { "foo": "bar" } + * """ + * ``` + * + * @access public + * * @Given /^that HTTP requests to (.*?) will respond with:$/ */ public function given_a_request_to_a_url_respond_with_file( $url_or_pattern, PyStringNode $content ) { @@ -240,6 +313,16 @@ static function( \$pre, \$parsed_args, \$url ) { } /** + * Download WordPress files without installing. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * And WP files + * ``` + * + * @access public + * * @Given WP files */ public function given_wp_files() { @@ -247,6 +330,17 @@ public function given_wp_files() { } /** + * Create a wp-config.php file using `wp config create`. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * And WP files + * And wp-config.php + * ``` + * + * @access public + * * @Given wp-config.php */ public function given_wp_config_php() { @@ -254,6 +348,18 @@ public function given_wp_config_php() { } /** + * Creates an empty database. + * + * Has no effect when tests run with SQLite. + * + * ``` + * Scenario: My example scenario + * Given a database + * ... + * ``` + * + * @access public + * * @Given a database */ public function given_a_database() { @@ -261,6 +367,20 @@ public function given_a_database() { } /** + * Installs WordPress. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * ... + * + * Scenario: My other scenario + * Given a WP install + * ... + * ``` + * + * @access public + * * @Given a WP install(ation) */ public function given_a_wp_installation() { @@ -268,6 +388,20 @@ public function given_a_wp_installation() { } /** + * Installs WordPress in a given directory. + * + * ``` + * Scenario: My example scenario + * Given a WP installation in 'foo' + * ... + * + * Scenario: My other scenario + * Given a WP install in 'bar' + * ... + * ``` + * + * @access public + * * @Given a WP install(ation) in :subdir */ public function given_a_wp_installation_in_a_specific_folder( $subdir ) { @@ -275,6 +409,20 @@ public function given_a_wp_installation_in_a_specific_folder( $subdir ) { } /** + * Installs WordPress with Composer. + * + * ``` + * Scenario: My example scenario + * Given a WP installation with Composer + * ... + * + * Scenario: My other scenario + * Given a WP install with Composer + * ... + * ``` + * + * @access public + * * @Given a WP install(ation) with Composer */ public function given_a_wp_installation_with_composer() { @@ -282,6 +430,20 @@ public function given_a_wp_installation_with_composer() { } /** + * Installs WordPress with Composer and a custom vendor directory. + * + * ``` + * Scenario: My example scenario + * Given a WP installation with Composer and a custom vendor directory 'vendor-custom' + * ... + * + * Scenario: My other scenario + * Given a WP install with Composer with Composer and a custom vendor directory 'vendor-custom' + * ... + * ``` + * + * @access public + * * @Given a WP install(ation) with Composer and a custom vendor directory :vendor_directory */ public function given_a_wp_installation_with_composer_and_a_custom_vendor_folder( $vendor_directory ) { @@ -289,6 +451,22 @@ public function given_a_wp_installation_with_composer_and_a_custom_vendor_folder } /** + * Installs WordPress Multisite. + * + * Supports either subdirectory or subdomain installation. + * + * ``` + * Scenario: My example scenario + * Given a WP multisite subdomain installation + * ... + * + * Scenario: My other scenario + * Given a WP subdirectory install + * ... + * ``` + * + * @access public + * * @Given /^a WP multisite (subdirectory|subdomain)?\s?(install|installation)$/ */ public function given_a_wp_multisite_installation( $type = 'subdirectory' ) { @@ -304,6 +482,20 @@ public function given_a_wp_multisite_installation( $type = 'subdirectory' ) { } /** + * Installs and activates one or more plugins. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * And these installed and active plugins: + * """ + * akismet + * wordpress-importer + * """ + * ``` + * + * @access public + * * @Given these installed and active plugins: */ public function given_these_installed_and_active_plugins( $stream ) { @@ -314,6 +506,18 @@ public function given_these_installed_and_active_plugins( $stream ) { } /** + * Configure a custom `wp-content` directory. + * + * Defines the `WP_CONTENT_DIR`, `WP_PLUGIN_DIR`, and `WPMU_PLUGIN_DIR` constants. + * + * ``` + * Scenario: My example scenario + * Given a WP install + * And a custom wp-content directory + * ``` + * + * @access public + * * @Given a custom wp-content directory */ public function given_a_custom_wp_directory() { @@ -356,6 +560,18 @@ public function given_a_custom_wp_directory() { } /** + * Download multiple files into the given destinations. + * + * ``` + * Scenario: My example scenario + * Given download: + * | path | url | + * | {CACHE_DIR}/foo.jpg | https://example.com/foo.jpg | + * | {CACHE_DIR}/bar.png | https://example.com/another-image.png | + * ``` + * + * @access public + * * @Given download: */ public function given_a_download( TableNode $table ) { @@ -371,6 +587,20 @@ public function given_a_download( TableNode $table ) { } /** + * Store STDOUT or STDERR contents in a variable. + * + * ``` + * Scenario: My example scenario + * When I run `wp package path` + * Then save STDOUT as {PACKAGE_PATH} + * + * Scenario: My other scenario + * When I run `wp core download` + * Then save STDOUT 'Downloading WordPress ([\d\.]+)' as {VERSION} + * ``` + * + * @access public + * * @Given /^save (STDOUT|STDERR) ([\'].+[^\'])?\s?as \{(\w+)\}$/ */ public function given_saved_stdout_stderr( $stream, $output_filter, $key ) { @@ -390,6 +620,16 @@ public function given_saved_stdout_stderr( $stream, $output_filter, $key ) { } /** + * Build a new WP-CLI Phar file with a given version. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * And a new Phar with version "2.11.0" + * ``` + * + * @access public + * * @Given /^a new Phar with (?:the same version|version "([^"]+)")$/ */ public function given_a_new_phar_with_a_specific_version( $version = 'same' ) { @@ -397,6 +637,20 @@ public function given_a_new_phar_with_a_specific_version( $version = 'same' ) { } /** + * Download a specific WP-CLI Phar version from GitHub. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * And a downloaded Phar with version "2.11.0" + * + * Scenario: My other scenario + * Given an empty directory + * And a downloaded Phar with the same version + * ``` + * + * @access public + * * @Given /^a downloaded Phar with (?:the same version|version "([^"]+)")$/ */ public function given_a_downloaded_phar_with_a_specific_version( $version = 'same' ) { @@ -404,6 +658,16 @@ public function given_a_downloaded_phar_with_a_specific_version( $version = 'sam } /** + * Stores the contents of the given file in a variable. + * + * ``` + * Scenario: My example scenario + * Given a WP installation with Composer + * And save the {RUN_DIR}/composer.json file as {COMPOSER_JSON} + * ``` + * + * @access public + * * @Given /^save the (.+) file ([\'].+[^\'])?as \{(\w+)\}$/ */ public function given_saved_a_specific_file( $filepath, $output_filter, $key ) { @@ -423,6 +687,16 @@ public function given_saved_a_specific_file( $filepath, $output_filter, $key ) { } /** + * Modify wp-config.php to set `WP_CONTENT_DIR` to an empty string. + * + * ``` + * Scenario: My example scenario + * Given a WP install + * And a misconfigured WP_CONTENT_DIR constant directory + * ``` + * + * @access public + * * @Given a misconfigured WP_CONTENT_DIR constant directory */ public function given_a_misconfigured_wp_content_dir_constant_directory() { @@ -439,6 +713,16 @@ public function given_a_misconfigured_wp_content_dir_constant_directory() { } /** + * Add `wp-cli/wp-cli` as a Composer dependency. + * + * ``` + * Scenario: My example scenario + * Given a WP installation with Composer + * And a dependency on current wp-cli + * ``` + * + * @access public + * * @Given a dependency on current wp-cli */ public function given_a_dependency_on_wp_cli() { @@ -446,6 +730,16 @@ public function given_a_dependency_on_wp_cli() { } /** + * Start a PHP built-in web server in the current directory. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * And a PHP built-in web server + * ``` + * + * @access public + * * @Given a PHP built-in web server */ public function given_a_php_built_in_web_server() { @@ -453,6 +747,16 @@ public function given_a_php_built_in_web_server() { } /** + * Start a PHP built-in web server in the given subdirectory. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * And a PHP built-in web server to serve 'WordPress' + * ``` + * + * @access public + * * @Given a PHP built-in web server to serve :subdir */ public function given_a_php_built_in_web_server_to_serve_a_specific_folder( $subdir ) { diff --git a/src/Context/ThenStepDefinitions.php b/src/Context/ThenStepDefinitions.php index 7ec476b1a..6a2cca92b 100644 --- a/src/Context/ThenStepDefinitions.php +++ b/src/Context/ThenStepDefinitions.php @@ -13,6 +13,17 @@ trait ThenStepDefinitions { use Support; /** + * Expect a specific exit code of the previous command. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * When I try `wp plugin install` + * Then the return code should be 1 + * ``` + * + * @access public + * * @Then /^the return code should( not)? be (\d+)$/ */ public function then_the_return_code_should_be( $not, $return_code ) { @@ -25,6 +36,26 @@ public function then_the_return_code_should_be( $not, $return_code ) { } /** + * Check the contents of STDOUT or STDERR. + * + * ``` + * Scenario: My example scenario + * Given an empty directory + * When I run `wp core is-installed` + * Then STDOUT should be empty + * + * Scenario: My other scenario + * Given a WP install + * When I run `wp plugin install akismet` + * Then STDOUT should contain: + * """ + * Plugin installed successfully. + * """ + * And STDERR should be empty + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should( strictly)? (be|contain|not contain):$/ */ public function then_stdout_stderr_should_contain( $stream, $strictly, $action, PyStringNode $expected ) { @@ -37,6 +68,17 @@ public function then_stdout_stderr_should_contain( $stream, $strictly, $action, } /** + * Expect STDOUT or STDERR to be a numeric value. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * When I run `wp db size --size_format=b` + * Then STDOUT should be a number + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should be a number$/ */ public function then_stdout_stderr_should_be_a_number( $stream ) { @@ -47,6 +89,17 @@ public function then_stdout_stderr_should_be_a_number( $stream ) { } /** + * Expect STDOUT or STDERR to not be a numeric value. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * When I run `wp post list --format=json` + * Then STDOUT should not be a number + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should not be a number$/ */ public function then_stdout_stderr_should_not_be_a_number( $stream ) { @@ -57,6 +110,20 @@ public function then_stdout_stderr_should_not_be_a_number( $stream ) { } /** + * Expect STDOUT to be a table containing the given rows. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * When I run `wp config list --fields=name,type` + * Then STDOUT should be a table containing rows: + * | name | type | + * | DB_NAME | constant | + * | DB_USER | constant | + * ``` + * + * @access public + * * @Then /^STDOUT should be a table containing rows:$/ */ public function then_stdout_should_be_a_table_containing_rows( TableNode $expected ) { @@ -72,6 +139,27 @@ public function then_stdout_should_be_a_table_containing_rows( TableNode $expect } /** + * Expect STDOUT to end with a table containing the given rows. + * + * Useful when the table is preceded by some other output. + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * When I run `wp search-replace foo bar --report-changed-only` + * Then STDOUT should contain: + * """ + * Success: Made 3 replacements. + * """ + * And STDOUT should end with a table containing rows: + * | Table | Column | Replacements | Type | + * | wp_options | option_value | 1 | PHP | + * | wp_postmeta | meta_value | 1 | SQL | + * | wp_posts | post_title | 1 | SQL | + * ``` + * + * @access public + * * @Then /^STDOUT should end with a table containing rows:$/ */ public function then_stdout_should_end_with_a_table_containing_rows( TableNode $expected ) { @@ -93,6 +181,21 @@ public function then_stdout_should_end_with_a_table_containing_rows( TableNode $ } /** + * Expect valid JSON output in STDOUT. + * + * ``` + * Scenario: My example scenario + * When I run `wp post meta get 1 meta-key --format=json` + * Then STDOUT should be JSON containing: + * """ + * { + * "foo": "baz" + * } + * """ + * ``` + * + * @access public + * * @Then /^STDOUT should be JSON containing:$/ */ public function then_stdout_should_be_json_containing( PyStringNode $expected ) { @@ -105,6 +208,21 @@ public function then_stdout_should_be_json_containing( PyStringNode $expected ) } /** + * Expect valid JSON array output in STDOUT. + * + * Errors when some items are missing from the expected array. + * + * ``` + * Scenario: My example scenario + * When I run `wp plugin list --field=name --format=json` + * Then STDOUT should be a JSON array containing: + * """ + * ["akismet", "hello-dolly"] + * """ + * ``` + * + * @access public + * * @Then /^STDOUT should be a JSON array containing:$/ */ public function then_stdout_should_be_a_json_array_containing( PyStringNode $expected ) { @@ -121,6 +239,18 @@ public function then_stdout_should_be_a_json_array_containing( PyStringNode $exp } /** + * Expect STDOUT to be CSV containing certain values. + * + * ``` + * Scenario: My example scenario + * When I run `wp term list post_tag --fields=name,slug --format=csv` + * Then STDOUT should be CSV containing: + * | name | slug | + * | Test term | test | + * ``` + * + * @access public + * * @Then /^STDOUT should be CSV containing:$/ */ public function then_stdout_should_be_csv_containing( TableNode $expected ) { @@ -139,6 +269,21 @@ public function then_stdout_should_be_csv_containing( TableNode $expected ) { } /** + * Expect STDOUT to be YAML containig certain content. + * + * ``` + * Scenario: My example scenario + * When I run `wp cli alias list` + * Then STDOUT should be YAML containing: + * """ + * @all: Run command against every registered alias. + * @foo: + * path: {TEST_DIR}/foo + * """ + * ``` + * + * @access public + * * @Then /^STDOUT should be YAML containing:$/ */ public function then_stdout_should_be_yaml_containing( PyStringNode $expected ) { @@ -151,6 +296,17 @@ public function then_stdout_should_be_yaml_containing( PyStringNode $expected ) } /** + * Expect STDOUT or STDERR to be empty. + * + * ``` + * Scenario: My other scenario + * Given a WP install + * When I run `wp plugin install akismet` + * Then STDERR should be empty + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should be empty$/ */ public function then_stdout_stderr_should_be_empty( $stream ) { @@ -163,6 +319,16 @@ public function then_stdout_stderr_should_be_empty( $stream ) { } /** + * Expect STDOUT or STDERR not to be empty. + * + * ``` + * Scenario: My example scenario + * When I run `wp user create examplejane jane@example.com` + * Then STDOUT should not be empty + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should not be empty$/ */ public function then_stdout_stderr_should_not_be_empty( $stream ) { @@ -175,6 +341,17 @@ public function then_stdout_stderr_should_not_be_empty( $stream ) { } /** + * Expect STDOUT or STDERR to be a version string comparing to the given version. + * + * ``` + * Scenario: My example scenario + * Given a WP install + * When I run `wp core version + * Then STDOUT should be a version string >= 6.8 + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should be a version string (<|<=|>|>=|==|=|!=|<>) ([+\w.{}-]+)$/ */ public function then_stdout_stderr_should_be_a_specific_version_string( $stream, $operator, $goal_ver ) { @@ -186,6 +363,26 @@ public function then_stdout_stderr_should_be_a_specific_version_string( $stream, } /** + * Expect a certain file or directory to (not) exist or (not) contain certain contents. + * + * ``` + * Scenario: My example scenario + * When I run `wp core download` + * Then the wp-settings.php file should exist + * And the wp-content directory should exist + * And the {RUN_DIR} directory should contain: + * """ + * index.php + * license.txt + * """ + * And the wp-config.php file should contain: + * """ + * That's all, stop editing! Happy publishing. + * """ + * ``` + * + * @access public + * * @Then /^the (.+) (file|directory) should( strictly)? (exist|not exist|be:|contain:|not contain:)$/ */ public function then_a_specific_file_folder_should_exist( $path, $type, $strictly, $action, $expected = null ) { @@ -196,7 +393,7 @@ public function then_a_specific_file_folder_should_exist( $path, $type, $strictl $path = $this->variables['RUN_DIR'] . "/$path"; } - $exists = function ( $path ) use ( $type ) { + $exists = static function ( $path ) use ( $type ) { // Clear the stat cache for the path first to avoid // potentially inaccurate results when files change outside of PHP. // See https://www.php.net/manual/en/function.clearstatcache.php @@ -240,6 +437,16 @@ public function then_a_specific_file_folder_should_exist( $path, $type, $strictl } /** + * Match file contents against a regex. + * + * ``` + * Scenario: My example scenario + * When I run `wp scaffold plugin hello-world` + * Then the contents of the wp-content/plugins/hello-world/languages/hello-world.pot file should match /X-Generator:\s/ + * ``` + * + * @access public + * * @Then /^the contents of the (.+) file should( not)? match (((\/.+\/)|(#.+#))([a-z]+)?)$/ */ public function then_the_contents_of_a_specific_file_should_match( $path, $not, $expected ) { @@ -259,6 +466,16 @@ public function then_the_contents_of_a_specific_file_should_match( $path, $not, } /** + * Match STDOUT or STDERR against a regex. + * + * ``` + * Scenario: My example scenario + * When I run `wp dist-archive wp-content/plugins/hello-world` + * Then STDOUT should match /^Success: Created hello-world.0.1.0.zip \(Size: \d+(?:\.\d*)? [a-zA-Z]{1,3}\)$/ + * ``` + * + * @access public + * * @Then /^(STDOUT|STDERR) should( not)? match (((\/.+\/)|(#.+#))([a-z]+)?)$/ */ public function then_stdout_stderr_should_match_a_string( $stream, $not, $expected ) { @@ -273,6 +490,16 @@ public function then_stdout_stderr_should_match_a_string( $stream, $not, $expect } /** + * Expect an email to be sent (or not). + * + * ``` + * Scenario: My example scenario + * When I run `wp user reset-password 1` + * Then an email should be sent + * ``` + * + * @access public + * * @Then /^an email should (be sent|not be sent)$/ */ public function then_an_email_should_be_sent( $expected ) { @@ -286,6 +513,17 @@ public function then_an_email_should_be_sent( $expected ) { } /** + * Expect the HTTP status code for visiting `http://localhost:8080`. + * + * ``` + * Scenario: My example scenario + * Given a WP installation with Composer + * And a PHP built-in web server to serve 'WordPress' + * Then the HTTP status code should be 200 + * ``` + * + * @access public + * * @Then the HTTP status code should be :code */ public function then_the_http_status_code_should_be( $return_code ) { diff --git a/src/Context/WhenStepDefinitions.php b/src/Context/WhenStepDefinitions.php index a727e8c7f..eaa14a141 100644 --- a/src/Context/WhenStepDefinitions.php +++ b/src/Context/WhenStepDefinitions.php @@ -7,7 +7,6 @@ trait WhenStepDefinitions { - public function wpcli_tests_invoke_proc( $proc, $mode ) { $map = array( 'run' => 'run_check_stderr', @@ -25,6 +24,17 @@ public function wpcli_tests_capture_email_sends( $stdout ) { } /** + * Launch a given command in the background. + * + * ``` + * Scenario: My example scenario + * Given a WP install + * And I launch in the background `wp server --host=localhost --port=8181` + * ... + * ``` + * + * @access public + * * @When /^I launch in the background `([^`]+)`$/ */ public function when_i_launch_in_the_background( $cmd ) { @@ -32,6 +42,31 @@ public function when_i_launch_in_the_background( $cmd ) { } /** + * Run or try a given command. + * + * `run` expects an exit code 0, whereas `try` allows for non-zero exit codes. + * + * So if using `run` and the command errors, the step will fail. + * + * ``` + * Scenario: My example scenario + * When I run `wp core version` + * Then STDOUT should contain: + * """ + * 6.8 + * """ + * + * Scenario: My other scenario + * When I try `wp i18n make-pot foo bar/baz.pot` + * Then STDERR should contain: + * """ + * Error: Not a valid source directory. + * """ + * And the return code should be 1 + * ``` + * + * @access public + * * @When /^I (run|try) `([^`]+)`$/ */ public function when_i_run( $mode, $cmd ) { @@ -41,6 +76,21 @@ public function when_i_run( $mode, $cmd ) { } /** + * Run or try a given command in a subdirectory. + * + * `run` expects an exit code 0, whereas `try` allows for non-zero exit codes. + * + * ``` + * Scenario: My example scenario + * When I run `wp core is-installed` + * Then STDOUT should be empty + * + * When I run `wp core is-installed` from 'foo/wp-content' + * Then STDOUT should be empty + * ``` + * + * @access public + * * @When /^I (run|try) `([^`]+)` from '([^\s]+)'$/ */ public function when_i_run_from_a_subfolder( $mode, $cmd, $subdir ) { @@ -50,6 +100,27 @@ public function when_i_run_from_a_subfolder( $mode, $cmd, $subdir ) { } /** + * Run or try the previous command again. + * + * `run` expects an exit code 0, whereas `try` allows for non-zero exit codes. + * + * ``` + * Scenario: My example scenario + * When I run `wp site option update admin_user_id 1` + * Then STDOUT should contain: + * """ + * Success: Updated 'admin_user_id' site option. + * """ + * + * When I run the previous command again + * Then STDOUT should contain: + * """ + * Success: Value passed for 'admin_user_id' site option is unchanged. + * """ + * ``` + * + * @access public + * * @When /^I (run|try) the previous command again$/ */ public function when_i_run_the_previous_command_again( $mode ) {