Skip to content

Commit 30e1202

Browse files
committed
Update testing framework.
1 parent 80ddc81 commit 30e1202

File tree

5 files changed

+140
-9
lines changed

5 files changed

+140
-9
lines changed

features/bootstrap/FeatureContext.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
if ( ! empty( $composer->autoload->files ) ) {
2020
$contents = 'require:' . PHP_EOL;
2121
foreach( $composer->autoload->files as $file ) {
22-
$contents .= ' - ' . dirname( dirname( dirname( __FILE__ ) ) ) . '/' . $file;
22+
$contents .= ' - ' . dirname( dirname( dirname( __FILE__ ) ) ) . '/' . $file . PHP_EOL;
2323
}
2424
@mkdir( sys_get_temp_dir() . '/wp-cli-package-test/' );
2525
$project_config = sys_get_temp_dir() . '/wp-cli-package-test/config.yml';
@@ -59,9 +59,10 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface {
5959
*/
6060
private static function get_process_env_variables() {
6161
// Ensure we're using the expected `wp` binary
62-
$bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . "/../../bin" );
62+
$bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . '/../../bin' );
63+
$vendor_dir = realpath( __DIR__ . '/../../vendor/bin' );
6364
$env = array(
64-
'PATH' => $bin_dir . ':' . getenv( 'PATH' ),
65+
'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ),
6566
'BEHAT_RUN' => 1,
6667
'HOME' => '/tmp/wp-cli-home',
6768
);
@@ -178,6 +179,9 @@ public static function create_cache_dir() {
178179
* @param array $parameters context parameters (set them up through behat.yml)
179180
*/
180181
public function __construct( array $parameters ) {
182+
if ( getenv( 'WP_CLI_TEST_DBHOST' ) ) {
183+
self::$db_settings['dbhost'] = getenv( 'WP_CLI_TEST_DBHOST' );
184+
}
181185
$this->drop_db();
182186
$this->set_cache_dir();
183187
$this->variables['CORE_CONFIG_SETTINGS'] = Utils\assoc_args_to_str( self::$db_settings );
@@ -215,9 +219,21 @@ public function create_run_dir() {
215219
public function build_phar( $version = 'same' ) {
216220
$this->variables['PHAR_PATH'] = $this->variables['RUN_DIR'] . '/' . uniqid( "wp-cli-build-", TRUE ) . '.phar';
217221

222+
// Test running against WP-CLI proper
223+
$make_phar_path = __DIR__ . '/../../utils/make-phar.php';
224+
if ( ! file_exists( $make_phar_path ) ) {
225+
// Test running against a package installed as a WP-CLI dependency
226+
// WP-CLI installed as a project dependency
227+
$make_phar_path = __DIR__ . '/../../../../../utils/make-phar.php';
228+
if ( ! file_exists( $make_phar_path ) ) {
229+
// WP-CLI as a dependency of this project
230+
$make_phar_path = __DIR__ . '/../../vendor/wp-cli/wp-cli/utils/make-phar.php';
231+
}
232+
}
233+
218234
$this->proc( Utils\esc_cmd(
219235
'php -dphar.readonly=0 %1$s %2$s --version=%3$s && chmod +x %2$s',
220-
__DIR__ . '/../../utils/make-phar.php',
236+
$make_phar_path,
221237
$this->variables['PHAR_PATH'],
222238
$version
223239
) )->run_check();
@@ -315,7 +331,8 @@ public function download_wp( $subdir = '' ) {
315331

316332
public function create_config( $subdir = '' ) {
317333
$params = self::$db_settings;
318-
$params['dbprefix'] = $subdir ?: 'wp_';
334+
// Replaces all characters that are not alphanumeric or an underscore into an underscore.
335+
$params['dbprefix'] = $subdir ? preg_replace( '#[^a-zA-Z\_0-9]#', '_', $subdir ) : 'wp_';
319336

320337
$params['skip-salts'] = true;
321338
$this->proc( 'wp core config', $params, $subdir )->run_check();

features/bootstrap/utils.php

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use \Composer\Semver\Comparator;
88
use \Composer\Semver\Semver;
9+
use \WP_CLI;
910
use \WP_CLI\Dispatcher;
1011
use \WP_CLI\Iterators\Transform;
1112

@@ -34,7 +35,11 @@ function extract_from_phar( $path ) {
3435

3536
function load_dependencies() {
3637
if ( inside_phar() ) {
37-
require WP_CLI_ROOT . '/vendor/autoload.php';
38+
if ( file_exists( WP_CLI_ROOT . '/vendor/autoload.php' ) ) {
39+
require WP_CLI_ROOT . '/vendor/autoload.php';
40+
} elseif ( file_exists( dirname( dirname( WP_CLI_ROOT ) ) . '/autoload.php' ) ) {
41+
require dirname( dirname( WP_CLI_ROOT ) ) . '/autoload.php';
42+
}
3843
return;
3944
}
4045

@@ -762,3 +767,76 @@ function parse_ssh_url( $url, $component = -1 ) {
762767
return $bits;
763768
}
764769
}
770+
771+
/**
772+
* Report the results of the same operation against multiple resources.
773+
*
774+
* @access public
775+
* @category Input
776+
*
777+
* @param string $noun Resource being affected (e.g. plugin)
778+
* @param string $verb Type of action happening to the noun (e.g. activate)
779+
* @param integer $total Total number of resource being affected.
780+
* @param integer $successes Number of successful operations.
781+
* @param integer $failures Number of failures.
782+
*/
783+
function report_batch_operation_results( $noun, $verb, $total, $successes, $failures ) {
784+
$plural_noun = $noun . 's';
785+
if ( in_array( $verb, array( 'reset' ), true ) ) {
786+
$past_tense_verb = $verb;
787+
} else {
788+
$past_tense_verb = 'e' === substr( $verb, -1 ) ? $verb . 'd' : $verb . 'ed';
789+
}
790+
$past_tense_verb_upper = ucfirst( $past_tense_verb );
791+
if ( $failures ) {
792+
if ( $successes ) {
793+
WP_CLI::error( "Only {$past_tense_verb} {$successes} of {$total} {$plural_noun}." );
794+
} else {
795+
WP_CLI::error( "No {$plural_noun} {$past_tense_verb}." );
796+
}
797+
} else {
798+
if ( $successes ) {
799+
WP_CLI::success( "{$past_tense_verb_upper} {$successes} of {$total} {$plural_noun}." );
800+
} else {
801+
$message = $total > 1 ? ucfirst( $plural_noun ) : ucfirst( $noun );
802+
WP_CLI::success( "{$message} already {$past_tense_verb}." );
803+
}
804+
}
805+
}
806+
807+
/**
808+
* Parse a string of command line arguments into an $argv-esqe variable.
809+
*
810+
* @access public
811+
* @category Input
812+
*
813+
* @param string $arguments
814+
* @return array
815+
*/
816+
function parse_str_to_argv( $arguments ) {
817+
preg_match_all ('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $arguments, $matches );
818+
$argv = isset( $matches[0] ) ? $matches[0] : array();
819+
$argv = array_map( function( $arg ){
820+
foreach( array( '"', "'" ) as $char ) {
821+
if ( $char === substr( $arg, 0, 1 ) && $char === substr( $arg, -1 ) ) {
822+
$arg = substr( $arg, 1, -1 );
823+
break;
824+
}
825+
}
826+
return $arg;
827+
}, $argv );
828+
return $argv;
829+
}
830+
831+
/**
832+
* Locale-independent version of basename()
833+
*
834+
* @access public
835+
*
836+
* @param string $path
837+
* @param string $suffix
838+
* @return string
839+
*/
840+
function basename( $path, $suffix = '' ) {
841+
return urldecode( \basename( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ), $suffix ) );
842+
}

features/steps/given.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ function ( $world, $path, PyStringNode $content ) {
2525
}
2626
);
2727

28+
$steps->Given( '/^"([^"]+)" replaced with "([^"]+)" in the ([^\s]+) file$/', function( $world, $search, $replace, $path ) {
29+
$full_path = $world->variables['RUN_DIR'] . "/$path";
30+
$contents = file_get_contents( $full_path );
31+
$contents = str_replace( $search, $replace, $contents );
32+
file_put_contents( $full_path, $contents );
33+
});
34+
2835
$steps->Given( '/^WP files$/',
2936
function ( $world ) {
3037
$world->download_wp();
@@ -102,7 +109,7 @@ function ( $world, TableNode $table ) {
102109
}
103110
);
104111

105-
$steps->Given( '/^save (STDOUT|STDERR) ([\'].+[^\'])?as \{(\w+)\}$/',
112+
$steps->Given( '/^save (STDOUT|STDERR) ([\'].+[^\'])?\s?as \{(\w+)\}$/',
106113
function ( $world, $stream, $output_filter, $key ) {
107114

108115
$stream = strtolower( $stream );
@@ -154,4 +161,4 @@ function($world) {
154161

155162
file_put_contents( $wp_config_path, $wp_config_code );
156163
}
157-
);
164+
);

features/steps/then.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ function ( $world, $stream ) {
145145
}
146146
);
147147

148+
$steps->Then( '/^(STDOUT|STDERR) should be a version string (<|<=|>|>=|==|=|!=|<>) ([+\w\.-]+)$/',
149+
function ( $world, $stream, $operator, $goal_ver ) {
150+
$stream = strtolower( $stream );
151+
if ( false === version_compare( trim( $world->result->$stream, "\n" ), $goal_ver, $operator ) ) {
152+
throw new Exception( $world->result );
153+
}
154+
}
155+
);
156+
148157
$steps->Then( '/^the (.+) (file|directory) should (exist|not exist|be:|contain:|not contain:)$/',
149158
function ( $world, $path, $type, $action, $expected = null ) {
150159
$path = $world->replace_variables( $path );

utils/behat-tags.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
function version_tags( $prefix, $current, $operator = '<' ) {
1717
if ( ! $current )
18-
return;
18+
return array();
1919

2020
exec( "grep '@{$prefix}-[0-9\.]*' -h -o features/*.feature | uniq", $existing_tags );
2121

@@ -40,6 +40,26 @@ function version_tags( $prefix, $current, $operator = '<' ) {
4040
# Skip Github API tests by default because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612
4141
$skip_tags[] = '@github-api';
4242

43+
# Require PHP extension, eg 'imagick'.
44+
function extension_tags() {
45+
$extension_tags = array();
46+
exec( "grep '@require-extension-[A-Za-z_]*' -h -o features/*.feature | uniq", $extension_tags );
47+
48+
$skip_tags = array();
49+
50+
$substr_start = strlen( '@require-extension-' );
51+
foreach ( $extension_tags as $tag ) {
52+
$extension = substr( $tag, $substr_start );
53+
if ( ! extension_loaded( $extension ) ) {
54+
$skip_tags[] = $tag;
55+
}
56+
}
57+
58+
return $skip_tags;
59+
}
60+
61+
$skip_tags = array_merge( $skip_tags, extension_tags() );
62+
4363
if ( !empty( $skip_tags ) ) {
4464
echo '--tags=~' . implode( '&&~', $skip_tags );
4565
}

0 commit comments

Comments
 (0)