diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml
index d41c4f9412..c27aaefa3f 100644
--- a/.github/workflows/phpunit-tests.yml
+++ b/.github/workflows/phpunit-tests.yml
@@ -19,7 +19,6 @@ on:
- cron: '0 0 * * 0'
env:
- LOCAL_DIR: build
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: ${{ true }}
COMPOSER_INSTALL: ${{ false }}
# Controls which NPM script to use for running PHPUnit tests. Options ar `php` and `php-composer`.
@@ -27,20 +26,12 @@ env:
LOCAL_PHP_MEMCACHED: ${{ false }}
jobs:
- # Sets up WordPress for testing or development use.
+ # Sets up the workflow for testing.
#
# Performs the following steps:
# - Cancels all previous workflow runs for pull requests that have not completed.
- # - Checks out the repository.
- # - Logs debug information about the runner container.
- # - Installs NodeJS 14.
- # - Sets up caching for NPM.
- # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
- # - Builds WordPress to run from the `build` directory.
- # - Creates a ZIP file of compiled WordPress.
- # - Uploads ZIP file as an artifact.
- setup-wordpress:
- name: Setup WordPress
+ setup-workflow:
+ name: Setup Workflow
runs-on: ubuntu-latest
if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
@@ -51,67 +42,16 @@ jobs:
with:
access_token: ${{ github.token }}
- - name: Checkout repository
- uses: actions/checkout@v2
-
- - name: Log debug information
- run: |
- echo "$GITHUB_REF"
- echo "$GITHUB_EVENT_NAME"
- npm --version
- node --version
- curl --version
- git --version
- svn --version
- php --version
- php -i
- locale -a
-
- - name: Install NodeJS
- uses: actions/setup-node@v2
- with:
- node-version: 14
-
- - name: Cache NodeJS modules
- uses: actions/cache@v2
- env:
- cache-name: cache-node-modules
- with:
- # npm cache files are stored in `~/.npm` on Linux/macOS
- path: ~/.npm
- key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install Dependencies
- run: npx install-changed --install-command="npm ci"
-
- - name: Build WordPress
- run: npm run build
-
- - name: Create ZIP artifact
- uses: thedoctor0/zip-release@0.4.1
- with:
- filename: built-wp-${{ github.sha }}.zip
- exclusions: '*.git* /*node_modules/* packagehash.txt'
-
- - name: Upload build artifact
- uses: actions/upload-artifact@v2
- with:
- name: built-wp-${{ github.sha }}
- path: built-wp-${{ github.sha }}.zip
- if-no-files-found: error
-
# Runs the PHPUnit tests for WordPress.
#
# Performs the following steps:
# - Set environment variables.
# - Sets up the environment variables needed for testing with memcached (if desired).
- # - Downloads the built WordPress artifact from the previous job.
- # - Unzips the artifact.
# - Installs NodeJS 14.
# - Sets up caching for NPM.
- # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+ # - Installs NPM dependencies
# - Configures caching for Composer.
- # _ Installs Composer dependencies (if desired).
+ # - Installs Composer dependencies (if desired).
# - Logs Docker debug information (about both the Docker installation within the runner).
# - Starts the WordPress Docker container.
# - Starts the memcached server after the Docker network has been created (if desired).
@@ -127,7 +67,6 @@ jobs:
# - todo: Configure Slack notifications for failing tests.
test-php:
name: ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }}${{ matrix.memcached && ' with memcached' || '' }} on ${{ matrix.os }}
- needs: setup-wordpress
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -163,13 +102,8 @@ jobs:
echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV
echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV
- - name: Download the built WordPress artifact
- uses: actions/download-artifact@v2
- with:
- name: built-wp-${{ github.sha }}
-
- - name: Unzip built artifact
- run: unzip built-wp-${{ github.sha }}.zip
+ - name: Checkout repository
+ uses: actions/checkout@v2
- name: Install NodeJS
uses: actions/setup-node@v2
@@ -230,7 +164,7 @@ jobs:
- name: Start the Memcached server.
if: ${{ matrix.memcached }}
run: |
- cp tests/phpunit/includes/object-cache.php build/wp-content/object-cache.php
+ cp tests/phpunit/includes/object-cache.php src/wp-content/object-cache.php
docker run --name memcached --net $(basename "$PWD")_wpdevnet -d memcached
- name: General debug information
diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml
index 8fe9054a49..79c453429f 100644
--- a/.github/workflows/test-coverage.yml
+++ b/.github/workflows/test-coverage.yml
@@ -6,7 +6,6 @@ on:
- cron: '0 0 * * *'
env:
- LOCAL_DIR: build
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: ${{ true }}
COMPOSER_INSTALL: ${{ false }}
# Controls which NPM script to use for running PHPUnit tests. Options ar `php` and `php-composer`.
@@ -26,7 +25,6 @@ jobs:
# - Installs NodeJS 14.
# - Sets up caching for NPM.
# _ Installs NPM dependencies using install-changed to hash the `package.json` file.
- # - Builds WordPress to run from the `build` directory.
# - Logs Docker debug information (about the Docker installation within the runner).
# - Starts the WordPress Docker container.
# - Logs debug general information.
@@ -85,9 +83,6 @@ jobs:
- name: Install Dependencies
run: npx install-changed --install-command="npm ci"
- - name: Build WordPress
- run: npm run build
-
- name: Docker debug information
run: |
docker -v
diff --git a/Gruntfile.js b/Gruntfile.js
index 06d9b4b298..c7a772e73d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -7,6 +7,8 @@ var installChanged = require( 'install-changed' );
module.exports = function(grunt) {
var path = require('path'),
fs = require( 'fs' ),
+ glob = require( 'glob' ),
+ assert = require( 'assert' ).strict,
spawn = require( 'child_process' ).spawnSync,
SOURCE_DIR = 'src/',
BUILD_DIR = 'build/',
@@ -1431,6 +1433,126 @@ module.exports = function(grunt) {
'copy:version',
] );
+ /**
+ * Build verification tasks.
+ */
+ grunt.registerTask( 'verify:build', [
+ 'verify:wp-embed',
+ 'verify:old-files',
+ 'verify:source-maps',
+ ] );
+
+ /**
+ * Build assertions for wp-embed.min.js.
+ *
+ * @ticket 34698
+ */
+ grunt.registerTask( 'verify:wp-embed', function() {
+ const file = `${ BUILD_DIR }/wp-includes/js/wp-embed.min.js`;
+
+ assert(
+ fs.existsSync( file ),
+ 'The build/wp-includes/js/wp-embed.min.js file does not exist.'
+ );
+
+ const contents = fs.readFileSync( file, {
+ encoding: 'utf8',
+ } );
+
+ assert(
+ contents.length > 0,
+ 'The build/wp-includes/js/wp-embed.min.js file must not be empty.'
+ );
+ assert(
+ false === contents.includes( '&' ),
+ 'The build/wp-includes/js/wp-embed.min.js file must not contain ampersands.'
+ );
+ } );
+
+ /**
+ * Build assertions to ensure no project files are inside `$_old_files` in the build directory.
+ *
+ * @ticket 36083
+ */
+ grunt.registerTask( 'verify:old-files', function() {
+ const file = `${ BUILD_DIR }wp-admin/includes/update-core.php`;
+
+ assert(
+ fs.existsSync( file ),
+ 'The build/wp-admin/includes/update-core.php file does not exist.'
+ );
+
+ const contents = fs.readFileSync( file, {
+ encoding: 'utf8',
+ } );
+
+ assert(
+ contents.length > 0,
+ 'The build/wp-admin/includes/update-core.php file must not be empty.'
+ );
+
+ const match = contents.match( /\$_old_files = array\(([^\)]+)\);/ );
+
+ assert(
+ match.length > 0,
+ 'The build/wp-admin/includes/update-core.php file does not include an `$_old_files` array.'
+ );
+
+ const files = match[1].split( '\n\t' ).filter( function( file ) {
+ // Filter out empty lines
+ if ( '' === file ) {
+ return false;
+ }
+
+ // Filter out commented out lines
+ if ( 0 === file.indexOf( '/' ) ) {
+ return false;
+ }
+
+ return true;
+ } ).map( function( file ) {
+ // Strip leading and trailing single quotes and commas
+ return file.replace( /^\'|\',$/g, '' );
+ } );
+
+ files.forEach(function( file ){
+ const search = `${ BUILD_DIR }${ file }`;
+ assert(
+ false === fs.existsSync( search ),
+ `${ search } should not be present in the $_old_files array.`
+ );
+ });
+ } );
+
+ /**
+ * Build assertions for the lack of source maps in JavaScript files.
+ *
+ * @ticket 24994
+ * @ticket 46218
+ */
+ grunt.registerTask( 'verify:source-maps', function() {
+ const path = `${ BUILD_DIR }**/*.js`;
+ const files = glob.sync( path );
+
+ assert(
+ files.length > 0,
+ 'No JavaScript files found in the build directory.'
+ );
+
+ files.forEach( function( file ) {
+ const contents = fs.readFileSync( file, {
+ encoding: 'utf8',
+ } );
+ // `data:` URLs are allowed:
+ const match = contents.match( /sourceMappingURL=((?!data:).)/ );
+
+ assert(
+ match === null,
+ `The ${ file } file must not contain a sourceMappingURL.`
+ );
+ } );
+ } );
+
grunt.registerTask( 'build', function() {
if ( grunt.option( 'dev' ) ) {
grunt.task.run( [
@@ -1444,7 +1566,8 @@ module.exports = function(grunt) {
'build:css',
'includes:emoji',
'includes:embed',
- 'replace:emojiBannerText'
+ 'replace:emojiBannerText',
+ 'verify:build'
] );
}
} );
diff --git a/README.md b/README.md
index 48af3be754..952d037d37 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Your WordPress site will accessible at http://localhost:8889. You can see or cha
If you're making changes to WordPress core files, you should start the file watcher in order to build or copy the files as necessary:
```
-npm run watch
+npm run dev
```
To stop the watcher, press `ctrl+c`.
diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php
index 4dbbea959f..1c532b9372 100644
--- a/tests/phpunit/includes/abstract-testcase.php
+++ b/tests/phpunit/includes/abstract-testcase.php
@@ -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 );
+ }
}
diff --git a/tests/phpunit/tests/admin/includesUpdateCore.php b/tests/phpunit/tests/admin/includesUpdateCore.php
deleted file mode 100644
index 67d750a442..0000000000
--- a/tests/phpunit/tests/admin/includesUpdateCore.php
+++ /dev/null
@@ -1,34 +0,0 @@
-assertFileNotExists( dirname( ABSPATH ) . '/build/' . $file );
- }
-}
diff --git a/tests/phpunit/tests/dependencies/jquery.php b/tests/phpunit/tests/dependencies/jquery.php
index 33f3b6b9a0..082d0e6bd0 100644
--- a/tests/phpunit/tests/dependencies/jquery.php
+++ b/tests/phpunit/tests/dependencies/jquery.php
@@ -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
*
diff --git a/tests/phpunit/tests/dependencies/mediaelementjs.php b/tests/phpunit/tests/dependencies/mediaelementjs.php
deleted file mode 100644
index 38263f7581..0000000000
--- a/tests/phpunit/tests/dependencies/mediaelementjs.php
+++ /dev/null
@@ -1,36 +0,0 @@
-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 ) );
- }
-}
diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php
index 838ac454d3..299c112f5f 100644
--- a/tests/phpunit/tests/dependencies/scripts.php
+++ b/tests/phpunit/tests/dependencies/scripts.php
@@ -728,7 +728,7 @@ JS;
$expected .= "\n";
$expected .= "\n";
$expected .= "\n";
$expected .= "\n";
$expected .= "\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
diff --git a/tests/phpunit/tests/formatting/Emoji.php b/tests/phpunit/tests/formatting/Emoji.php
index 8ddb5bc05b..6c8c5685f3 100644
--- a/tests/phpunit/tests/formatting/Emoji.php
+++ b/tests/phpunit/tests/formatting/Emoji.php
@@ -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 );
diff --git a/tests/phpunit/tests/oembed/controller.php b/tests/phpunit/tests/oembed/controller.php
index 731955f31d..f39c74f5d0 100644
--- a/tests/phpunit/tests/oembed/controller.php
+++ b/tests/phpunit/tests/oembed/controller.php
@@ -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() {
diff --git a/tests/phpunit/tests/oembed/getResponseData.php b/tests/phpunit/tests/oembed/getResponseData.php
index 8315d652a4..1c6547a6b7 100644
--- a/tests/phpunit/tests/oembed/getResponseData.php
+++ b/tests/phpunit/tests/oembed/getResponseData.php
@@ -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 ) );
}
diff --git a/tests/phpunit/tests/oembed/template.php b/tests/phpunit/tests/oembed/template.php
index 0eefb8f4c0..1577c53609 100644
--- a/tests/phpunit/tests/oembed/template.php
+++ b/tests/phpunit/tests/oembed/template.php
@@ -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 ) );
- }
-
}
diff --git a/tests/phpunit/tests/oembed/wpOembed.php b/tests/phpunit/tests/oembed/wpOembed.php
index 1f15abbad8..a2d767e373 100644
--- a/tests/phpunit/tests/oembed/wpOembed.php
+++ b/tests/phpunit/tests/oembed/wpOembed.php
@@ -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 ) {
diff --git a/tests/phpunit/tests/shortcode.php b/tests/phpunit/tests/shortcode.php
index 764c492764..ea8bb136fc 100644
--- a/tests/phpunit/tests/shortcode.php
+++ b/tests/phpunit/tests/shortcode.php
@@ -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();
diff --git a/tests/qunit/index.html b/tests/qunit/index.html
index ab6a9c0468..dd3fb68224 100644
--- a/tests/qunit/index.html
+++ b/tests/qunit/index.html
@@ -152,6 +152,7 @@
+
diff --git a/tests/qunit/wp-includes/js/jquery.js b/tests/qunit/wp-includes/js/jquery.js
new file mode 100644
index 0000000000..6c02e63238
--- /dev/null
+++ b/tests/qunit/wp-includes/js/jquery.js
@@ -0,0 +1,10 @@
+( function( QUnit ) {
+ QUnit.module( 'jQuery' );
+
+ QUnit.test( 'jQuery is run in noConflict mode', function( assert ) {
+ assert.expect( 1 );
+
+ assert.ok( 'undefined' === typeof window.$ );
+ } );
+
+} )( window.QUnit );
diff --git a/wp-tests-config-sample.php b/wp-tests-config-sample.php
index 7e87d5f6d3..62636da344 100644
--- a/wp-tests-config-sample.php
+++ b/wp-tests-config-sample.php
@@ -1,11 +1,7 @@