@wordpress/env 4.8.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +25 -13
- package/lib/build-docker-compose-config.js +33 -8
- package/lib/cli.js +53 -49
- package/lib/commands/run.js +6 -6
- package/lib/commands/start.js +22 -2
- package/lib/config/config.js +32 -20
- package/lib/config/test/__snapshots__/config.js.snap +4 -6
- package/lib/config/test/config.js +89 -57
- package/lib/download-sources.js +3 -3
- package/lib/download-wp-phpunit.js +140 -0
- package/lib/wordpress.js +59 -14
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 5.1.0 (2022-08-10)
|
|
6
|
+
|
|
7
|
+
### Enhancement
|
|
8
|
+
- Previously, wp-env used the WordPress version provided by Docker in the WordPress image for installations which don't specify a WordPress version. Now, wp-env will find the latest stable version on WordPress.org and check out the https://github.com/WordPress/WordPress repository at the tag matching that version. In most cases, this will match what Docker provides. The benefit is that wp-env (and WordPress.org) now controls the default WordPress version rather than Docker.
|
|
9
|
+
|
|
10
|
+
### Bug Fix
|
|
11
|
+
- Downloading a default WordPress version also resolves a bug where the wrong WordPress test files were used if no core source was specified in wp-env.json. The current trunk test files were downloaded rather than the stable version. Now, the test files will match the default stable version.
|
|
12
|
+
|
|
13
|
+
## 5.0.0 (2022-07-27)
|
|
14
|
+
|
|
15
|
+
### Breaking Changes
|
|
16
|
+
- Removed the `WP_PHPUNIT__TESTS_CONFIG` environment variable from the `phpunit` container. **This removes automatic support for the `wp-phpunit/wp-phpunit` Composer package. To continue using the package, set the following two environment variables in your `phpunit.xml` file or similar: `WP_TESTS_DIR=""` and `WP_PHPUNIT__TESTS_CONFIG="/wordpress-phpunit/wp-tests-config.php"`.**
|
|
17
|
+
- Removed the generated `/var/www/html/phpunit-wp-config.php` file from the environment.
|
|
18
|
+
|
|
19
|
+
### Enhancement
|
|
20
|
+
- Read WordPress' version and include the corresponding PHPUnit test files in the environment.
|
|
21
|
+
- Set the `WP_TESTS_DIR` environment variable in all containers to point at the PHPUnit test files.
|
|
22
|
+
|
|
23
|
+
### Bug Fix
|
|
24
|
+
- Restrict `WP_TESTS_DOMAIN` constant to just hostname rather than an entire URL (e.g. it now excludes scheme, port, etc.) ([#41039](https://github.com/WordPress/gutenberg/pull/41039)).
|
|
25
|
+
|
|
5
26
|
## 4.8.0 (2022-06-01)
|
|
27
|
+
|
|
6
28
|
### Enhancement
|
|
7
29
|
- Removed the need for quotation marks when passing options to `wp-env run`.
|
|
8
30
|
- Setting a `config` key to `null` will prevent adding the constant to `wp-config.php` even if a default value is defined by `wp-env`.
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ The local environment will be available at http://localhost:8888 (Username: `adm
|
|
|
16
16
|
|
|
17
17
|
## Prerequisites
|
|
18
18
|
|
|
19
|
-
`wp-env` requires Docker to be installed. There are instructions available for installing Docker on [Windows
|
|
19
|
+
`wp-env` requires Docker to be installed. There are instructions available for installing Docker on [Windows](https://docs.docker.com/desktop/install/windows-install/), [macOS](https://docs.docker.com/docker-for-mac/install/), and [Linux](https://docs.docker.com/desktop/install/linux-install/).
|
|
20
20
|
|
|
21
21
|
Node.js and NPM are required. The latest LTS version of Node.js is used to develop `wp-env` and is recommended.
|
|
22
22
|
|
|
@@ -40,7 +40,9 @@ If your project already has a package.json, it's also possible to use `wp-env` a
|
|
|
40
40
|
$ npm i @wordpress/env --save-dev
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
At this point, you can use the local, project-level version of wp-env via [`npx`](https://www.npmjs.com/package/npx), a utility automatically installed with `npm`.`npx` finds binaries like wp-env installed through node modules. As an example: `npx wp-env start --update`.
|
|
44
|
+
|
|
45
|
+
If you don't wish to use `npx`, modify your package.json and add an extra command to npm `scripts` (https://docs.npmjs.com/misc/scripts):
|
|
44
46
|
|
|
45
47
|
```json
|
|
46
48
|
"scripts": {
|
|
@@ -51,7 +53,7 @@ Then modify your package.json and add an extra command to npm `scripts` (https:/
|
|
|
51
53
|
When installing `wp-env` in this way, all `wp-env` commands detailed in these docs must be prefixed with `npm run`, for example:
|
|
52
54
|
|
|
53
55
|
```sh
|
|
54
|
-
# You must add another double dash to pass
|
|
56
|
+
# You must add another double dash to pass flags to the script (wp-env) rather than to npm itself
|
|
55
57
|
$ npm run wp-env start -- --update
|
|
56
58
|
```
|
|
57
59
|
|
|
@@ -117,15 +119,14 @@ Running `docker ps` and inspecting the `PORTS` column allows you to determine wh
|
|
|
117
119
|
|
|
118
120
|
You may also specify the port numbers in your `.wp-env.json` file, but the environment variables take precedent.
|
|
119
121
|
|
|
120
|
-
### 3. Restart `wp-env`
|
|
122
|
+
### 3. Restart `wp-env` with updates
|
|
121
123
|
|
|
122
124
|
Restarting `wp-env` will restart the underlying Docker containers which can fix many issues.
|
|
123
125
|
|
|
124
|
-
To restart `wp-env
|
|
126
|
+
To restart `wp-env`, just run `wp-env start` again. It will automatically stop and start the container. If you also pass the `--update` argument, it will download updates and configure WordPress agian.
|
|
125
127
|
|
|
126
128
|
```sh
|
|
127
|
-
$ wp-env
|
|
128
|
-
$ wp-env start
|
|
129
|
+
$ wp-env start --update
|
|
129
130
|
```
|
|
130
131
|
|
|
131
132
|
### 4. Restart Docker
|
|
@@ -156,16 +157,17 @@ $ wp-env clean all
|
|
|
156
157
|
$ wp-env start
|
|
157
158
|
```
|
|
158
159
|
|
|
159
|
-
### 6.
|
|
160
|
+
### 6. Destroy everything and start again 🔥
|
|
160
161
|
|
|
161
|
-
When all else fails, you can use `wp-env destroy` to forcibly remove all of the underlying Docker containers and
|
|
162
|
+
When all else fails, you can use `wp-env destroy` to forcibly remove all of the underlying Docker containers, volumes, and files. This will allow you to start from scratch.
|
|
162
163
|
|
|
163
|
-
To
|
|
164
|
+
To do so:
|
|
164
165
|
|
|
165
166
|
**⚠️ WARNING: This will permanently delete any posts, pages, media, etc. in the local WordPress installation.**
|
|
166
167
|
|
|
167
168
|
```sh
|
|
168
169
|
$ wp-env destroy
|
|
170
|
+
# This new instance is a fresh start with no existing data:
|
|
169
171
|
$ wp-env start
|
|
170
172
|
```
|
|
171
173
|
|
|
@@ -188,6 +190,14 @@ wp-env start --debug
|
|
|
188
190
|
...
|
|
189
191
|
```
|
|
190
192
|
|
|
193
|
+
## Using included WordPress PHPUnit test files
|
|
194
|
+
|
|
195
|
+
Out of the box `wp-env` includes the [WordPress' PHPUnit test files](https://develop.svn.wordpress.org/trunk/tests/phpunit/) corresponding to the version of WordPress installed. There is an environment variable, `WP_TESTS_DIR`, which points to the location of these files within each container. By including these files in the environment, we remove the need for you to use a package or install and mount them yourself. If you do not want to use these files, you should ignore the `WP_TESTS_DIR` environment variable and load them from the location of your choosing.
|
|
196
|
+
|
|
197
|
+
### Customizing the `wp-tests-config.php` file
|
|
198
|
+
|
|
199
|
+
While we do provide a default `wp-tests-config.php` file within the environment, there may be cases where you want to use your own. WordPress provides a `WP_TESTS_CONFIG_FILE_PATH` constant that you can use to change the `wp-config.php` file used for testing. Set this to a desired path in your `bootstrap.php` file and the file you've chosen will be used instead of the one included in the environment.
|
|
200
|
+
|
|
191
201
|
## Using Xdebug
|
|
192
202
|
|
|
193
203
|
Xdebug is installed in the wp-env environment, but it is turned off by default. To enable Xdebug, you can use the `--xdebug` flag with the `wp-env start` command. Here is a reference to how the flag works:
|
|
@@ -203,10 +213,12 @@ wp-env start
|
|
|
203
213
|
wp-env start --xdebug=profile,trace,debug
|
|
204
214
|
```
|
|
205
215
|
|
|
206
|
-
When you're running `wp-env` using `npm run`, like when working in the Gutenberg repo or when
|
|
216
|
+
When you're running `wp-env` using `npm run`, like when working in the Gutenberg repo or when `wp-env` is a local project dependency, don't forget to add an extra double dash before the `--xdebug` command:
|
|
207
217
|
|
|
208
218
|
```sh
|
|
209
219
|
npm run wp-env start -- --xdebug
|
|
220
|
+
# Alternatively, use npx:
|
|
221
|
+
npx wp-env start --xdebug
|
|
210
222
|
```
|
|
211
223
|
|
|
212
224
|
If you forget about that, the `--xdebug` parameter will be passed to NPM instead of the `wp-env start` command and it will be ignored.
|
|
@@ -511,7 +523,7 @@ SCRIPT_DEBUG: true,
|
|
|
511
523
|
WP_PHP_BINARY: 'php',
|
|
512
524
|
WP_TESTS_EMAIL: 'admin@example.org',
|
|
513
525
|
WP_TESTS_TITLE: 'Test Blog',
|
|
514
|
-
WP_TESTS_DOMAIN: '
|
|
526
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
515
527
|
WP_SITEURL: 'http://localhost',
|
|
516
528
|
WP_HOME: 'http://localhost',
|
|
517
529
|
```
|
|
@@ -524,7 +536,7 @@ Additionally, the values referencing a URL include the specified port for the gi
|
|
|
524
536
|
|
|
525
537
|
### Examples
|
|
526
538
|
|
|
527
|
-
#### Latest
|
|
539
|
+
#### Latest stable WordPress + current directory as a plugin
|
|
528
540
|
|
|
529
541
|
This is useful for plugin development.
|
|
530
542
|
|
|
@@ -19,13 +19,18 @@ const { dbEnv } = require( './config' );
|
|
|
19
19
|
/**
|
|
20
20
|
* Gets the volume mounts for an individual service.
|
|
21
21
|
*
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {
|
|
24
|
-
*
|
|
22
|
+
* @param {string} workDirectoryPath The working directory for wp-env.
|
|
23
|
+
* @param {WPServiceConfig} config The service config to get the mounts from.
|
|
24
|
+
* @param {string} wordpressDefault The default internal path for the WordPress
|
|
25
|
+
* source code (such as tests-wordpress).
|
|
25
26
|
*
|
|
26
27
|
* @return {string[]} An array of volumes to mount in string format.
|
|
27
28
|
*/
|
|
28
|
-
function getMounts(
|
|
29
|
+
function getMounts(
|
|
30
|
+
workDirectoryPath,
|
|
31
|
+
config,
|
|
32
|
+
wordpressDefault = 'wordpress'
|
|
33
|
+
) {
|
|
29
34
|
// Top-level WordPress directory mounts (like wp-content/themes)
|
|
30
35
|
const directoryMounts = Object.entries( config.mappings ).map(
|
|
31
36
|
( [ wpDir, source ] ) => `${ source.path }:/var/www/html/${ wpDir }`
|
|
@@ -45,9 +50,19 @@ function getMounts( config, wordpressDefault = 'wordpress' ) {
|
|
|
45
50
|
config.coreSource ? config.coreSource.path : wordpressDefault
|
|
46
51
|
}:/var/www/html`;
|
|
47
52
|
|
|
53
|
+
const corePHPUnitMount = `${ path.join(
|
|
54
|
+
workDirectoryPath,
|
|
55
|
+
wordpressDefault === 'wordpress'
|
|
56
|
+
? 'WordPress-PHPUnit'
|
|
57
|
+
: 'tests-WordPress-PHPUnit',
|
|
58
|
+
'tests',
|
|
59
|
+
'phpunit'
|
|
60
|
+
) }:/wordpress-phpunit`;
|
|
61
|
+
|
|
48
62
|
return [
|
|
49
63
|
...new Set( [
|
|
50
64
|
coreMount,
|
|
65
|
+
corePHPUnitMount,
|
|
51
66
|
...directoryMounts,
|
|
52
67
|
...pluginMounts,
|
|
53
68
|
...themeMounts,
|
|
@@ -64,8 +79,15 @@ function getMounts( config, wordpressDefault = 'wordpress' ) {
|
|
|
64
79
|
* @return {Object} A docker-compose config object, ready to serialize into YAML.
|
|
65
80
|
*/
|
|
66
81
|
module.exports = function buildDockerComposeConfig( config ) {
|
|
67
|
-
const developmentMounts = getMounts(
|
|
68
|
-
|
|
82
|
+
const developmentMounts = getMounts(
|
|
83
|
+
config.workDirectoryPath,
|
|
84
|
+
config.env.development
|
|
85
|
+
);
|
|
86
|
+
const testsMounts = getMounts(
|
|
87
|
+
config.workDirectoryPath,
|
|
88
|
+
config.env.tests,
|
|
89
|
+
'tests-wordpress'
|
|
90
|
+
);
|
|
69
91
|
|
|
70
92
|
// When both tests and development reference the same WP source, we need to
|
|
71
93
|
// ensure that tests pulls from a copy of the files so that it maintains
|
|
@@ -208,6 +230,7 @@ module.exports = function buildDockerComposeConfig( config ) {
|
|
|
208
230
|
environment: {
|
|
209
231
|
...dbEnv.credentials,
|
|
210
232
|
...dbEnv.development,
|
|
233
|
+
WP_TESTS_DIR: '/wordpress-phpunit',
|
|
211
234
|
},
|
|
212
235
|
volumes: developmentMounts,
|
|
213
236
|
},
|
|
@@ -218,6 +241,7 @@ module.exports = function buildDockerComposeConfig( config ) {
|
|
|
218
241
|
environment: {
|
|
219
242
|
...dbEnv.credentials,
|
|
220
243
|
...dbEnv.tests,
|
|
244
|
+
WP_TESTS_DIR: '/wordpress-phpunit',
|
|
221
245
|
},
|
|
222
246
|
volumes: testsMounts,
|
|
223
247
|
},
|
|
@@ -229,6 +253,7 @@ module.exports = function buildDockerComposeConfig( config ) {
|
|
|
229
253
|
environment: {
|
|
230
254
|
...dbEnv.credentials,
|
|
231
255
|
...dbEnv.development,
|
|
256
|
+
WP_TESTS_DIR: '/wordpress-phpunit',
|
|
232
257
|
},
|
|
233
258
|
},
|
|
234
259
|
'tests-cli': {
|
|
@@ -239,6 +264,7 @@ module.exports = function buildDockerComposeConfig( config ) {
|
|
|
239
264
|
environment: {
|
|
240
265
|
...dbEnv.credentials,
|
|
241
266
|
...dbEnv.tests,
|
|
267
|
+
WP_TESTS_DIR: '/wordpress-phpunit',
|
|
242
268
|
},
|
|
243
269
|
},
|
|
244
270
|
composer: {
|
|
@@ -256,8 +282,7 @@ module.exports = function buildDockerComposeConfig( config ) {
|
|
|
256
282
|
],
|
|
257
283
|
environment: {
|
|
258
284
|
LOCAL_DIR: 'html',
|
|
259
|
-
|
|
260
|
-
'/var/www/html/phpunit-wp-config.php',
|
|
285
|
+
WP_TESTS_DIR: '/wordpress-phpunit',
|
|
261
286
|
...dbEnv.credentials,
|
|
262
287
|
...dbEnv.tests,
|
|
263
288
|
},
|
package/lib/cli.js
CHANGED
|
@@ -22,57 +22,61 @@ const wpRed = boldWhite.bgHex( '#d94f4f' );
|
|
|
22
22
|
const wpYellow = boldWhite.bgHex( '#f0b849' );
|
|
23
23
|
|
|
24
24
|
// Spinner.
|
|
25
|
-
const withSpinner =
|
|
26
|
-
|
|
27
|
-
args
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
( error ) => {
|
|
40
|
-
if ( error instanceof env.ValidationError ) {
|
|
41
|
-
// Error is a validation error. That means the user did something wrong.
|
|
42
|
-
spinner.fail( error.message );
|
|
43
|
-
process.exit( 1 );
|
|
44
|
-
} else if (
|
|
45
|
-
error &&
|
|
46
|
-
typeof error === 'object' &&
|
|
47
|
-
'exitCode' in error &&
|
|
48
|
-
'err' in error &&
|
|
49
|
-
'out' in error
|
|
50
|
-
) {
|
|
51
|
-
// Error is a docker-compose error. That means something docker-related failed.
|
|
52
|
-
// https://github.com/PDMLab/docker-compose/blob/HEAD/src/index.ts
|
|
53
|
-
spinner.fail( 'Error while running docker-compose command.' );
|
|
54
|
-
if ( error.out ) {
|
|
55
|
-
process.stdout.write( error.out );
|
|
56
|
-
}
|
|
57
|
-
if ( error.err ) {
|
|
58
|
-
process.stderr.write( error.err );
|
|
59
|
-
}
|
|
60
|
-
process.exit( error.exitCode );
|
|
61
|
-
} else if ( error ) {
|
|
62
|
-
// Error is an unknown error. That means there was a bug in our code.
|
|
63
|
-
spinner.fail(
|
|
64
|
-
typeof error === 'string' ? error : error.message
|
|
25
|
+
const withSpinner =
|
|
26
|
+
( command ) =>
|
|
27
|
+
( ...args ) => {
|
|
28
|
+
const spinner = ora().start();
|
|
29
|
+
args[ 0 ].spinner = spinner;
|
|
30
|
+
let time = process.hrtime();
|
|
31
|
+
return command( ...args ).then(
|
|
32
|
+
( message ) => {
|
|
33
|
+
time = process.hrtime( time );
|
|
34
|
+
spinner.succeed(
|
|
35
|
+
`${ message || spinner.text } (in ${ time[ 0 ] }s ${ (
|
|
36
|
+
time[ 1 ] / 1e6
|
|
37
|
+
).toFixed( 0 ) }ms)`
|
|
65
38
|
);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
39
|
+
process.exit( 0 );
|
|
40
|
+
},
|
|
41
|
+
( error ) => {
|
|
42
|
+
if ( error instanceof env.ValidationError ) {
|
|
43
|
+
// Error is a validation error. That means the user did something wrong.
|
|
44
|
+
spinner.fail( error.message );
|
|
45
|
+
process.exit( 1 );
|
|
46
|
+
} else if (
|
|
47
|
+
error &&
|
|
48
|
+
typeof error === 'object' &&
|
|
49
|
+
'exitCode' in error &&
|
|
50
|
+
'err' in error &&
|
|
51
|
+
'out' in error
|
|
52
|
+
) {
|
|
53
|
+
// Error is a docker-compose error. That means something docker-related failed.
|
|
54
|
+
// https://github.com/PDMLab/docker-compose/blob/HEAD/src/index.ts
|
|
55
|
+
spinner.fail(
|
|
56
|
+
'Error while running docker-compose command.'
|
|
57
|
+
);
|
|
58
|
+
if ( error.out ) {
|
|
59
|
+
process.stdout.write( error.out );
|
|
60
|
+
}
|
|
61
|
+
if ( error.err ) {
|
|
62
|
+
process.stderr.write( error.err );
|
|
63
|
+
}
|
|
64
|
+
process.exit( error.exitCode );
|
|
65
|
+
} else if ( error ) {
|
|
66
|
+
// Error is an unknown error. That means there was a bug in our code.
|
|
67
|
+
spinner.fail(
|
|
68
|
+
typeof error === 'string' ? error : error.message
|
|
69
|
+
);
|
|
70
|
+
// Disable reason: Using console.error() means we get a stack trace.
|
|
71
|
+
console.error( error );
|
|
72
|
+
process.exit( 1 );
|
|
73
|
+
} else {
|
|
74
|
+
spinner.fail( 'An unknown error occured.' );
|
|
75
|
+
process.exit( 1 );
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
78
|
+
);
|
|
79
|
+
};
|
|
76
80
|
|
|
77
81
|
module.exports = function cli() {
|
|
78
82
|
// Do nothing if Docker is unavailable.
|
package/lib/commands/run.js
CHANGED
|
@@ -9,7 +9,7 @@ const { spawn } = require( 'child_process' );
|
|
|
9
9
|
const initConfig = require( '../init-config' );
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* @typedef {import('../config').
|
|
12
|
+
* @typedef {import('../config').WPConfig} WPConfig
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -42,11 +42,11 @@ module.exports = async function run( { container, command, spinner, debug } ) {
|
|
|
42
42
|
/**
|
|
43
43
|
* Runs an arbitrary command on the given Docker container.
|
|
44
44
|
*
|
|
45
|
-
* @param {Object}
|
|
46
|
-
* @param {string}
|
|
47
|
-
* @param {string}
|
|
48
|
-
* @param {
|
|
49
|
-
* @param {Object}
|
|
45
|
+
* @param {Object} options
|
|
46
|
+
* @param {string} options.container The Docker container to run the command on.
|
|
47
|
+
* @param {string} options.command The command to run.
|
|
48
|
+
* @param {WPConfig} options.config The wp-env configuration.
|
|
49
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
50
50
|
*/
|
|
51
51
|
function spawnCommandDirectly( { container, command, config, spinner } ) {
|
|
52
52
|
const composeCommand = [
|
package/lib/commands/start.js
CHANGED
|
@@ -21,16 +21,18 @@ const retry = require( '../retry' );
|
|
|
21
21
|
const stop = require( './stop' );
|
|
22
22
|
const initConfig = require( '../init-config' );
|
|
23
23
|
const downloadSources = require( '../download-sources' );
|
|
24
|
+
const downloadWPPHPUnit = require( '../download-wp-phpunit' );
|
|
24
25
|
const {
|
|
25
26
|
checkDatabaseConnection,
|
|
26
27
|
configureWordPress,
|
|
27
28
|
setupWordPressDirectories,
|
|
29
|
+
readWordPressVersion,
|
|
28
30
|
} = require( '../wordpress' );
|
|
29
31
|
const { didCacheChange, setCache } = require( '../cache' );
|
|
30
32
|
const md5 = require( '../md5' );
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
|
-
* @typedef {import('../config').
|
|
35
|
+
* @typedef {import('../config').WPConfig} WPConfig
|
|
34
36
|
*/
|
|
35
37
|
const CONFIG_CACHE_KEY = 'config_checksum';
|
|
36
38
|
|
|
@@ -127,7 +129,25 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) {
|
|
|
127
129
|
] );
|
|
128
130
|
|
|
129
131
|
if ( shouldConfigureWp ) {
|
|
132
|
+
spinner.text = 'Setting up WordPress directories';
|
|
133
|
+
|
|
130
134
|
await setupWordPressDirectories( config );
|
|
135
|
+
|
|
136
|
+
// Use the WordPress versions to download the PHPUnit suite.
|
|
137
|
+
const wpVersions = await Promise.all( [
|
|
138
|
+
readWordPressVersion(
|
|
139
|
+
config.env.development.coreSource,
|
|
140
|
+
spinner,
|
|
141
|
+
debug
|
|
142
|
+
),
|
|
143
|
+
readWordPressVersion( config.env.tests.coreSource, spinner, debug ),
|
|
144
|
+
] );
|
|
145
|
+
await downloadWPPHPUnit(
|
|
146
|
+
config,
|
|
147
|
+
{ development: wpVersions[ 0 ], tests: wpVersions[ 1 ] },
|
|
148
|
+
spinner,
|
|
149
|
+
debug
|
|
150
|
+
);
|
|
131
151
|
}
|
|
132
152
|
|
|
133
153
|
spinner.text = 'Starting WordPress.';
|
|
@@ -173,7 +193,7 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) {
|
|
|
173
193
|
}
|
|
174
194
|
|
|
175
195
|
const siteUrl = config.env.development.config.WP_SITEURL;
|
|
176
|
-
const e2eSiteUrl = config.env.tests.config.WP_TESTS_DOMAIN
|
|
196
|
+
const e2eSiteUrl = `http://${ config.env.tests.config.WP_TESTS_DOMAIN }:${ config.env.tests.port }/`;
|
|
177
197
|
|
|
178
198
|
const { out: mySQLAddress } = await dockerCompose.port(
|
|
179
199
|
'mysql',
|
package/lib/config/config.js
CHANGED
|
@@ -15,6 +15,7 @@ const readRawConfigFile = require( './read-raw-config-file' );
|
|
|
15
15
|
const parseConfig = require( './parse-config' );
|
|
16
16
|
const { includeTestsPath, parseSourceString } = parseConfig;
|
|
17
17
|
const md5 = require( '../md5' );
|
|
18
|
+
const { getLatestWordPressVersion } = require( '../wordpress' );
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* wp-env configuration.
|
|
@@ -33,7 +34,7 @@ const md5 = require( '../md5' );
|
|
|
33
34
|
* Base-level config for any particular environment. (development/tests/etc)
|
|
34
35
|
*
|
|
35
36
|
* @typedef WPServiceConfig
|
|
36
|
-
* @property {
|
|
37
|
+
* @property {WPSource} coreSource The WordPress installation to load in the environment.
|
|
37
38
|
* @property {WPSource[]} pluginSources Plugins to load in the environment.
|
|
38
39
|
* @property {WPSource[]} themeSources Themes to load in the environment.
|
|
39
40
|
* @property {number} port The port to use.
|
|
@@ -68,9 +69,37 @@ module.exports = async function readConfig( configPath ) {
|
|
|
68
69
|
md5( configPath )
|
|
69
70
|
);
|
|
70
71
|
|
|
72
|
+
// The specified base configuration from .wp-env.json or from the local
|
|
73
|
+
// source type which was automatically detected.
|
|
74
|
+
const baseConfig =
|
|
75
|
+
( await readRawConfigFile( '.wp-env.json', configPath ) ) ||
|
|
76
|
+
( await getDefaultBaseConfig( configPath ) );
|
|
77
|
+
|
|
78
|
+
// Overriden .wp-env.json on a per-user case.
|
|
79
|
+
const overrideConfig =
|
|
80
|
+
( await readRawConfigFile(
|
|
81
|
+
'.wp-env.override.json',
|
|
82
|
+
configPath.replace( /\.wp-env\.json$/, '.wp-env.override.json' )
|
|
83
|
+
) ) || {};
|
|
84
|
+
|
|
85
|
+
const detectedLocalConfig =
|
|
86
|
+
Object.keys( { ...baseConfig, ...overrideConfig } ).length > 0;
|
|
87
|
+
|
|
88
|
+
// If there is no local WordPress version, use the latest stable version from GitHub.
|
|
89
|
+
let coreRef;
|
|
90
|
+
if ( ! overrideConfig.core && ! baseConfig.core ) {
|
|
91
|
+
const wpVersion = await getLatestWordPressVersion();
|
|
92
|
+
if ( ! wpVersion ) {
|
|
93
|
+
throw new ValidationError(
|
|
94
|
+
'Could not find the latest WordPress version. There may be a network issue.'
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
coreRef = `WordPress/WordPress#${ wpVersion }`;
|
|
98
|
+
}
|
|
99
|
+
|
|
71
100
|
// Default configuration which is overridden by .wp-env.json files.
|
|
72
101
|
const defaultConfiguration = {
|
|
73
|
-
core:
|
|
102
|
+
core: coreRef,
|
|
74
103
|
phpVersion: null,
|
|
75
104
|
plugins: [],
|
|
76
105
|
themes: [],
|
|
@@ -83,7 +112,7 @@ module.exports = async function readConfig( configPath ) {
|
|
|
83
112
|
WP_PHP_BINARY: 'php',
|
|
84
113
|
WP_TESTS_EMAIL: 'admin@example.org',
|
|
85
114
|
WP_TESTS_TITLE: 'Test Blog',
|
|
86
|
-
WP_TESTS_DOMAIN: '
|
|
115
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
87
116
|
WP_SITEURL: 'http://localhost',
|
|
88
117
|
WP_HOME: 'http://localhost',
|
|
89
118
|
},
|
|
@@ -96,22 +125,6 @@ module.exports = async function readConfig( configPath ) {
|
|
|
96
125
|
},
|
|
97
126
|
};
|
|
98
127
|
|
|
99
|
-
// The specified base configuration from .wp-env.json or from the local
|
|
100
|
-
// source type which was automatically detected.
|
|
101
|
-
const baseConfig =
|
|
102
|
-
( await readRawConfigFile( '.wp-env.json', configPath ) ) ||
|
|
103
|
-
( await getDefaultBaseConfig( configPath ) );
|
|
104
|
-
|
|
105
|
-
// Overriden .wp-env.json on a per-user case.
|
|
106
|
-
const overrideConfig =
|
|
107
|
-
( await readRawConfigFile(
|
|
108
|
-
'.wp-env.override.json',
|
|
109
|
-
configPath.replace( /\.wp-env\.json$/, '.wp-env.override.json' )
|
|
110
|
-
) ) || {};
|
|
111
|
-
|
|
112
|
-
const detectedLocalConfig =
|
|
113
|
-
Object.keys( { ...baseConfig, ...overrideConfig } ).length > 0;
|
|
114
|
-
|
|
115
128
|
// A quick validation before merging on a service by service level allows us
|
|
116
129
|
// to check the root configuration options and provide more helpful errors.
|
|
117
130
|
validateConfig(
|
|
@@ -297,7 +310,6 @@ function withOverrides( config ) {
|
|
|
297
310
|
};
|
|
298
311
|
|
|
299
312
|
// Update wp config options to include the correct port number in the URL.
|
|
300
|
-
updateEnvUrl( 'WP_TESTS_DOMAIN' );
|
|
301
313
|
updateEnvUrl( 'WP_SITEURL' );
|
|
302
314
|
updateEnvUrl( 'WP_HOME' );
|
|
303
315
|
|
|
@@ -17,11 +17,10 @@ Object {
|
|
|
17
17
|
"WP_HOME": "http://localhost:2000/",
|
|
18
18
|
"WP_PHP_BINARY": "php",
|
|
19
19
|
"WP_SITEURL": "http://localhost:2000/",
|
|
20
|
-
"WP_TESTS_DOMAIN": "
|
|
20
|
+
"WP_TESTS_DOMAIN": "localhost",
|
|
21
21
|
"WP_TESTS_EMAIL": "admin@example.org",
|
|
22
22
|
"WP_TESTS_TITLE": "Test Blog",
|
|
23
23
|
},
|
|
24
|
-
"coreSource": null,
|
|
25
24
|
"mappings": Object {},
|
|
26
25
|
"phpVersion": null,
|
|
27
26
|
"pluginSources": Array [],
|
|
@@ -40,11 +39,10 @@ Object {
|
|
|
40
39
|
"WP_HOME": "http://localhost:1000/",
|
|
41
40
|
"WP_PHP_BINARY": "php",
|
|
42
41
|
"WP_SITEURL": "http://localhost:1000/",
|
|
43
|
-
"WP_TESTS_DOMAIN": "
|
|
42
|
+
"WP_TESTS_DOMAIN": "localhost",
|
|
44
43
|
"WP_TESTS_EMAIL": "admin@example.org",
|
|
45
44
|
"WP_TESTS_TITLE": "Test Blog",
|
|
46
45
|
},
|
|
47
|
-
"coreSource": null,
|
|
48
46
|
"mappings": Object {},
|
|
49
47
|
"phpVersion": null,
|
|
50
48
|
"pluginSources": Array [],
|
|
@@ -64,7 +62,7 @@ Object {
|
|
|
64
62
|
"WP_HOME": "http://localhost:8889/",
|
|
65
63
|
"WP_PHP_BINARY": "php",
|
|
66
64
|
"WP_SITEURL": "http://localhost:8889/",
|
|
67
|
-
"WP_TESTS_DOMAIN": "
|
|
65
|
+
"WP_TESTS_DOMAIN": "localhost",
|
|
68
66
|
"WP_TESTS_EMAIL": "admin@example.org",
|
|
69
67
|
"WP_TESTS_TITLE": "Test Blog",
|
|
70
68
|
}
|
|
@@ -78,7 +76,7 @@ Object {
|
|
|
78
76
|
"WP_HOME": "http://localhost:8888/",
|
|
79
77
|
"WP_PHP_BINARY": "php",
|
|
80
78
|
"WP_SITEURL": "http://localhost:8888/",
|
|
81
|
-
"WP_TESTS_DOMAIN": "
|
|
79
|
+
"WP_TESTS_DOMAIN": "localhost",
|
|
82
80
|
"WP_TESTS_EMAIL": "admin@example.org",
|
|
83
81
|
"WP_TESTS_TITLE": "Test Blog",
|
|
84
82
|
}
|
|
@@ -19,6 +19,23 @@ jest.mock( 'fs', () => ( {
|
|
|
19
19
|
},
|
|
20
20
|
} ) );
|
|
21
21
|
|
|
22
|
+
// This mocks a small response with a format matching the stable-check API.
|
|
23
|
+
// It makes getLatestWordPressVersion resolve to "100.0.0".
|
|
24
|
+
jest.mock( 'got', () =>
|
|
25
|
+
jest.fn( ( url ) => ( {
|
|
26
|
+
json: () => {
|
|
27
|
+
if ( url === 'https://api.wordpress.org/core/stable-check/1.0/' ) {
|
|
28
|
+
return Promise.resolve( {
|
|
29
|
+
'1.0': 'insecure',
|
|
30
|
+
'99.1.1': 'outdated',
|
|
31
|
+
'100.0.0': 'latest',
|
|
32
|
+
'100.0.1': 'fancy',
|
|
33
|
+
} );
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
} ) )
|
|
37
|
+
);
|
|
38
|
+
|
|
22
39
|
jest.mock( '../detect-directory-type', () => jest.fn() );
|
|
23
40
|
|
|
24
41
|
describe( 'readConfig', () => {
|
|
@@ -59,19 +76,38 @@ describe( 'readConfig', () => {
|
|
|
59
76
|
);
|
|
60
77
|
detectDirectoryType.mockImplementation( () => 'core' );
|
|
61
78
|
const config = await readConfig( '.wp-env.json' );
|
|
62
|
-
expect( config.env.development.coreSource ).
|
|
79
|
+
expect( config.env.development.coreSource.type ).toBe( 'local' );
|
|
63
80
|
expect( config.env.tests.coreSource ).not.toBeNull();
|
|
64
81
|
expect( config.env.development.pluginSources ).toHaveLength( 0 );
|
|
65
82
|
expect( config.env.development.themeSources ).toHaveLength( 0 );
|
|
66
83
|
} );
|
|
67
84
|
|
|
85
|
+
it( 'should use the most recent stable WordPress version for the default core source', async () => {
|
|
86
|
+
readFile.mockImplementation( () =>
|
|
87
|
+
Promise.resolve( JSON.stringify( {} ) )
|
|
88
|
+
);
|
|
89
|
+
const config = await readConfig( '.wp-env.json' );
|
|
90
|
+
|
|
91
|
+
const expected = {
|
|
92
|
+
url: 'https://github.com/WordPress/WordPress.git',
|
|
93
|
+
type: 'git',
|
|
94
|
+
basename: 'WordPress',
|
|
95
|
+
ref: '100.0.0', // From the mock of https at the top of the file.
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
expect( config.env.development.coreSource ).toMatchObject(
|
|
99
|
+
expected
|
|
100
|
+
);
|
|
101
|
+
expect( config.env.tests.coreSource ).toMatchObject( expected );
|
|
102
|
+
} );
|
|
103
|
+
|
|
68
104
|
it( 'should infer a plugin config when ran from a plugin directory', async () => {
|
|
69
105
|
readFile.mockImplementation( () =>
|
|
70
106
|
Promise.reject( { code: 'ENOENT' } )
|
|
71
107
|
);
|
|
72
108
|
detectDirectoryType.mockImplementation( () => 'plugin' );
|
|
73
109
|
const config = await readConfig( '.wp-env.json' );
|
|
74
|
-
expect( config.env.development.coreSource ).
|
|
110
|
+
expect( config.env.development.coreSource.type ).toBe( 'git' );
|
|
75
111
|
expect( config.env.development.pluginSources ).toHaveLength( 1 );
|
|
76
112
|
expect( config.env.tests.pluginSources ).toHaveLength( 1 );
|
|
77
113
|
expect( config.env.development.themeSources ).toHaveLength( 0 );
|
|
@@ -83,8 +119,8 @@ describe( 'readConfig', () => {
|
|
|
83
119
|
);
|
|
84
120
|
detectDirectoryType.mockImplementation( () => 'theme' );
|
|
85
121
|
const config = await readConfig( '.wp-env.json' );
|
|
86
|
-
expect( config.env.development.coreSource ).
|
|
87
|
-
expect( config.env.tests.coreSource ).
|
|
122
|
+
expect( config.env.development.coreSource.type ).toBe( 'git' );
|
|
123
|
+
expect( config.env.tests.coreSource.type ).toBe( 'git' );
|
|
88
124
|
expect( config.env.development.themeSources ).toHaveLength( 1 );
|
|
89
125
|
expect( config.env.tests.themeSources ).toHaveLength( 1 );
|
|
90
126
|
expect( config.env.development.pluginSources ).toHaveLength( 0 );
|
|
@@ -197,6 +233,11 @@ describe( 'readConfig', () => {
|
|
|
197
233
|
// Remove generated values which are different on other machines.
|
|
198
234
|
delete config.dockerComposeConfigPath;
|
|
199
235
|
delete config.workDirectoryPath;
|
|
236
|
+
|
|
237
|
+
// This encodes both the version of WordPress (which can change frequently)
|
|
238
|
+
// as well as the wp-env directory which is unique on every machine.
|
|
239
|
+
delete config.env.development.coreSource;
|
|
240
|
+
delete config.env.tests.coreSource;
|
|
200
241
|
expect( config ).toMatchSnapshot();
|
|
201
242
|
} );
|
|
202
243
|
} );
|
|
@@ -265,17 +306,17 @@ describe( 'readConfig', () => {
|
|
|
265
306
|
pluginSources: [
|
|
266
307
|
{
|
|
267
308
|
type: 'local',
|
|
268
|
-
path: expect.stringMatching( /^(
|
|
309
|
+
path: expect.stringMatching( /^(\/|\\).*relative$/ ),
|
|
269
310
|
basename: 'relative',
|
|
270
311
|
},
|
|
271
312
|
{
|
|
272
313
|
type: 'local',
|
|
273
|
-
path: expect.stringMatching( /^(
|
|
314
|
+
path: expect.stringMatching( /^(\/|\\).*parent$/ ),
|
|
274
315
|
basename: 'parent',
|
|
275
316
|
},
|
|
276
317
|
{
|
|
277
318
|
type: 'local',
|
|
278
|
-
path: expect.stringMatching( /^(
|
|
319
|
+
path: expect.stringMatching( /^(\/|\\).*home$/ ),
|
|
279
320
|
basename: 'home',
|
|
280
321
|
},
|
|
281
322
|
],
|
|
@@ -284,17 +325,17 @@ describe( 'readConfig', () => {
|
|
|
284
325
|
pluginSources: [
|
|
285
326
|
{
|
|
286
327
|
type: 'local',
|
|
287
|
-
path: expect.stringMatching( /^(
|
|
328
|
+
path: expect.stringMatching( /^(\/|\\).*relative$/ ),
|
|
288
329
|
basename: 'relative',
|
|
289
330
|
},
|
|
290
331
|
{
|
|
291
332
|
type: 'local',
|
|
292
|
-
path: expect.stringMatching( /^(
|
|
333
|
+
path: expect.stringMatching( /^(\/|\\).*parent$/ ),
|
|
293
334
|
basename: 'parent',
|
|
294
335
|
},
|
|
295
336
|
{
|
|
296
337
|
type: 'local',
|
|
297
|
-
path: expect.stringMatching( /^(
|
|
338
|
+
path: expect.stringMatching( /^(\/|\\).*home$/ ),
|
|
298
339
|
basename: 'home',
|
|
299
340
|
},
|
|
300
341
|
],
|
|
@@ -324,28 +365,28 @@ describe( 'readConfig', () => {
|
|
|
324
365
|
expect( config.env.development.pluginSources ).toEqual( [
|
|
325
366
|
{
|
|
326
367
|
type: 'local',
|
|
327
|
-
path: expect.stringMatching( /^(
|
|
368
|
+
path: expect.stringMatching( /^(\/|\\).*test1a$/ ),
|
|
328
369
|
basename: 'test1a',
|
|
329
370
|
},
|
|
330
371
|
] );
|
|
331
372
|
expect( config.env.development.themeSources ).toEqual( [
|
|
332
373
|
{
|
|
333
374
|
type: 'local',
|
|
334
|
-
path: expect.stringMatching( /^(
|
|
375
|
+
path: expect.stringMatching( /^(\/|\\).*test2a$/ ),
|
|
335
376
|
basename: 'test2a',
|
|
336
377
|
},
|
|
337
378
|
] );
|
|
338
379
|
expect( config.env.tests.pluginSources ).toEqual( [
|
|
339
380
|
{
|
|
340
381
|
type: 'local',
|
|
341
|
-
path: expect.stringMatching( /^(
|
|
382
|
+
path: expect.stringMatching( /^(\/|\\).*test1b$/ ),
|
|
342
383
|
basename: 'test1b',
|
|
343
384
|
},
|
|
344
385
|
] );
|
|
345
386
|
expect( config.env.tests.themeSources ).toEqual( [
|
|
346
387
|
{
|
|
347
388
|
type: 'local',
|
|
348
|
-
path: expect.stringMatching( /^(
|
|
389
|
+
path: expect.stringMatching( /^(\/|\\).*test2b$/ ),
|
|
349
390
|
basename: 'test2b',
|
|
350
391
|
},
|
|
351
392
|
] );
|
|
@@ -359,18 +400,18 @@ describe( 'readConfig', () => {
|
|
|
359
400
|
expect( config.env.development ).toMatchObject( {
|
|
360
401
|
coreSource: {
|
|
361
402
|
type: 'local',
|
|
362
|
-
path: expect.stringMatching( /^(
|
|
403
|
+
path: expect.stringMatching( /^(\/|\\).*relative$/ ),
|
|
363
404
|
testsPath: expect.stringMatching(
|
|
364
|
-
/^(
|
|
405
|
+
/^(\/|\\).*tests-relative$/
|
|
365
406
|
),
|
|
366
407
|
},
|
|
367
408
|
} );
|
|
368
409
|
expect( config.env.tests ).toMatchObject( {
|
|
369
410
|
coreSource: {
|
|
370
411
|
type: 'local',
|
|
371
|
-
path: expect.stringMatching( /^(
|
|
412
|
+
path: expect.stringMatching( /^(\/|\\).*relative$/ ),
|
|
372
413
|
testsPath: expect.stringMatching(
|
|
373
|
-
/^(
|
|
414
|
+
/^(\/|\\).*tests-relative$/
|
|
374
415
|
),
|
|
375
416
|
},
|
|
376
417
|
} );
|
|
@@ -396,30 +437,29 @@ describe( 'readConfig', () => {
|
|
|
396
437
|
type: 'git',
|
|
397
438
|
url: 'https://github.com/WordPress/gutenberg.git',
|
|
398
439
|
ref: undefined,
|
|
399
|
-
path: expect.stringMatching( /^(
|
|
440
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
400
441
|
basename: 'gutenberg',
|
|
401
442
|
},
|
|
402
443
|
{
|
|
403
444
|
type: 'git',
|
|
404
445
|
url: 'https://github.com/WordPress/gutenberg.git',
|
|
405
446
|
ref: 'trunk',
|
|
406
|
-
path: expect.stringMatching( /^(
|
|
447
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
407
448
|
basename: 'gutenberg',
|
|
408
449
|
},
|
|
409
450
|
{
|
|
410
451
|
type: 'git',
|
|
411
452
|
url: 'https://github.com/WordPress/gutenberg.git',
|
|
412
453
|
ref: '5.0',
|
|
413
|
-
path: expect.stringMatching( /^(
|
|
454
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
414
455
|
basename: 'gutenberg',
|
|
415
456
|
},
|
|
416
457
|
{
|
|
417
458
|
type: 'git',
|
|
418
|
-
url:
|
|
419
|
-
'https://github.com/WordPress/theme-experiments.git',
|
|
459
|
+
url: 'https://github.com/WordPress/theme-experiments.git',
|
|
420
460
|
ref: 'tt1-blocks@0.4.3',
|
|
421
461
|
path: expect.stringMatching(
|
|
422
|
-
/^(
|
|
462
|
+
/^(\/|\\).*theme-experiments(\/|\\)tt1-blocks$/
|
|
423
463
|
),
|
|
424
464
|
basename: 'tt1-blocks',
|
|
425
465
|
},
|
|
@@ -447,33 +487,29 @@ describe( 'readConfig', () => {
|
|
|
447
487
|
pluginSources: [
|
|
448
488
|
{
|
|
449
489
|
type: 'zip',
|
|
450
|
-
url:
|
|
451
|
-
|
|
452
|
-
path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
|
|
490
|
+
url: 'https://downloads.wordpress.org/plugin/gutenberg.zip',
|
|
491
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
453
492
|
basename: 'gutenberg',
|
|
454
493
|
},
|
|
455
494
|
{
|
|
456
495
|
type: 'zip',
|
|
457
|
-
url:
|
|
458
|
-
|
|
459
|
-
path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
|
|
496
|
+
url: 'https://downloads.wordpress.org/plugin/gutenberg.8.1.0.zip',
|
|
497
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
460
498
|
basename: 'gutenberg',
|
|
461
499
|
},
|
|
462
500
|
{
|
|
463
501
|
type: 'zip',
|
|
464
|
-
url:
|
|
465
|
-
'https://downloads.wordpress.org/theme/twentytwenty.zip',
|
|
502
|
+
url: 'https://downloads.wordpress.org/theme/twentytwenty.zip',
|
|
466
503
|
path: expect.stringMatching(
|
|
467
|
-
/^(
|
|
504
|
+
/^(\/|\\).*twentytwenty$/
|
|
468
505
|
),
|
|
469
506
|
basename: 'twentytwenty',
|
|
470
507
|
},
|
|
471
508
|
{
|
|
472
509
|
type: 'zip',
|
|
473
|
-
url:
|
|
474
|
-
'https://downloads.wordpress.org/theme/twentytwenty.1.3.zip',
|
|
510
|
+
url: 'https://downloads.wordpress.org/theme/twentytwenty.1.3.zip',
|
|
475
511
|
path: expect.stringMatching(
|
|
476
|
-
/^(
|
|
512
|
+
/^(\/|\\).*twentytwenty$/
|
|
477
513
|
),
|
|
478
514
|
basename: 'twentytwenty',
|
|
479
515
|
},
|
|
@@ -502,35 +538,31 @@ describe( 'readConfig', () => {
|
|
|
502
538
|
pluginSources: [
|
|
503
539
|
{
|
|
504
540
|
type: 'zip',
|
|
505
|
-
url:
|
|
506
|
-
|
|
507
|
-
path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
|
|
541
|
+
url: 'https://www.example.com/test/path/to/gutenberg.zip',
|
|
542
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
508
543
|
basename: 'gutenberg',
|
|
509
544
|
},
|
|
510
545
|
{
|
|
511
546
|
type: 'zip',
|
|
512
|
-
url:
|
|
513
|
-
'https://www.example.com/test/path/to/gutenberg.8.1.0.zip',
|
|
547
|
+
url: 'https://www.example.com/test/path/to/gutenberg.8.1.0.zip',
|
|
514
548
|
path: expect.stringMatching(
|
|
515
|
-
/^(
|
|
549
|
+
/^(\/|\\).*gutenberg.8.1.0$/
|
|
516
550
|
),
|
|
517
551
|
basename: 'gutenberg.8.1.0',
|
|
518
552
|
},
|
|
519
553
|
{
|
|
520
554
|
type: 'zip',
|
|
521
|
-
url:
|
|
522
|
-
'https://www.example.com/test/path/to/twentytwenty.zip',
|
|
555
|
+
url: 'https://www.example.com/test/path/to/twentytwenty.zip',
|
|
523
556
|
path: expect.stringMatching(
|
|
524
|
-
/^(
|
|
557
|
+
/^(\/|\\).*twentytwenty$/
|
|
525
558
|
),
|
|
526
559
|
basename: 'twentytwenty',
|
|
527
560
|
},
|
|
528
561
|
{
|
|
529
562
|
type: 'zip',
|
|
530
|
-
url:
|
|
531
|
-
'https://www.example.com/test/path/to/twentytwenty.1.3.zip',
|
|
563
|
+
url: 'https://www.example.com/test/path/to/twentytwenty.1.3.zip',
|
|
532
564
|
path: expect.stringMatching(
|
|
533
|
-
/^(
|
|
565
|
+
/^(\/|\\).*twentytwenty.1.3$/
|
|
534
566
|
),
|
|
535
567
|
basename: 'twentytwenty.1.3',
|
|
536
568
|
},
|
|
@@ -538,7 +570,7 @@ describe( 'readConfig', () => {
|
|
|
538
570
|
type: 'zip',
|
|
539
571
|
url: 'https://example.com/twentytwenty.1.3.zip',
|
|
540
572
|
path: expect.stringMatching(
|
|
541
|
-
/^(
|
|
573
|
+
/^(\/|\\).*twentytwenty.1.3$/
|
|
542
574
|
),
|
|
543
575
|
basename: 'twentytwenty.1.3',
|
|
544
576
|
},
|
|
@@ -580,12 +612,12 @@ describe( 'readConfig', () => {
|
|
|
580
612
|
const matchObj = {
|
|
581
613
|
test: {
|
|
582
614
|
type: 'local',
|
|
583
|
-
path: expect.stringMatching( /^(
|
|
615
|
+
path: expect.stringMatching( /^(\/|\\).*relative$/ ),
|
|
584
616
|
basename: 'relative',
|
|
585
617
|
},
|
|
586
618
|
test2: {
|
|
587
619
|
type: 'git',
|
|
588
|
-
path: expect.stringMatching( /^(
|
|
620
|
+
path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
|
|
589
621
|
basename: 'gutenberg',
|
|
590
622
|
},
|
|
591
623
|
};
|
|
@@ -813,7 +845,7 @@ describe( 'readConfig', () => {
|
|
|
813
845
|
development: {
|
|
814
846
|
port: 1000,
|
|
815
847
|
config: {
|
|
816
|
-
WP_TESTS_DOMAIN: '
|
|
848
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
817
849
|
WP_SITEURL: 'http://localhost:1000/',
|
|
818
850
|
WP_HOME: 'http://localhost:1000/',
|
|
819
851
|
},
|
|
@@ -821,7 +853,7 @@ describe( 'readConfig', () => {
|
|
|
821
853
|
tests: {
|
|
822
854
|
port: 2000,
|
|
823
855
|
config: {
|
|
824
|
-
WP_TESTS_DOMAIN: '
|
|
856
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
825
857
|
WP_SITEURL: 'http://localhost:2000/',
|
|
826
858
|
WP_HOME: 'http://localhost:2000/',
|
|
827
859
|
},
|
|
@@ -849,7 +881,7 @@ describe( 'readConfig', () => {
|
|
|
849
881
|
development: {
|
|
850
882
|
port: 1000,
|
|
851
883
|
config: {
|
|
852
|
-
WP_TESTS_DOMAIN: '
|
|
884
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
853
885
|
WP_SITEURL: 'http://localhost:1000/',
|
|
854
886
|
WP_HOME: 'http://localhost:3000/',
|
|
855
887
|
},
|
|
@@ -857,7 +889,7 @@ describe( 'readConfig', () => {
|
|
|
857
889
|
tests: {
|
|
858
890
|
port: 2000,
|
|
859
891
|
config: {
|
|
860
|
-
WP_TESTS_DOMAIN: '
|
|
892
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
861
893
|
WP_SITEURL: 'http://localhost:2000/',
|
|
862
894
|
WP_HOME: 'http://localhost:3000/',
|
|
863
895
|
},
|
|
@@ -1112,7 +1144,7 @@ describe( 'readConfig', () => {
|
|
|
1112
1144
|
WP_PHP_BINARY: 'php',
|
|
1113
1145
|
WP_TESTS_EMAIL: 'admin@example.org',
|
|
1114
1146
|
WP_TESTS_TITLE: 'Test Blog',
|
|
1115
|
-
WP_TESTS_DOMAIN: '
|
|
1147
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
1116
1148
|
WP_SITEURL: 'http://localhost:8889/',
|
|
1117
1149
|
WP_HOME: 'http://localhost:8889/',
|
|
1118
1150
|
} );
|
|
@@ -1126,7 +1158,7 @@ describe( 'readConfig', () => {
|
|
|
1126
1158
|
WP_PHP_BINARY: 'php',
|
|
1127
1159
|
WP_TESTS_EMAIL: 'admin@example.org',
|
|
1128
1160
|
WP_TESTS_TITLE: 'Test Blog',
|
|
1129
|
-
WP_TESTS_DOMAIN: '
|
|
1161
|
+
WP_TESTS_DOMAIN: 'localhost',
|
|
1130
1162
|
WP_SITEURL: 'http://localhost:8888/',
|
|
1131
1163
|
WP_HOME: 'http://localhost:8888/',
|
|
1132
1164
|
} );
|
package/lib/download-sources.js
CHANGED
|
@@ -16,7 +16,7 @@ const extractZip = util.promisify( require( 'extract-zip' ) );
|
|
|
16
16
|
const rimraf = util.promisify( require( 'rimraf' ) );
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @typedef {import('./config').
|
|
19
|
+
* @typedef {import('./config').WPConfig} WPConfig
|
|
20
20
|
* @typedef {import('./config').WPSource} WPSource
|
|
21
21
|
*/
|
|
22
22
|
|
|
@@ -24,8 +24,8 @@ const rimraf = util.promisify( require( 'rimraf' ) );
|
|
|
24
24
|
* Download each source for each environment. If the same source is used in
|
|
25
25
|
* multiple environments, it will only be downloaded once.
|
|
26
26
|
*
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {Object}
|
|
27
|
+
* @param {WPConfig} config The wp-env configuration object.
|
|
28
|
+
* @param {Object} spinner The spinner object to show progress.
|
|
29
29
|
* @return {Promise} Returns a promise which resolves when the downloads finish.
|
|
30
30
|
*/
|
|
31
31
|
module.exports = function downloadSources( config, spinner ) {
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const SimpleGit = require( 'simple-git' );
|
|
6
|
+
const fs = require( 'fs' );
|
|
7
|
+
const path = require( 'path' );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import('./config').WPConfig} WPConfig
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Downloads the WordPress PHPUnit files for each environment into the appropriate directories.
|
|
15
|
+
*
|
|
16
|
+
* @param {WPConfig} config The wp-env config object.
|
|
17
|
+
* @param {Object} wpVersions The WordPress versions for each environment.
|
|
18
|
+
* @param {Object} spinner The spinner object to show progress.
|
|
19
|
+
* @param {boolean} debug Indicates whether or not debug mode is active.
|
|
20
|
+
* @return {Promise} Returns a promise which resolves when the downloads finish.
|
|
21
|
+
*/
|
|
22
|
+
module.exports = function downloadWPPHPUnit(
|
|
23
|
+
config,
|
|
24
|
+
wpVersions,
|
|
25
|
+
spinner,
|
|
26
|
+
debug
|
|
27
|
+
) {
|
|
28
|
+
const progresses = {};
|
|
29
|
+
const getProgressSetter = ( id ) => ( progress ) => {
|
|
30
|
+
progresses[ id ] = progress;
|
|
31
|
+
spinner.text =
|
|
32
|
+
'Downloading WordPress PHPUnit Suite.\n' +
|
|
33
|
+
Object.entries( progresses )
|
|
34
|
+
.map(
|
|
35
|
+
( [ key, value ] ) =>
|
|
36
|
+
` - ${ key }: ${ ( value * 100 ).toFixed( 0 ) }/100%`
|
|
37
|
+
)
|
|
38
|
+
.join( '\n' );
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const promises = [];
|
|
42
|
+
for ( const env in config.env ) {
|
|
43
|
+
const wpVersion = wpVersions[ env ] ? wpVersions[ env ] : null;
|
|
44
|
+
const directory = path.join(
|
|
45
|
+
config.workDirectoryPath,
|
|
46
|
+
env === 'development'
|
|
47
|
+
? 'WordPress-PHPUnit'
|
|
48
|
+
: 'tests-WordPress-PHPUnit'
|
|
49
|
+
);
|
|
50
|
+
promises.push(
|
|
51
|
+
downloadTestSuite( directory, wpVersion, {
|
|
52
|
+
onProgress: getProgressSetter,
|
|
53
|
+
spinner,
|
|
54
|
+
debug,
|
|
55
|
+
} )
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return Promise.all( promises );
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Downloads the PHPUnit tests for a given WordPress version into the appropriate directory.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} directory The directory to place the PHPUnit tests in.
|
|
66
|
+
* @param {string} wpVersion The version of WordPress to install PHPUnit tests for. Trunk when empty.
|
|
67
|
+
* @param {Object} options
|
|
68
|
+
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
|
|
69
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
70
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
71
|
+
*/
|
|
72
|
+
async function downloadTestSuite(
|
|
73
|
+
directory,
|
|
74
|
+
wpVersion,
|
|
75
|
+
{ onProgress, spinner, debug }
|
|
76
|
+
) {
|
|
77
|
+
const log = debug
|
|
78
|
+
? ( message ) => {
|
|
79
|
+
spinner.info( `SimpleGit: ${ message }` );
|
|
80
|
+
spinner.start();
|
|
81
|
+
}
|
|
82
|
+
: () => {};
|
|
83
|
+
onProgress( 0 );
|
|
84
|
+
|
|
85
|
+
const progressHandler = ( { progress } ) => {
|
|
86
|
+
onProgress( progress / 100 );
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Make sure that the version is in X.X.X format. This is required
|
|
90
|
+
// because WordPress/wordpress-develop uses X.X.X tags but
|
|
91
|
+
// WordPress uses X.X for non-patch releases.
|
|
92
|
+
if ( wpVersion && wpVersion.match( /^[0-9]+.[0-9]+$/ ) ) {
|
|
93
|
+
wpVersion += '.0';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
log( 'Cloning or getting the PHPUnit suite from GitHub.' );
|
|
97
|
+
const git = SimpleGit( { progress: progressHandler } );
|
|
98
|
+
|
|
99
|
+
const isRepo =
|
|
100
|
+
fs.existsSync( directory ) &&
|
|
101
|
+
( await git.cwd( directory ).checkIsRepo( 'root' ) );
|
|
102
|
+
|
|
103
|
+
if ( isRepo ) {
|
|
104
|
+
log( 'Repo already exists, using it.' );
|
|
105
|
+
} else {
|
|
106
|
+
await git.clone(
|
|
107
|
+
'https://github.com/WordPress/wordpress-develop.git',
|
|
108
|
+
directory,
|
|
109
|
+
{
|
|
110
|
+
'--depth': '1',
|
|
111
|
+
'--no-checkout': null,
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
await git.cwd( directory );
|
|
115
|
+
|
|
116
|
+
// We use a sparse checkout to minimize the amount of data we need to download.
|
|
117
|
+
log( 'Enabling sparse checkout.' );
|
|
118
|
+
await git.raw( 'sparse-checkout', 'set', '--cone', 'tests/phpunit' );
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Figure out the ref that we need to checkout to get the correct version of the PHPUnit library.
|
|
122
|
+
// Alpha, Beta, and RC versions are bleeding edge and should pull from trunk.
|
|
123
|
+
let ref;
|
|
124
|
+
const fetchRaw = [];
|
|
125
|
+
if ( ! wpVersion || wpVersion.match( /-(?:alpha|beta|rc)/ ) ) {
|
|
126
|
+
ref = 'trunk';
|
|
127
|
+
fetchRaw.push( 'fetch', 'origin', ref, '--depth', '1' );
|
|
128
|
+
} else {
|
|
129
|
+
ref = `tags/${ wpVersion }`;
|
|
130
|
+
fetchRaw.push( 'fetch', 'origin', 'tag', wpVersion, '--depth', '1' );
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
log( `Fetching ${ ref }.` );
|
|
134
|
+
await git.raw( fetchRaw );
|
|
135
|
+
|
|
136
|
+
log( `Checking out ${ ref }.` );
|
|
137
|
+
await git.checkout( ref );
|
|
138
|
+
|
|
139
|
+
onProgress( 1 );
|
|
140
|
+
}
|
package/lib/wordpress.js
CHANGED
|
@@ -5,6 +5,7 @@ const dockerCompose = require( 'docker-compose' );
|
|
|
5
5
|
const util = require( 'util' );
|
|
6
6
|
const fs = require( 'fs' ).promises;
|
|
7
7
|
const path = require( 'path' );
|
|
8
|
+
const got = require( 'got' );
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Promisified dependencies
|
|
@@ -14,6 +15,7 @@ const copyDir = util.promisify( require( 'copy-dir' ) );
|
|
|
14
15
|
/**
|
|
15
16
|
* @typedef {import('./config').WPConfig} WPConfig
|
|
16
17
|
* @typedef {import('./config').WPServiceConfig} WPServiceConfig
|
|
18
|
+
* @typedef {import('./config').WPSource} WPSource
|
|
17
19
|
* @typedef {'development'|'tests'} WPEnvironment
|
|
18
20
|
* @typedef {'development'|'tests'|'all'} WPEnvironmentSelection
|
|
19
21
|
*/
|
|
@@ -101,25 +103,15 @@ async function configureWordPress( environment, config, spinner ) {
|
|
|
101
103
|
}
|
|
102
104
|
);
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* we load it too early, then some things (like MULTISITE) will be defined
|
|
108
|
-
* before wp-phpunit has a chance to configure them. To avoid this, create a
|
|
109
|
-
* copy of wp-config.php for phpunit which doesn't require wp-settings.php.
|
|
110
|
-
*
|
|
111
|
-
* Note that This needs to be executed using `exec` on the wordpress service
|
|
112
|
-
* so that file permissions work properly.
|
|
113
|
-
*
|
|
114
|
-
* This will be removed in the future. @see https://github.com/WordPress/gutenberg/issues/23171
|
|
115
|
-
*
|
|
116
|
-
*/
|
|
106
|
+
// WordPress' PHPUnit suite expects a `wp-tests-config.php` in
|
|
107
|
+
// the directory that the test suite is contained within.
|
|
108
|
+
// Make sure ABSPATH points to the WordPress install.
|
|
117
109
|
await dockerCompose.exec(
|
|
118
110
|
environment === 'development' ? 'wordpress' : 'tests-wordpress',
|
|
119
111
|
[
|
|
120
112
|
'sh',
|
|
121
113
|
'-c',
|
|
122
|
-
|
|
114
|
+
`sed -e "/^require.*wp-settings.php/d" -e "s/define( 'ABSPATH', __DIR__ . '\\/' );/define( 'ABSPATH', '\\/var\\/www\\/html\\/' );\\n\\tdefine( 'WP_DEFAULT_THEME', 'default' );/" /var/www/html/wp-config.php > /wordpress-phpunit/wp-tests-config.php`,
|
|
123
115
|
],
|
|
124
116
|
{
|
|
125
117
|
config: config.dockerComposeConfigPath,
|
|
@@ -246,10 +238,63 @@ async function copyCoreFiles( fromPath, toPath ) {
|
|
|
246
238
|
} );
|
|
247
239
|
}
|
|
248
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Scans through a WordPress source to find the version of WordPress it contains.
|
|
243
|
+
*
|
|
244
|
+
* @param {WPSource} coreSource The WordPress source.
|
|
245
|
+
* @param {Object} spinner A CLI spinner which indicates progress.
|
|
246
|
+
* @param {boolean} debug Indicates whether or not the CLI is in debug mode.
|
|
247
|
+
* @return {string} The version of WordPress the source is for.
|
|
248
|
+
*/
|
|
249
|
+
async function readWordPressVersion( coreSource, spinner, debug ) {
|
|
250
|
+
const versionFilePath = path.join(
|
|
251
|
+
coreSource.path,
|
|
252
|
+
'wp-includes',
|
|
253
|
+
'version.php'
|
|
254
|
+
);
|
|
255
|
+
const versionFile = await fs.readFile( versionFilePath, {
|
|
256
|
+
encoding: 'utf-8',
|
|
257
|
+
} );
|
|
258
|
+
const versionMatch = versionFile.match(
|
|
259
|
+
/\$wp_version = '([A-Za-z\-0-9.]+)'/
|
|
260
|
+
);
|
|
261
|
+
if ( ! versionMatch ) {
|
|
262
|
+
throw new Error( `Failed to find version in ${ versionFilePath }` );
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if ( debug ) {
|
|
266
|
+
spinner.info(
|
|
267
|
+
`Found WordPress ${ versionMatch[ 1 ] } in ${ versionFilePath }.`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return versionMatch[ 1 ];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Returns the latest stable version of WordPress by requesting the stable-check
|
|
276
|
+
* endpoint on WordPress.org.
|
|
277
|
+
*
|
|
278
|
+
* @return {string} The latest stable version of WordPress, like "6.0.1"
|
|
279
|
+
*/
|
|
280
|
+
async function getLatestWordPressVersion() {
|
|
281
|
+
const versions = await got(
|
|
282
|
+
'https://api.wordpress.org/core/stable-check/1.0/'
|
|
283
|
+
).json();
|
|
284
|
+
|
|
285
|
+
for ( const [ version, status ] of Object.entries( versions ) ) {
|
|
286
|
+
if ( status === 'latest' ) {
|
|
287
|
+
return version;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
249
292
|
module.exports = {
|
|
250
293
|
hasSameCoreSource,
|
|
251
294
|
checkDatabaseConnection,
|
|
252
295
|
configureWordPress,
|
|
253
296
|
resetDatabase,
|
|
254
297
|
setupWordPressDirectories,
|
|
298
|
+
readWordPressVersion,
|
|
299
|
+
getLatestWordPressVersion,
|
|
255
300
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/env",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "A zero-config, self contained local WordPress environment for development and testing.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"copy-dir": "^1.3.0",
|
|
37
37
|
"docker-compose": "^0.22.2",
|
|
38
38
|
"extract-zip": "^1.6.7",
|
|
39
|
-
"got": "^
|
|
39
|
+
"got": "^11.8.5",
|
|
40
40
|
"inquirer": "^7.1.0",
|
|
41
41
|
"js-yaml": "^3.13.1",
|
|
42
42
|
"ora": "^4.0.2",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"scripts": {
|
|
52
52
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "08358f53b627a15148c3a3e433cdf58cf8714aa4"
|
|
55
55
|
}
|