Build/Test Tools: Switch back to running the PHPUnit test suite against the src directory instead of build.

Some PHPUnit tests were concerned with the state of files in the `build` directory. In order to allow the tests to run without requiring a build to be run first, these have been moved into assertions that run after the build step (and therefore cause it to fail if they do not pass), or into QUnit tests as necessary.

Various other PHPUnit tests implictly depend on built JavaScript files being present. These files are now touched during the test setup to avoid PHP warnings if the `build` files are not present.

The `wp-tests-config-sample.php` file and the GitHub Actions configuration have also been changed so `ABSPATH` uses `src` instead of `build`, therefore allowing the PHPUnit tests to be run without a build having to be run first. This means all new local installations of WordPress will use `src` for PHPUnit testing. If you would like to switch your existing installation over then change the location of `ABSPATH` in `wp-tests-config.php` to point to `src` instead of `build`.

Props peterwilsoncc, iandunn, gziolo, desroj, johnbillion

Fixes #51734
See #45863


git-svn-id: https://develop.svn.wordpress.org/trunk@50441 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
John Blackbourn
2021-02-26 14:07:53 +00:00
parent a280d5704b
commit 4ab922d224
18 changed files with 195 additions and 218 deletions
@@ -1293,4 +1293,26 @@ abstract class WP_UnitTestCase_Base extends PHPUnit\Framework\TestCase {
)
);
}
/**
* Touches the given file and its directory if it doesn't already exist.
*
* This can be used to ensure a file that is implictly relied on in a test exists
* without it having to be built.
*
* @param string $file The file name.
*/
public static function touch( $file ) {
if ( file_exists( $file ) ) {
return;
}
$dir = dirname( $file );
if ( ! file_exists( $dir ) ) {
mkdir( $dir, 0777, true );
}
touch( $file );
}
}
@@ -1,34 +0,0 @@
<?php
/**
* @group admin
* @group upgrade
*/
class Tests_Admin_IncludesUpdateCore extends WP_UnitTestCase {
public function data_old_files() {
global $_old_files;
require_once ABSPATH . 'wp-admin/includes/update-core.php';
$files = $_old_files;
foreach ( $files as &$file ) {
$file = array( $file );
}
return $files;
}
/**
* Ensure no project files are inside `$_old_files` in the build directory.
*
* @ticket 36083
*
* @dataProvider data_old_files
*
* @param string $file File name.
*/
public function test_new_files_are_not_in_old_files_array_compiled( $file ) {
$this->assertFileNotExists( dirname( ABSPATH ) . '/build/' . $file );
}
}
@@ -39,13 +39,6 @@ class Tests_Dependencies_jQuery extends WP_UnitTestCase {
}
}
function test_presence_of_jquery_no_conflict() {
$contents = trim( file_get_contents( ABSPATH . WPINC . '/js/jquery/jquery.js' ) );
$noconflict = 'jQuery.noConflict();';
$end = substr( $contents, - strlen( $noconflict ) );
$this->assertSame( $noconflict, $end );
}
/**
* @ticket 22896
*
@@ -1,36 +0,0 @@
<?php
/**
* @group dependencies
* @group scripts
*/
class Tests_Dependencies_MediaElementjs extends WP_UnitTestCase {
/**
* Test if the MediaElement.js Flash fallbacks have been re-added.
*
* MediaElement's Flash fallbacks were removed in WordPress 4.9.2 due to limited use cases and
* a history of security vulnerabilities. It's unlikely that there'll ever be a need to
* restore them in the future, and doing so could introduce security vulnerabilities. If you
* want to re-add them, please discuss that with the Security team first.
*
* @since 5.1.0
*
* @ticket 42720
*/
function test_exclusion_of_flash() {
$mejs_folder = ABSPATH . WPINC . '/js/mediaelement';
$js_files = glob( $mejs_folder . '/*.js' );
/*
* The path in $mejs_folder is hardcoded, so this is just a sanity check to make sure the
* correct directory is used, in case it gets renamed in the future.
*/
$this->assertGreaterThan( 0, count( $js_files ) );
$mejs_directory_iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $mejs_folder ) );
$mejs_swf_iterator = new RegexIterator( $mejs_directory_iterator, '/\.swf$/i', RecursiveRegexIterator::GET_MATCH );
// Make sure the Flash files haven't been re-added accidentally.
$this->assertCount( 0, iterator_to_array( $mejs_swf_iterator ) );
}
}
+1 -13
View File
@@ -728,7 +728,7 @@ JS;
$expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/dist/vendor/wp-polyfill{$suffix}.js' id='wp-polyfill-js'></script>\n";
$expected .= "<script type='text/javascript' id='wp-polyfill-js-after'>\n";
$expected .= "( 'fetch' in window ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-fetch{$suffix}.js\"></scr' + 'ipt>' );( document.contains ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-node-contains{$suffix}.js\"></scr' + 'ipt>' );( window.DOMRect ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-dom-rect{$suffix}.js\"></scr' + 'ipt>' );( window.URL && window.URL.prototype && window.URLSearchParams ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-url{$suffix}.js\"></scr' + 'ipt>' );( window.FormData && window.FormData.prototype.keys ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-formdata{$suffix}.js\"></scr' + 'ipt>' );( Element.prototype.matches && Element.prototype.closest ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-element-closest{$suffix}.js\"></scr' + 'ipt>' );( 'objectFit' in document.documentElement.style ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-object-fit.min.js\"></scr' + 'ipt>' );\n";
$expected .= "( 'fetch' in window ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-fetch{$suffix}.js\"></scr' + 'ipt>' );( document.contains ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-node-contains{$suffix}.js\"></scr' + 'ipt>' );( window.DOMRect ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-dom-rect{$suffix}.js\"></scr' + 'ipt>' );( window.URL && window.URL.prototype && window.URLSearchParams ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-url{$suffix}.js\"></scr' + 'ipt>' );( window.FormData && window.FormData.prototype.keys ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-formdata{$suffix}.js\"></scr' + 'ipt>' );( Element.prototype.matches && Element.prototype.closest ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-element-closest{$suffix}.js\"></scr' + 'ipt>' );( 'objectFit' in document.documentElement.style ) || document.write( '<script src=\"http://example.org/wp-includes/js/dist/vendor/wp-polyfill-object-fit{$suffix}.js\"></scr' + 'ipt>' );\n";
$expected .= "</script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/dist/dom-ready{$suffix}.js' id='wp-dom-ready-js'></script>\n";
$expected .= "<script type='text/javascript' src='/wp-includes/js/dist/hooks{$suffix}.js' id='wp-hooks-js'></script>\n";
@@ -1417,18 +1417,6 @@ JS;
);
}
function test_no_source_mapping() {
$all_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( dirname( ABSPATH ) . '/build/' ) );
$js_files = new RegexIterator( $all_files, '/\.js$/' );
foreach ( $js_files as $js_file ) {
$contents = trim( file_get_contents( $js_file ) );
// We allow data: URLs.
$found = preg_match( '/sourceMappingURL=((?!data:).)/', $contents );
$this->assertSame( $found, 0, "sourceMappingURL found in $js_file" );
}
}
/**
* @ticket 52534
* @covers ::wp_localize_script
+6
View File
@@ -13,6 +13,8 @@ class Tests_Formatting_Emoji extends WP_UnitTestCase {
* @ticket 36525
*/
public function test_unfiltered_emoji_cdns() {
// `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' );
$output = get_echo( '_print_emoji_detection_script' );
$this->assertContains( wp_json_encode( $this->png_cdn ), $output );
@@ -31,6 +33,8 @@ class Tests_Formatting_Emoji extends WP_UnitTestCase {
add_filter( 'emoji_svg_url', array( $this, '_filtered_emoji_svn_cdn' ) );
// `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' );
$output = get_echo( '_print_emoji_detection_script' );
$this->assertContains( wp_json_encode( $this->png_cdn ), $output );
@@ -52,6 +56,8 @@ class Tests_Formatting_Emoji extends WP_UnitTestCase {
add_filter( 'emoji_url', array( $this, '_filtered_emoji_png_cdn' ) );
// `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' );
$output = get_echo( '_print_emoji_detection_script' );
$this->assertContains( wp_json_encode( $filtered_png_cdn ), $output );
@@ -34,6 +34,9 @@ class Test_oEmbed_Controller extends WP_UnitTestCase {
'user_email' => 'administrator@example.com',
)
);
// `get_post_embed_html()` assumes `wp-includes/js/wp-embed.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-embed.js' );
}
public static function wpTearDownAfterClass() {
@@ -5,6 +5,13 @@
* @covers ::get_oembed_response_data
*/
class Tests_oEmbed_Response_Data extends WP_UnitTestCase {
public function setUp() {
parent::setUp();
// `get_post_embed_html()` assumes `wp-includes/js/wp-embed.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-embed.js' );
}
function test_get_oembed_response_data_non_existent_post() {
$this->assertFalse( get_oembed_response_data( 0, 100 ) );
}
+7 -41
View File
@@ -23,6 +23,9 @@ class Tests_Embed_Template extends WP_UnitTestCase {
$this->assertQueryTrue( 'is_single', 'is_singular', 'is_embed' );
// `print_embed_scripts()` assumes `wp-includes/js/wp-embed-template.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-embed-template.js' );
ob_start();
require ABSPATH . WPINC . '/theme-compat/embed.php';
$actual = ob_get_clean();
@@ -290,50 +293,13 @@ class Tests_Embed_Template extends WP_UnitTestCase {
}
/**
* Confirms that no ampersands exist in src/wp-includes/js/wp-embed.js.
*
* See also the `verify:wp-embed` Grunt task for verifying the built file.
*
* @ticket 34698
*/
function test_js_no_ampersands() {
$this->assertNotContains( '&', file_get_contents( ABSPATH . WPINC . '/js/wp-embed.js' ) );
}
/**
* @ticket 34698
*
* @depends test_js_no_ampersands
*
* The previous test confirms that no ampersands exist in src/wp-includes/js/wp-embed.js.
* However, we must also confirm that UglifyJS does not add ampersands during its
* optimizations (which we tweak to avoid, but indirectly -- understandably, there's
* no "don't add ampersands to my JavaScript file" option).
*
* So this test checks for ampersands in build/wp-includes/js/wp-embed.min.js.
* In many cases, this file will not exist; in those cases, we simply skip the test.
*
* So when would it be run? We have Travis CI run `npm run test` which then runs, in order,
* `qunit:compiled` (which runs the build) and then `phpunit`. Thus, this test will at least be
* run during continuous integration.
*
* However, we need to verify that `qunit:compiled` runs before `phpunit`. So this test also
* does a cheap check for a registered Grunt task called `test` that contains both
* `qunit:compiled` and `phpunit`, in that order.
*
* One final failsafe: The Gruntfile.js assertion takes place before checking for the existence
* of wp-embed.min.js. If the Grunt tasks are significantly refactored later, it could indicate
* that wp-embed.min.js doesn't exist anymore. We wouldn't want the test to silently become one
* that is always skipped, and thus useless.
*/
function test_js_no_ampersands_in_compiled() {
$gruntfile = file_get_contents( dirname( ABSPATH ) . '/Gruntfile.js' );
// Confirm this file *should* exist, otherwise this test will always be skipped.
$test = '/grunt.registerTask\(\s*\'test\',.*\'qunit:compiled\'.*\'phpunit\'/';
$this->assertTrue( (bool) preg_match( $test, $gruntfile ) );
$file = dirname( ABSPATH ) . '/build/' . WPINC . '/js/wp-embed.min.js';
if ( ! file_exists( $file ) ) {
return;
}
$this->assertNotContains( '&', file_get_contents( $file ) );
}
}
+3
View File
@@ -18,6 +18,9 @@ class Tests_WP_oEmbed extends WP_UnitTestCase {
$this->oembed = _wp_oembed_get_object();
$this->pre_oembed_result_filtered = false;
// `get_post_embed_html()` assumes `wp-includes/js/wp-embed.js` is present:
self::touch( ABSPATH . WPINC . '/js/wp-embed.js' );
}
public function _filter_pre_oembed_result( $result ) {
+1 -1
View File
@@ -746,7 +746,7 @@ EOF;
function test_php_and_js_shortcode_attribute_regexes_match() {
$file = file_get_contents( ABSPATH . WPINC . '/js/shortcode.js' );
$file = file_get_contents( ABSPATH . 'js/_enqueues/wp/shortcode.js' );
$matched = preg_match( '|\s+pattern = (\/.+\/)g;|', $file, $matches );
$php = get_shortcode_atts_regex();