From 628a1f6d20237c47dd0c60f6790f555f7cac7ef5 Mon Sep 17 00:00:00 2001 From: Christopher Allford <6451942+ObliviousHarmony@users.noreply.github.com> Date: Mon, 1 May 2023 17:07:58 -0700 Subject: [PATCH] Add `wp-env` After Setup Command (#50196) * Added `afterSetup` Root Config Option This runs a user-provided script as a lifecycle hook after WordPress setup completes. * Moved Test Files The `config` test files are under `lib/config` but the `lib` test files are under the root. This moves them to be consistent with the other test files. * Enforced Strict Mode * Execute `afterSetup` on `start` and `clean` * Documented `afterSetup` Option --- packages/env/CHANGELOG.md | 7 ++ packages/env/README.md | 70 +++++++++++++------ packages/env/lib/cache.js | 1 + packages/env/lib/cli.js | 17 ++++- packages/env/lib/commands/clean.js | 15 +++- packages/env/lib/commands/destroy.js | 1 + packages/env/lib/commands/index.js | 1 + packages/env/lib/commands/install-path.js | 1 + packages/env/lib/commands/logs.js | 1 + packages/env/lib/commands/run.js | 1 + packages/env/lib/commands/start.js | 18 ++++- packages/env/lib/commands/stop.js | 1 + .../env/lib/config/add-or-replace-port.js | 1 + packages/env/lib/config/db-env.js | 1 + .../get-config-from-environment-vars.js | 11 ++- packages/env/lib/config/index.js | 3 +- packages/env/lib/config/load-config.js | 3 + packages/env/lib/config/parse-config.js | 35 +++++++--- .../env/lib/config/post-process-config.js | 6 +- .../__snapshots__/config-integration.js.snap | 4 ++ .../lib/config/test/add-or-replace-port.js | 1 + .../env/lib/config/test/config-integration.js | 4 ++ packages/env/lib/config/test/parse-config.js | 10 ++- .../lib/config/test/parse-source-string.js | 4 +- .../lib/config/test/post-process-config.js | 29 +++++++- .../lib/config/test/read-raw-config-file.js | 4 +- .../env/lib/config/test/validate-config.js | 44 ++++-------- packages/env/lib/config/validate-config.js | 38 +++++----- packages/env/lib/env.js | 2 + packages/env/lib/execute-after-setup.js | 51 ++++++++++++++ packages/env/lib/get-host-user.js | 1 + packages/env/lib/init-config.js | 1 + packages/env/lib/md5.js | 1 + packages/env/lib/parse-xdebug-mode.js | 1 + packages/env/lib/retry.js | 1 + .../{ => lib}/test/__snapshots__/md5.js.snap | 0 .../test/build-docker-compose-config.js | 7 +- packages/env/{ => lib}/test/cache.js | 3 +- packages/env/{ => lib}/test/cli.js | 22 +++--- packages/env/lib/test/execute-after-setup.js | 66 +++++++++++++++++ packages/env/{ => lib}/test/md5.js | 3 +- .../env/{ => lib}/test/parse-xdebug-mode.js | 3 +- packages/env/lib/wordpress.js | 1 + 43 files changed, 386 insertions(+), 109 deletions(-) create mode 100644 packages/env/lib/execute-after-setup.js rename packages/env/{ => lib}/test/__snapshots__/md5.js.snap (100%) rename packages/env/{ => lib}/test/build-docker-compose-config.js (96%) rename packages/env/{ => lib}/test/cache.js (99%) rename packages/env/{ => lib}/test/cli.js (91%) create mode 100644 packages/env/lib/test/execute-after-setup.js rename packages/env/{ => lib}/test/md5.js (94%) rename packages/env/{ => lib}/test/parse-xdebug-mode.js (94%) diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index aef44414c0db6..767b382e1e096 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -7,6 +7,13 @@ - Docker containers now run as the host user. This should resolve problems with permissions arising from different owners between the host, web container, and cli container. If you still encounter permissions issues, try running `npx wp-env destroy` so that the environment can be recreated with the correct permissions. +### New feature + +- Create an `afterSetup` option in `.wp-env.json` files for setting arbitrary commands to run after setting up WordPress when using `wp-env start` and `wp-env clean`. +- Add a `WP_ENV_AFTER_SETUP` environment variable to override the `afterSetup` option. +- Execute the `afterSetup` command on `wp-env start` after the environment is set up. This can happen when your config changes, WordPress updates, or you pass the `--update` flag. +- Execute the `afterSetup` command on `wp-env clean`. + ### Bug fix - Ensure `wordpress`, `tests-wordpress`, `cli`, and `tests-cli` always build the correct Docker image. diff --git a/packages/env/README.md b/packages/env/README.md index e6aea1cf18cf3..1b9e292171da1 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -253,15 +253,14 @@ The start command installs and initializes the WordPress environment, which incl ```sh wp-env start -Starts WordPress for development on port 8888 (override with WP_ENV_PORT) and -tests on port 8889 (override with WP_ENV_TESTS_PORT). The current working -directory must be a WordPress installation, a plugin, a theme, or contain a -.wp-env.json file. After first install, use the '--update' flag to download -updates to mapped sources and to re-apply WordPress configuration options. +Starts WordPress for development on port 8888 (​http://localhost:8888​) +(override with WP_ENV_PORT) and tests on port 8889 (​http://localhost:8889​) +(override with WP_ENV_TESTS_PORT). The current working directory must be a +WordPress installation, a plugin, a theme, or contain a .wp-env.json file. After +first install, use the '--update' flag to download updates to mapped sources and +to re-apply WordPress configuration options. Options: - --help Show help [boolean] - --version Show version number [boolean] --debug Enable debug output. [boolean] [default: false] --update Download source updates and apply WordPress configuration. [boolean] [default: false] @@ -270,6 +269,7 @@ Options: them in a comma-separated list: `--xdebug=develop,coverage`. See https://xdebug.org/docs/all_settings#mode for information about Xdebug modes. [string] + --scripts Execute any configured lifecycle scripts. [boolean] [default: true] ``` ### `wp-env stop` @@ -278,6 +278,9 @@ Options: wp-env stop Stops running WordPress for development and tests and frees the ports. + +Options: + --debug Enable debug output. [boolean] [default: false] ``` ### `wp-env clean [environment]` @@ -290,6 +293,10 @@ Cleans the WordPress databases. Positionals: environment Which environments' databases to clean. [string] [choices: "all", "development", "tests"] [default: "tests"] + +Options: + --debug Enable debug output. [boolean] [default: false] + --scripts Execute any configured lifecycle scripts. [boolean] [default: true] ``` ### `wp-env run [container] [command]` @@ -327,8 +334,6 @@ Positionals: command The command to run. [array] [default: []] Options: - --help Show help [boolean] - --version Show version number [boolean] --debug Enable debug output. [boolean] [default: false] --env-cwd The command's working directory inside of the container. Paths without a leading slash are relative to the WordPress root. @@ -397,6 +402,9 @@ wp-env destroy Destroy the WordPress environment. Deletes docker containers, volumes, and networks associated with the WordPress environment and removes local files. + +Options: + --debug Enable debug output. [boolean] [default: false] ``` ### `wp-env logs [environment]` @@ -411,8 +419,6 @@ Positionals: [string] [choices: "development", "tests", "all"] [default: "development"] Options: - --help Show help [boolean] - --version Show version number [boolean] --debug Enable debug output. [boolean] [default: false] --watch Watch for logs as they happen. [boolean] [default: true] ``` @@ -514,9 +520,23 @@ These can be overridden by setting a value within the `config` configuration. Se Additionally, the values referencing a URL include the specified port for the given environment. So if you set `testsPort: 3000, port: 2000`, `WP_HOME` (for example) will be `http://localhost:3000` on the tests instance and `http://localhost:2000` on the development instance. -### Examples +## Lifecycle Hooks + +These hooks are executed at certain points during the lifecycle of a command's execution. Keep in mind that these will be executed on both fresh and existing +environments, so, ensure any commands you build won't break on subsequent executions. + +### After Setup + +Using the `afterSetup` option in `.wp-env.json` files will allow you to configure an arbitrary command to execute after the environment's setup is complete: -#### Latest stable WordPress + current directory as a plugin +- `wp-env start`: Runs when the config changes, WordPress updates, or you pass the `--update` flag. +- `wp-env clean`: Runs after the selected environments have been cleaned. + +You can override the `afterSetup` option using the `WP_ENV_AFTER_SETUP` environment variable. + +## Examples + +### Latest stable WordPress + current directory as a plugin This is useful for plugin development. @@ -538,7 +558,7 @@ This is useful for plugin development when upstream Core changes need to be test } ``` -#### Local `wordpress-develop` + current directory as a plugin +### Local `wordpress-develop` + current directory as a plugin This is useful for working on plugins and WordPress Core at the same time. @@ -560,7 +580,7 @@ If you are running `wordpress-develop` in a dev mode (e.g. the watch command `de } ``` -#### A complete testing environment +### A complete testing environment This is useful for integration testing: that is, testing how old versions of WordPress and different combinations of plugins and themes impact each other. @@ -572,7 +592,7 @@ This is useful for integration testing: that is, testing how old versions of Wor } ``` -#### Add mu-plugins and other mapped directories +### Add mu-plugins and other mapped directories You can add mu-plugins via the mapping config. The mapping config also allows you to mount a directory to any location in the wordpress install, so you could even mount a subdirectory. Note here that theme-1, will not be activated. @@ -587,7 +607,7 @@ You can add mu-plugins via the mapping config. The mapping config also allows yo } ``` -#### Avoid activating plugins or themes on the instance +### Avoid activating plugins or themes on the instance Since all plugins in the `plugins` key are activated by default, you should use the `mappings` key to avoid this behavior. This might be helpful if you have a test plugin that should not be activated all the time. @@ -600,7 +620,7 @@ Since all plugins in the `plugins` key are activated by default, you should use } ``` -#### Map a plugin only in the tests environment +### Map a plugin only in the tests environment If you need a plugin active in one environment but not the other, you can use `env.` to set options specific to one environment. Here, we activate cwd and a test plugin on the tests instance. This plugin is not activated on any other instances. @@ -615,7 +635,7 @@ If you need a plugin active in one environment but not the other, you can use `e } ``` -#### Custom Port Numbers +### Custom Port Numbers You can tell `wp-env` to use a custom port number so that your instance does not conflict with other `wp-env` instances. @@ -631,7 +651,7 @@ You can tell `wp-env` to use a custom port number so that your instance does not } ``` -#### Specific PHP Version +### Specific PHP Version You can tell `wp-env` to use a specific PHP version for compatibility and testing. This can also be set via the environment variable `WP_ENV_PHP_VERSION`. @@ -642,6 +662,16 @@ You can tell `wp-env` to use a specific PHP version for compatibility and testin } ``` +### Node Lifecycle Script + +This is useful for performing some actions after setting up the environment, such as bootstrapping an E2E test environment. + +```json +{ + "afterSetup": "node tests/e2e/bin/setup-env.js" +} +``` + ## Contributing to this package This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. diff --git a/packages/env/lib/cache.js b/packages/env/lib/cache.js index d6b532c559f49..187a8a24d030a 100644 --- a/packages/env/lib/cache.js +++ b/packages/env/lib/cache.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/cli.js b/packages/env/lib/cli.js index 13bee46974bea..115018a329c02 100644 --- a/packages/env/lib/cli.js +++ b/packages/env/lib/cli.js @@ -39,8 +39,11 @@ const withSpinner = process.exit( 0 ); }, ( error ) => { - if ( error instanceof env.ValidationError ) { - // Error is a validation error. That means the user did something wrong. + if ( + error instanceof env.ValidationError || + error instanceof env.AfterSetupError + ) { + // Error is a configuration error. That means the user did something wrong. spinner.fail( error.message ); process.exit( 1 ); } else if ( @@ -124,6 +127,11 @@ module.exports = function cli() { coerce: parseXdebugMode, type: 'string', } ); + args.option( 'scripts', { + type: 'boolean', + describe: 'Execute any configured lifecycle scripts.', + default: true, + } ); }, withSpinner( env.start ) ); @@ -145,6 +153,11 @@ module.exports = function cli() { choices: [ 'all', 'development', 'tests' ], default: 'tests', } ); + args.option( 'scripts', { + type: 'boolean', + describe: 'Execute any configured lifecycle scripts.', + default: true, + } ); }, withSpinner( env.clean ) ); diff --git a/packages/env/lib/commands/clean.js b/packages/env/lib/commands/clean.js index adde9d072d9eb..20b7b1550c704 100644 --- a/packages/env/lib/commands/clean.js +++ b/packages/env/lib/commands/clean.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ @@ -8,6 +9,7 @@ const dockerCompose = require( 'docker-compose' ); */ const initConfig = require( '../init-config' ); const { configureWordPress, resetDatabase } = require( '../wordpress' ); +const { executeAfterSetup } = require( '../execute-after-setup' ); /** * @typedef {import('../wordpress').WPEnvironment} WPEnvironment @@ -20,9 +22,15 @@ const { configureWordPress, resetDatabase } = require( '../wordpress' ); * @param {Object} options * @param {WPEnvironmentSelection} options.environment The environment to clean. Either 'development', 'tests', or 'all'. * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed. * @param {boolean} options.debug True if debug mode is enabled. */ -module.exports = async function clean( { environment, spinner, debug } ) { +module.exports = async function clean( { + environment, + spinner, + scripts, + debug, +} ) { const config = await initConfig( { spinner, debug } ); const description = `${ environment } environment${ @@ -57,5 +65,10 @@ module.exports = async function clean( { environment, spinner, debug } ) { await Promise.all( tasks ); + // Execute any configured command that should run after the environment has finished being set up. + if ( scripts ) { + executeAfterSetup( config, spinner ); + } + spinner.text = `Cleaned ${ description }.`; }; diff --git a/packages/env/lib/commands/destroy.js b/packages/env/lib/commands/destroy.js index 8abfed9e33d1b..509f1e89c075a 100644 --- a/packages/env/lib/commands/destroy.js +++ b/packages/env/lib/commands/destroy.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/commands/index.js b/packages/env/lib/commands/index.js index f040fe174687d..04b0a9a3678d1 100644 --- a/packages/env/lib/commands/index.js +++ b/packages/env/lib/commands/index.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ diff --git a/packages/env/lib/commands/install-path.js b/packages/env/lib/commands/install-path.js index 4cc5358a65d02..a71a153339c47 100644 --- a/packages/env/lib/commands/install-path.js +++ b/packages/env/lib/commands/install-path.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ diff --git a/packages/env/lib/commands/logs.js b/packages/env/lib/commands/logs.js index 704b89328d6b5..3a749b20b3dab 100644 --- a/packages/env/lib/commands/logs.js +++ b/packages/env/lib/commands/logs.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/commands/run.js b/packages/env/lib/commands/run.js index bed771322fd24..1e13f7a797c38 100644 --- a/packages/env/lib/commands/run.js +++ b/packages/env/lib/commands/run.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/commands/start.js b/packages/env/lib/commands/start.js index d584809431f15..474d8fefbdaf0 100644 --- a/packages/env/lib/commands/start.js +++ b/packages/env/lib/commands/start.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ @@ -30,6 +31,7 @@ const { } = require( '../wordpress' ); const { didCacheChange, setCache } = require( '../cache' ); const md5 = require( '../md5' ); +const { executeAfterSetup } = require( '../execute-after-setup' ); /** * @typedef {import('../config').WPConfig} WPConfig @@ -41,11 +43,18 @@ const CONFIG_CACHE_KEY = 'config_checksum'; * * @param {Object} options * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. * @param {boolean} options.update If true, update sources. * @param {string} options.xdebug The Xdebug mode to set. + * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed. + * @param {boolean} options.debug True if debug mode is enabled. */ -module.exports = async function start( { spinner, debug, update, xdebug } ) { +module.exports = async function start( { + spinner, + update, + xdebug, + scripts, + debug, +} ) { spinner.text = 'Reading configuration.'; await checkForLegacyInstall( spinner ); @@ -194,6 +203,11 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) { } ), ] ); + // Execute any configured command that should run after the environment has finished being set up. + if ( scripts ) { + executeAfterSetup( config, spinner ); + } + // Set the cache key once everything has been configured. await setCache( CONFIG_CACHE_KEY, configHash, { workDirectoryPath, diff --git a/packages/env/lib/commands/stop.js b/packages/env/lib/commands/stop.js index 4f6688003ebb9..3700c3f2aa581 100644 --- a/packages/env/lib/commands/stop.js +++ b/packages/env/lib/commands/stop.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/config/add-or-replace-port.js b/packages/env/lib/config/add-or-replace-port.js index 8d891869238a3..605ede43644a1 100644 --- a/packages/env/lib/config/add-or-replace-port.js +++ b/packages/env/lib/config/add-or-replace-port.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ diff --git a/packages/env/lib/config/db-env.js b/packages/env/lib/config/db-env.js index 95c0c23cf93d3..aa73fc70d60ce 100644 --- a/packages/env/lib/config/db-env.js +++ b/packages/env/lib/config/db-env.js @@ -1,3 +1,4 @@ +'use strict'; // Username and password used in all databases. const credentials = { WORDPRESS_DB_USER: 'root', diff --git a/packages/env/lib/config/get-config-from-environment-vars.js b/packages/env/lib/config/get-config-from-environment-vars.js index 98eb7cf0b0081..1447d1a4de271 100644 --- a/packages/env/lib/config/get-config-from-environment-vars.js +++ b/packages/env/lib/config/get-config-from-environment-vars.js @@ -6,7 +6,7 @@ const { parseSourceString, includeTestsPath, } = require( './parse-source-string' ); -const { checkPort, checkVersion } = require( './validate-config' ); +const { checkPort, checkVersion, checkString } = require( './validate-config' ); /** * @typedef {import('./parse-source-string').WPSource} WPSource @@ -53,6 +53,15 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) { environmentConfig.phpVersion = process.env.WP_ENV_PHP_VERSION; } + if ( process.env.WP_ENV_AFTER_SETUP ) { + checkString( + 'environment variable', + 'WP_ENV_AFTER_SETUP', + process.env.WP_ENV_AFTER_SETUP + ); + environmentConfig.afterSetup = process.env.WP_ENV_AFTER_SETUP; + } + return environmentConfig; }; diff --git a/packages/env/lib/config/index.js b/packages/env/lib/config/index.js index 71f1ed5d51b30..0fa88f4422275 100644 --- a/packages/env/lib/config/index.js +++ b/packages/env/lib/config/index.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ @@ -6,7 +7,7 @@ const { ValidationError } = require( './validate-config' ); const dbEnv = require( './db-env' ); /** - * @typedef {import('./parse-config').WPConfig} WPConfig + * @typedef {import('./load-config').WPConfig} WPConfig * @typedef {import('./parse-config').WPRootConfig} WPRootConfig * @typedef {import('./parse-config').WPEnvironmentConfig} WPEnvironmentConfig * @typedef {import('./parse-source-string').WPSource} WPSource diff --git a/packages/env/lib/config/load-config.js b/packages/env/lib/config/load-config.js index d0f6130e22163..1459dbe5a4e62 100644 --- a/packages/env/lib/config/load-config.js +++ b/packages/env/lib/config/load-config.js @@ -14,6 +14,7 @@ const { parseConfig, getConfigFilePath } = require( './parse-config' ); const postProcessConfig = require( './post-process-config' ); /** + * @typedef {import('./parse-config').WPRootConfig} WPRootConfig * @typedef {import('./parse-config').WPEnvironmentConfig} WPEnvironmentConfig */ @@ -26,6 +27,7 @@ const postProcessConfig = require( './post-process-config' ); * @property {string} workDirectoryPath Path to the work directory located in ~/.wp-env. * @property {string} dockerComposeConfigPath Path to the docker-compose.yml file. * @property {boolean} detectedLocalConfig If true, wp-env detected local config and used it. + * @property {string} afterSetup The command(s) to run after configuring WordPress on start and clean. * @property {Object.} env Specific config for different environments. * @property {boolean} debug True if debug mode is enabled. */ @@ -66,6 +68,7 @@ module.exports = async function loadConfig( configDirectoryPath ) { configFilePath, getConfigFilePath( configDirectoryPath, 'override' ), ] ), + afterSetup: config.afterSetup, env: config.env, }; }; diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 18aad4e7b3540..aa39d94ebfd9f 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -14,6 +14,7 @@ const { } = require( './parse-source-string' ); const { ValidationError, + checkString, checkPort, checkStringArray, checkObjectWithValues, @@ -33,8 +34,9 @@ const mergeConfigs = require( './merge-configs' ); * The root configuration options. * * @typedef WPRootConfigOptions - * @property {number} port The port to use in the development environment. - * @property {number} testsPort The port to use in the tests environment. + * @property {number} port The port to use in the development environment. + * @property {number} testsPort The port to use in the tests environment. + * @property {string|null} afterSetup The command(s) to run after configuring WordPress on start and clean. */ /** @@ -47,7 +49,7 @@ const mergeConfigs = require( './merge-configs' ); * @property {number} port The port to use. * @property {Object} config Mapping of wp-config.php constants to their desired values. * @property {Object.} mappings Mapping of WordPress directories to local directories which should be mounted. - * @property {string} phpVersion Version of PHP to use in the environments, of the format 0.0. + * @property {string|null} phpVersion Version of PHP to use in the environments, of the format 0.0. */ /** @@ -191,6 +193,7 @@ async function getDefaultConfig( WP_SITEURL: 'http://localhost', WP_HOME: 'http://localhost', }, + afterSetup: null, env: { development: {}, tests: { @@ -249,6 +252,10 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) { overrideConfig.env.tests.phpVersion = overrides.phpVersion; } + if ( overrides.afterSetup ) { + overrideConfig.afterSetup = overrides.afterSetup; + } + return overrideConfig; } @@ -293,6 +300,13 @@ async function parseRootConfig( configFile, rawConfig, options ) { checkPort( configFile, `testsPort`, rawConfig.testsPort ); parsedConfig.testsPort = rawConfig.testsPort; } + if ( rawConfig.afterSetup !== undefined ) { + // Support null as a valid input. + if ( rawConfig.afterSetup !== null ) { + checkString( configFile, 'afterSetup', rawConfig.afterSetup ); + } + parsedConfig.afterSetup = rawConfig.afterSetup; + } // Parse the environment-specific configs so they're accessible to the root. parsedConfig.env = {}; @@ -342,11 +356,14 @@ async function parseEnvironmentConfig( } if ( config.phpVersion !== undefined ) { - checkVersion( - configFile, - `${ environmentPrefix }phpVersion`, - config.phpVersion - ); + // Support null as a valid input. + if ( config.phpVersion !== null ) { + checkVersion( + configFile, + `${ environmentPrefix }phpVersion`, + config.phpVersion + ); + } parsedConfig.phpVersion = config.phpVersion; } @@ -396,7 +413,7 @@ async function parseEnvironmentConfig( checkValidURL( configFile, `${ environmentPrefix }config.${ key }`, - parsedConfig[ key ] + parsedConfig.config[ key ] ); break; } diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index 4855f8835e14d..46723b9f3d8c3 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -39,7 +39,7 @@ module.exports = function postProcessConfig( config ) { * @return {WPRootConfig} The config object with the root options merged together with the environment-specific options. */ function mergeRootToEnvironments( config ) { - // Some root-level options need to be merged early because they have a special + // Some root-level options need to be handled early because they have a special // cascade behavior that would break the normal merge. After merging we then // delete them to avoid that breakage and add them back before we return. const removedRootOptions = {}; @@ -59,6 +59,10 @@ function mergeRootToEnvironments( config ) { config.env.tests.port = config.testsPort; delete config.testsPort; } + if ( config.afterSetup !== undefined ) { + removedRootOptions.afterSetup = config.afterSetup; + delete config.afterSetup; + } // Merge the root config and the environment configs together so that // we can ignore the root config and have full environment configs. diff --git a/packages/env/lib/config/test/__snapshots__/config-integration.js.snap b/packages/env/lib/config/test/__snapshots__/config-integration.js.snap index da4e1f4d3a0bc..914b0ec7cc0a4 100644 --- a/packages/env/lib/config/test/__snapshots__/config-integration.js.snap +++ b/packages/env/lib/config/test/__snapshots__/config-integration.js.snap @@ -2,6 +2,7 @@ exports[`Config Integration should load local and override configuration files 1`] = ` { + "afterSetup": null, "configDirectoryPath": "/test/gutenberg", "detectedLocalConfig": true, "dockerComposeConfigPath": "/cache/5fea4c5689ef6cc4a4e6eaaa39323338/docker-compose.yml", @@ -68,6 +69,7 @@ exports[`Config Integration should load local and override configuration files 1 exports[`Config Integration should load local configuration file 1`] = ` { + "afterSetup": "test", "configDirectoryPath": "/test/gutenberg", "detectedLocalConfig": true, "dockerComposeConfigPath": "/cache/5fea4c5689ef6cc4a4e6eaaa39323338/docker-compose.yml", @@ -134,6 +136,7 @@ exports[`Config Integration should load local configuration file 1`] = ` exports[`Config Integration should use default configuration 1`] = ` { + "afterSetup": null, "configDirectoryPath": "/test/gutenberg", "detectedLocalConfig": true, "dockerComposeConfigPath": "/cache/5fea4c5689ef6cc4a4e6eaaa39323338/docker-compose.yml", @@ -200,6 +203,7 @@ exports[`Config Integration should use default configuration 1`] = ` exports[`Config Integration should use environment variables over local and override configuration files 1`] = ` { + "afterSetup": "test", "configDirectoryPath": "/test/gutenberg", "detectedLocalConfig": true, "dockerComposeConfigPath": "/cache/5fea4c5689ef6cc4a4e6eaaa39323338/docker-compose.yml", diff --git a/packages/env/lib/config/test/add-or-replace-port.js b/packages/env/lib/config/test/add-or-replace-port.js index cba4642c19962..1c9794f0d0125 100644 --- a/packages/env/lib/config/test/add-or-replace-port.js +++ b/packages/env/lib/config/test/add-or-replace-port.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ diff --git a/packages/env/lib/config/test/config-integration.js b/packages/env/lib/config/test/config-integration.js index add5072c9eb09..08c3277f06a45 100644 --- a/packages/env/lib/config/test/config-integration.js +++ b/packages/env/lib/config/test/config-integration.js @@ -48,6 +48,7 @@ describe( 'Config Integration', () => { delete process.env.WP_ENV_HOME; delete process.env.WP_ENV_PORT; delete process.env.WP_ENV_TESTS_PORT; + delete process.env.WP_ENV_AFTER_SETUP; } ); it( 'should use default configuration', async () => { @@ -68,6 +69,7 @@ describe( 'Config Integration', () => { return JSON.stringify( { core: 'WordPress/WordPress#trunk', port: 123, + afterSetup: 'test', } ); } @@ -110,6 +112,7 @@ describe( 'Config Integration', () => { it( 'should use environment variables over local and override configuration files', async () => { process.env.WP_ENV_PORT = 12345; process.env.WP_ENV_TESTS_PORT = 61234; + process.env.WP_ENV_AFTER_SETUP = 'test'; readFile.mockImplementation( async ( fileName ) => { if ( fileName === '/test/gutenberg/.wp-env.json' ) { @@ -117,6 +120,7 @@ describe( 'Config Integration', () => { core: 'WordPress/WordPress#trunk', port: 123, testsPort: 456, + afterSetup: 'local', } ); } diff --git a/packages/env/lib/config/test/parse-config.js b/packages/env/lib/config/test/parse-config.js index eccb20a83c95c..ce5e28809ecd2 100644 --- a/packages/env/lib/config/test/parse-config.js +++ b/packages/env/lib/config/test/parse-config.js @@ -51,6 +51,7 @@ const DEFAULT_CONFIG = { WP_HOME: 'http://localhost', }, mappings: {}, + afterSetup: null, env: { development: {}, tests: { @@ -75,6 +76,7 @@ describe( 'parseConfig', () => { delete process.env.WP_ENV_TESTS_PORT; delete process.env.WP_ENV_CORE; delete process.env.WP_ENV_PHP_VERSION; + delete process.env.WP_ENV_AFTER_SETUP; } ); it( 'should return default config', async () => { @@ -139,6 +141,7 @@ describe( 'parseConfig', () => { return { core: 'WordPress/WordPress#Test', phpVersion: '1.0', + afterSetup: 'test', env: { development: { port: 1234, @@ -178,6 +181,7 @@ describe( 'parseConfig', () => { type: 'git', }, phpVersion: '2.0', + afterSetup: 'test', env: { development: { ...DEFAULT_CONFIG.env.development, @@ -266,6 +270,7 @@ describe( 'parseConfig', () => { process.env.WP_ENV_TESTS_PORT = 456; process.env.WP_ENV_CORE = 'WordPress/WordPress#test'; process.env.WP_ENV_PHP_VERSION = '3.0'; + process.env.WP_ENV_AFTER_SETUP = 'test after'; const parsed = await parseConfig( './', '/cache' ); @@ -283,6 +288,7 @@ describe( 'parseConfig', () => { type: 'git', }, phpVersion: '3.0', + afterSetup: 'test after', env: { development: { port: 123, @@ -324,8 +330,8 @@ describe( 'parseConfig', () => { expect.assertions( 1 ); try { await parseConfig( './', '/cache' ); - } catch ( e ) { - expect( e ).toEqual( + } catch ( error ) { + expect( error ).toEqual( new ValidationError( 'Could not find the latest WordPress version. There may be a network issue.' ) diff --git a/packages/env/lib/config/test/parse-source-string.js b/packages/env/lib/config/test/parse-source-string.js index a2a305833f4bf..a0ccc6eb6d3f7 100644 --- a/packages/env/lib/config/test/parse-source-string.js +++ b/packages/env/lib/config/test/parse-source-string.js @@ -33,8 +33,8 @@ describe( 'parseSourceString', () => { expect.assertions( 1 ); try { parseSourceString( 'test://test', options ); - } catch ( e ) { - expect( e ).toEqual( + } catch ( error ) { + expect( error ).toEqual( new ValidationError( 'Invalid or unrecognized source: "test://test".' ) diff --git a/packages/env/lib/config/test/post-process-config.js b/packages/env/lib/config/test/post-process-config.js index 0914b9acf1849..8559728b969d1 100644 --- a/packages/env/lib/config/test/post-process-config.js +++ b/packages/env/lib/config/test/post-process-config.js @@ -1,3 +1,4 @@ +'use strict'; /** * Internal dependencies */ @@ -9,7 +10,7 @@ describe( 'postProcessConfig', () => { jest.clearAllMocks(); } ); - it( 'should merge root options into environment options', () => { + it( 'should merge relevant root options into environment options', () => { const processed = postProcessConfig( { port: 123, testsPort: 456, @@ -151,6 +152,32 @@ describe( 'postProcessConfig', () => { } ); } ); + it( 'should not merge some root options into environment options', () => { + const processed = postProcessConfig( { + port: 8888, + testsPort: 8889, + afterSetup: 'test', + env: { + development: {}, + tests: {}, + }, + } ); + + expect( processed ).toEqual( { + port: 8888, + testsPort: 8889, + afterSetup: 'test', + env: { + development: { + port: 8888, + }, + tests: { + port: 8889, + }, + }, + } ); + } ); + describe( 'appendPortToWPConfigs', () => { it( 'should add port to certain environment config options', () => { const processed = postProcessConfig( { diff --git a/packages/env/lib/config/test/read-raw-config-file.js b/packages/env/lib/config/test/read-raw-config-file.js index b4607b135a559..135bc4cd4d9c4 100644 --- a/packages/env/lib/config/test/read-raw-config-file.js +++ b/packages/env/lib/config/test/read-raw-config-file.js @@ -36,8 +36,8 @@ describe( 'readRawConfigFile', () => { try { await readRawConfigFile( '/.wp-env.json' ); - } catch ( e ) { - expect( e ).toEqual( + } catch ( error ) { + expect( error ).toEqual( new ValidationError( 'Could not read .wp-env.json: Test' ) ); } diff --git a/packages/env/lib/config/test/validate-config.js b/packages/env/lib/config/test/validate-config.js index b612fbfb3549c..adcae2b90e241 100644 --- a/packages/env/lib/config/test/validate-config.js +++ b/packages/env/lib/config/test/validate-config.js @@ -1,8 +1,10 @@ +'use strict'; /** * Internal dependencies */ const { ValidationError, + checkString, checkPort, checkStringArray, checkObjectWithValues, @@ -11,13 +13,23 @@ const { } = require( '../validate-config' ); describe( 'validate-config', () => { - describe( 'checkPort', () => { - it( 'does nothing for undefined values', () => { + describe( 'checkString', () => { + it( 'throws when not a string', () => { + expect( () => checkString( 'test.json', 'test', 1234 ) ).toThrow( + new ValidationError( + 'Invalid test.json: "test" must be a string.' + ) + ); + } ); + + it( 'passes for string', () => { expect( () => - checkPort( 'test.json', 'test', undefined ) + checkString( 'test.json', 'test', 'test' ) ).not.toThrow(); } ); + } ); + describe( 'checkPort', () => { it( 'throws when not a number', () => { expect( () => checkPort( 'test.json', 'test', 'test' ) ).toThrow( new ValidationError( @@ -56,12 +68,6 @@ describe( 'validate-config', () => { } ); describe( 'checkStringArray', () => { - it( 'does nothing for undefined values', () => { - expect( () => - checkStringArray( 'test.json', 'test', undefined ) - ).not.toThrow(); - } ); - it( 'throws when not an array', () => { expect( () => checkStringArray( 'test.json', 'test', 'test' ) @@ -109,14 +115,6 @@ describe( 'validate-config', () => { } ); describe( 'checkObjectWithValues', () => { - it( 'does nothing for undefined values', () => { - expect( () => - checkObjectWithValues( 'test.json', 'test', undefined, [ - 'string', - ] ) - ).not.toThrow(); - } ); - it( 'throws when not an object', () => { expect( () => checkObjectWithValues( 'test.json', 'test', 'test', [] ) @@ -216,12 +214,6 @@ describe( 'validate-config', () => { } ); describe( 'checkVersion', () => { - it( 'does nothing for undefined values', () => { - expect( () => - checkVersion( 'test.json', 'test', undefined ) - ).not.toThrow(); - } ); - it( 'throws for invalid input', () => { expect( () => checkVersion( 'test.json', 'test', 'test' ) ).toThrow( new ValidationError( @@ -256,12 +248,6 @@ describe( 'validate-config', () => { } ); describe( 'checkValidURL', () => { - it( 'does nothing for undefined values', () => { - expect( () => - checkValidURL( 'test.json', 'test', undefined ) - ).not.toThrow(); - } ); - it( 'throws for invaid URLs', () => { expect( () => checkValidURL( 'test.json', 'test', 'localhost' ) diff --git a/packages/env/lib/config/validate-config.js b/packages/env/lib/config/validate-config.js index 7cadbeade4d51..02a673eea3cb8 100644 --- a/packages/env/lib/config/validate-config.js +++ b/packages/env/lib/config/validate-config.js @@ -10,6 +10,21 @@ */ class ValidationError extends Error {} +/** + * Validates that the value is a string. + * + * @param {string} configFile The configuration file we're validating. + * @param {string} configKey The configuration key we're validating. + * @param {number} value The value to check. + */ +function checkString( configFile, configKey, value ) { + if ( typeof value !== 'string' ) { + throw new ValidationError( + `Invalid ${ configFile }: "${ configKey }" must be a string.` + ); + } +} + /** * Validates the port and throws if it isn't valid. * @@ -18,10 +33,6 @@ class ValidationError extends Error {} * @param {number} port The port to check. */ function checkPort( configFile, configKey, port ) { - if ( port === undefined ) { - return; - } - if ( ! Number.isInteger( port ) ) { throw new ValidationError( `Invalid ${ configFile }: "${ configKey }" must be an integer.` @@ -45,10 +56,6 @@ function checkPort( configFile, configKey, port ) { * @param {string[]} array The array that we're checking. */ function checkStringArray( configFile, configKey, array ) { - if ( array === undefined ) { - return; - } - if ( ! Array.isArray( array ) ) { throw new ValidationError( `Invalid ${ configFile }: "${ configKey }" must be an array.` @@ -71,10 +78,6 @@ function checkStringArray( configFile, configKey, array ) { * @param {string[]} allowTypes The types that are allowed. */ function checkObjectWithValues( configFile, configKey, obj, allowTypes ) { - if ( obj === undefined ) { - return; - } - if ( allowTypes === undefined ) { allowTypes = []; } @@ -113,10 +116,6 @@ function checkObjectWithValues( configFile, configKey, obj, allowTypes ) { * @param {string} version The version that we're checking. */ function checkVersion( configFile, configKey, version ) { - if ( version === undefined || version === null ) { - return; - } - if ( typeof version !== 'string' ) { throw new ValidationError( `Invalid ${ configFile }: "${ configKey }" must be a string.` @@ -138,13 +137,9 @@ function checkVersion( configFile, configKey, version ) { * @param {string} url The URL that we're checking. */ function checkValidURL( configFile, configKey, url ) { - if ( url === undefined ) { - return; - } - try { new URL( url ); - } catch ( e ) { + } catch { throw new ValidationError( `Invalid ${ configFile }: "${ configKey }" must be a valid URL.` ); @@ -153,6 +148,7 @@ function checkValidURL( configFile, configKey, url ) { module.exports = { ValidationError, + checkString, checkPort, checkStringArray, checkObjectWithValues, diff --git a/packages/env/lib/env.js b/packages/env/lib/env.js index 3942a30710937..be093afe5a106 100644 --- a/packages/env/lib/env.js +++ b/packages/env/lib/env.js @@ -3,9 +3,11 @@ * Internal dependencies */ const { ValidationError } = require( './config' ); +const { AfterSetupError } = require( './execute-after-setup' ); const commands = require( './commands' ); module.exports = { ...commands, ValidationError, + AfterSetupError, }; diff --git a/packages/env/lib/execute-after-setup.js b/packages/env/lib/execute-after-setup.js new file mode 100644 index 0000000000000..09b642d2fef56 --- /dev/null +++ b/packages/env/lib/execute-after-setup.js @@ -0,0 +1,51 @@ +'use strict'; +/** + * External dependencies + */ +const { execSync } = require( 'child_process' ); + +/** + * @typedef {import('./config').WPConfig} WPConfig + */ + +/** + * Error subtype which indicates that the afterSetup command failed. + */ +class AfterSetupError extends Error {} + +/** + * Executes any defined afterSetup command. + * + * @param {WPConfig} config The config object to use. + * @param {Object} spinner A CLI spinner which indciates progress. + */ +function executeAfterSetup( config, spinner ) { + if ( ! config.afterSetup ) { + return; + } + + spinner.text = 'Executing Script: afterSetup'; + + try { + let output = execSync( config.afterSetup, { + encoding: 'utf-8', + stdio: 'pipe', + env: process.env, + } ); + + // Remove any trailing whitespace for nicer output. + output = output.trimRight(); + + // We don't need to bother with any output if there isn't any. + if ( output ) { + spinner.info( `After Setup:\n${ output }` ); + } + } catch ( error ) { + throw new AfterSetupError( `After Setup:\n${ error.stderr }` ); + } +} + +module.exports = { + AfterSetupError, + executeAfterSetup, +}; diff --git a/packages/env/lib/get-host-user.js b/packages/env/lib/get-host-user.js index ab88b3f728d6b..7c7f095de1715 100644 --- a/packages/env/lib/get-host-user.js +++ b/packages/env/lib/get-host-user.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/init-config.js b/packages/env/lib/init-config.js index ad46880042e43..659278eed2160 100644 --- a/packages/env/lib/init-config.js +++ b/packages/env/lib/init-config.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/md5.js b/packages/env/lib/md5.js index 2fd6b7c6a6bf2..9f37b5a4ede62 100644 --- a/packages/env/lib/md5.js +++ b/packages/env/lib/md5.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/lib/parse-xdebug-mode.js b/packages/env/lib/parse-xdebug-mode.js index 927b4f6e3f233..0fb781d786fba 100644 --- a/packages/env/lib/parse-xdebug-mode.js +++ b/packages/env/lib/parse-xdebug-mode.js @@ -1,3 +1,4 @@ +'use strict'; // See https://xdebug.org/docs/all_settings#mode const XDEBUG_MODES = [ 'develop', diff --git a/packages/env/lib/retry.js b/packages/env/lib/retry.js index 014e5b7bffe81..753a8123ead6a 100644 --- a/packages/env/lib/retry.js +++ b/packages/env/lib/retry.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ diff --git a/packages/env/test/__snapshots__/md5.js.snap b/packages/env/lib/test/__snapshots__/md5.js.snap similarity index 100% rename from packages/env/test/__snapshots__/md5.js.snap rename to packages/env/lib/test/__snapshots__/md5.js.snap diff --git a/packages/env/test/build-docker-compose-config.js b/packages/env/lib/test/build-docker-compose-config.js similarity index 96% rename from packages/env/test/build-docker-compose-config.js rename to packages/env/lib/test/build-docker-compose-config.js index 444589d6ad637..50f5b2e42d0fa 100644 --- a/packages/env/test/build-docker-compose-config.js +++ b/packages/env/lib/test/build-docker-compose-config.js @@ -1,8 +1,9 @@ +'use strict'; /** * Internal dependencies */ -const buildDockerComposeConfig = require( '../lib/build-docker-compose-config' ); -const getHostUser = require( '../lib/get-host-user' ); +const buildDockerComposeConfig = require( '../build-docker-compose-config' ); +const getHostUser = require( '../get-host-user' ); // The basic config keys which build docker compose config requires. const CONFIG = { @@ -13,7 +14,7 @@ const CONFIG = { configDirectoryPath: '/path/to/config', }; -jest.mock( '../lib/get-host-user', () => jest.fn() ); +jest.mock( '../get-host-user', () => jest.fn() ); getHostUser.mockImplementation( () => { return { name: 'test', diff --git a/packages/env/test/cache.js b/packages/env/lib/test/cache.js similarity index 99% rename from packages/env/test/cache.js rename to packages/env/lib/test/cache.js index 3b7f17d11e1f5..63da7ec47d70b 100644 --- a/packages/env/test/cache.js +++ b/packages/env/lib/test/cache.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */ @@ -11,7 +12,7 @@ const { setCache, getCache, getCacheFile, -} = require( '../lib/cache' ); +} = require( '../cache' ); jest.mock( 'fs', () => ( { promises: { diff --git a/packages/env/test/cli.js b/packages/env/lib/test/cli.js similarity index 91% rename from packages/env/test/cli.js rename to packages/env/lib/test/cli.js index 9319750518095..336d254493682 100644 --- a/packages/env/test/cli.js +++ b/packages/env/lib/test/cli.js @@ -2,8 +2,8 @@ /** * Internal dependencies */ -const cli = require( '../lib/cli' ); -const env = require( '../lib/env' ); +const cli = require( '../cli' ); +const env = require( '../env' ); /** * Mocked dependencies @@ -14,13 +14,17 @@ jest.mock( 'ora', () => () => ( { return { text: '', succeed: jest.fn(), fail: jest.fn() }; }, } ) ); -jest.mock( '../lib/env', () => ( { - start: jest.fn( Promise.resolve.bind( Promise ) ), - stop: jest.fn( Promise.resolve.bind( Promise ) ), - clean: jest.fn( Promise.resolve.bind( Promise ) ), - run: jest.fn( Promise.resolve.bind( Promise ) ), - ValidationError: jest.requireActual( '../lib/env' ).ValidationError, -} ) ); +jest.mock( '../env', () => { + const actual = jest.requireActual( '../env' ); + return { + start: jest.fn( Promise.resolve.bind( Promise ) ), + stop: jest.fn( Promise.resolve.bind( Promise ) ), + clean: jest.fn( Promise.resolve.bind( Promise ) ), + run: jest.fn( Promise.resolve.bind( Promise ) ), + ValidationError: actual.ValidationError, + AfterSetupError: actual.AfterSetupError, + }; +} ); describe( 'env cli', () => { beforeEach( jest.clearAllMocks ); diff --git a/packages/env/lib/test/execute-after-setup.js b/packages/env/lib/test/execute-after-setup.js new file mode 100644 index 0000000000000..4ea0e8fd9bfdd --- /dev/null +++ b/packages/env/lib/test/execute-after-setup.js @@ -0,0 +1,66 @@ +'use strict'; +/** + * External dependencies + */ +const { execSync } = require( 'child_process' ); + +/** + * Internal dependencies + */ +const { + AfterSetupError, + executeAfterSetup, +} = require( '../execute-after-setup' ); + +jest.mock( 'child_process', () => ( { + execSync: jest.fn(), +} ) ); + +describe( 'executeAfterSetup', () => { + const spinner = { + info: jest.fn(), + }; + + afterEach( () => { + jest.clearAllMocks(); + } ); + + it( 'should do nothing without afterSetup option', () => { + executeAfterSetup( { afterSetup: null }, spinner ); + + expect( spinner.info ).not.toHaveBeenCalled(); + } ); + + it( 'should run afterSetup option and print output without extra whitespace', () => { + execSync.mockReturnValue( 'Test \n' ); + + executeAfterSetup( { afterSetup: 'Test Setup' }, spinner ); + + expect( execSync ).toHaveBeenCalled(); + expect( execSync.mock.calls[ 0 ][ 0 ] ).toEqual( 'Test Setup' ); + expect( spinner.info ).toHaveBeenCalledWith( 'After Setup:\nTest' ); + } ); + + it( 'should print nothing if afterSetup returns no output', () => { + execSync.mockReturnValue( '' ); + + executeAfterSetup( { afterSetup: 'Test Setup' }, spinner ); + + expect( execSync ).toHaveBeenCalled(); + expect( execSync.mock.calls[ 0 ][ 0 ] ).toEqual( 'Test Setup' ); + expect( spinner.info ).not.toHaveBeenCalled(); + } ); + + it( 'should throw AfterSetupError when process errors', () => { + execSync.mockImplementation( ( command ) => { + expect( command ).toEqual( 'Test Setup' ); + throw { stderr: 'Something bad happened.' }; + } ); + + expect( () => + executeAfterSetup( { afterSetup: 'Test Setup' }, spinner ) + ).toThrow( + new AfterSetupError( 'After Setup:\nSomething bad happened.' ) + ); + } ); +} ); diff --git a/packages/env/test/md5.js b/packages/env/lib/test/md5.js similarity index 94% rename from packages/env/test/md5.js rename to packages/env/lib/test/md5.js index 2d07a589c1768..ad40f0040f16c 100644 --- a/packages/env/test/md5.js +++ b/packages/env/lib/test/md5.js @@ -1,7 +1,8 @@ +'use strict'; /** * Internal dependencies */ -const md5 = require( '../lib/md5' ); +const md5 = require( '../md5' ); describe( 'md5', () => { it( 'creates a hash of a string', () => { diff --git a/packages/env/test/parse-xdebug-mode.js b/packages/env/lib/test/parse-xdebug-mode.js similarity index 94% rename from packages/env/test/parse-xdebug-mode.js rename to packages/env/lib/test/parse-xdebug-mode.js index 454611cd40d43..c84ad16bb81c3 100644 --- a/packages/env/test/parse-xdebug-mode.js +++ b/packages/env/lib/test/parse-xdebug-mode.js @@ -1,7 +1,8 @@ +'use strict'; /** * Internal dependencies */ -const parseXdebugMode = require( '../lib/parse-xdebug-mode' ); +const parseXdebugMode = require( '../parse-xdebug-mode' ); describe( 'parseXdebugMode', () => { it( 'throws an error if the passed value is neither a string nor undefined', () => { diff --git a/packages/env/lib/wordpress.js b/packages/env/lib/wordpress.js index 7039e41f327fd..f238288498cf5 100644 --- a/packages/env/lib/wordpress.js +++ b/packages/env/lib/wordpress.js @@ -1,3 +1,4 @@ +'use strict'; /** * External dependencies */