@wordpress/env 10.39.0 → 11.0.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.
@@ -11,7 +11,6 @@ const { rimraf } = require( 'rimraf' );
11
11
  /**
12
12
  * Promisified dependencies
13
13
  */
14
- const sleep = util.promisify( setTimeout );
15
14
  const exec = util.promisify( require( 'child_process' ).exec );
16
15
 
17
16
  /**
@@ -26,7 +25,6 @@ const {
26
25
  validateRunContainer,
27
26
  } = require( './validate-run-container' );
28
27
  const {
29
- checkDatabaseConnection,
30
28
  configureWordPress,
31
29
  resetDatabase,
32
30
  setupWordPressDirectories,
@@ -109,8 +107,11 @@ class DockerRuntime {
109
107
  xdebug,
110
108
  spx,
111
109
  writeChanges: true,
110
+ customConfigPath: config.customConfigPath,
112
111
  } );
113
112
 
113
+ const testsEnabled = fullConfig.testsEnvironment !== false;
114
+
114
115
  // Check if the hash of the config has changed. If so, run configuration.
115
116
  const configHash = md5( fullConfig );
116
117
  const { workDirectoryPath, dockerComposeConfigPath } = fullConfig;
@@ -139,13 +140,19 @@ class DockerRuntime {
139
140
  * the container before continuing allows the docker entrypoint script,
140
141
  * which restores the files, to run again when we start the containers.
141
142
  *
142
- * Additionally, this serves as a way to restart the container entirely
143
- * should the need arise.
143
+ * Additionally, --remove-orphans ensures containers from services that
144
+ * were removed in the new config (e.g., tests-* after setting
145
+ * testsEnvironment: false) are properly stopped.
144
146
  *
145
147
  * @see https://github.com/WordPress/gutenberg/pull/20253#issuecomment-587228440
146
148
  */
147
149
  if ( shouldConfigureWp ) {
148
- await this.stop( fullConfig, { spinner, debug } );
150
+ spinner.text = 'Stopping WordPress.';
151
+ await dockerCompose.down( {
152
+ config: dockerComposeConfigPath,
153
+ log: debug,
154
+ commandOptions: [ '--remove-orphans' ],
155
+ } );
149
156
  // Update the images before starting the services again.
150
157
  spinner.text = 'Updating docker images.';
151
158
 
@@ -156,7 +163,9 @@ class DockerRuntime {
156
163
  // as docker volumes, simply updating the image will not change those
157
164
  // files. Thus, we need to remove those volumes in order for the files
158
165
  // to be updated when pulling the new images.
159
- const volumesToRemove = `${ directoryHash }_wordpress ${ directoryHash }_tests-wordpress`;
166
+ const volumesToRemove = testsEnabled
167
+ ? `${ directoryHash }_wordpress ${ directoryHash }_tests-wordpress`
168
+ : `${ directoryHash }_wordpress`;
160
169
 
161
170
  try {
162
171
  if ( fullConfig.debug ) {
@@ -173,8 +182,12 @@ class DockerRuntime {
173
182
  spinner.text = 'Downloading sources.';
174
183
  }
175
184
 
185
+ const mysqlServices = [ 'mysql' ];
186
+ if ( testsEnabled ) {
187
+ mysqlServices.push( 'tests-mysql' );
188
+ }
176
189
  await Promise.all( [
177
- dockerCompose.upOne( 'mysql', {
190
+ dockerCompose.upMany( mysqlServices, {
178
191
  ...dockerComposeConfig,
179
192
  commandOptions: shouldConfigureWp
180
193
  ? [ '--build', '--force-recreate' ]
@@ -189,37 +202,44 @@ class DockerRuntime {
189
202
  await setupWordPressDirectories( fullConfig );
190
203
 
191
204
  // Use the WordPress versions to download the PHPUnit suite.
192
- const wpVersions = await Promise.all( [
205
+ const wpVersionPromises = [
193
206
  readWordPressVersion(
194
207
  fullConfig.env.development.coreSource,
195
208
  spinner,
196
209
  debug
197
210
  ),
198
- readWordPressVersion(
199
- fullConfig.env.tests.coreSource,
200
- spinner,
201
- debug
202
- ),
203
- ] );
204
- await downloadWPPHPUnit(
205
- fullConfig,
206
- { development: wpVersions[ 0 ], tests: wpVersions[ 1 ] },
207
- spinner,
208
- debug
209
- );
211
+ ];
212
+ if ( testsEnabled ) {
213
+ wpVersionPromises.push(
214
+ readWordPressVersion(
215
+ fullConfig.env.tests.coreSource,
216
+ spinner,
217
+ debug
218
+ )
219
+ );
220
+ }
221
+ const wpVersions = await Promise.all( wpVersionPromises );
222
+ const wpVersionMap = {
223
+ development: wpVersions[ 0 ],
224
+ };
225
+ if ( testsEnabled ) {
226
+ wpVersionMap.tests = wpVersions[ 1 ];
227
+ }
228
+ await downloadWPPHPUnit( fullConfig, wpVersionMap, spinner, debug );
210
229
  }
211
230
 
212
231
  spinner.text = 'Starting WordPress.';
213
232
 
214
- await dockerCompose.upMany(
215
- [ 'wordpress', 'tests-wordpress', 'cli', 'tests-cli' ],
216
- {
217
- ...dockerComposeConfig,
218
- commandOptions: shouldConfigureWp
219
- ? [ '--build', '--force-recreate' ]
220
- : [],
221
- }
222
- );
233
+ const wpServices = [ 'wordpress', 'cli' ];
234
+ if ( testsEnabled ) {
235
+ wpServices.push( 'tests-wordpress', 'tests-cli' );
236
+ }
237
+ await dockerCompose.upMany( wpServices, {
238
+ ...dockerComposeConfig,
239
+ commandOptions: shouldConfigureWp
240
+ ? [ '--build', '--force-recreate' ]
241
+ : [],
242
+ } );
223
243
 
224
244
  if ( fullConfig.env.development.phpmyadminPort ) {
225
245
  await dockerCompose.upOne( 'phpmyadmin', {
@@ -230,7 +250,7 @@ class DockerRuntime {
230
250
  } );
231
251
  }
232
252
 
233
- if ( fullConfig.env.tests.phpmyadminPort ) {
253
+ if ( testsEnabled && fullConfig.env.tests.phpmyadminPort ) {
234
254
  await dockerCompose.upOne( 'tests-phpmyadmin', {
235
255
  ...dockerComposeConfig,
236
256
  commandOptions: shouldConfigureWp
@@ -250,21 +270,8 @@ class DockerRuntime {
250
270
  if ( shouldConfigureWp ) {
251
271
  spinner.text = 'Configuring WordPress.';
252
272
 
253
- try {
254
- await checkDatabaseConnection( fullConfig );
255
- } catch ( error ) {
256
- // Wait 30 seconds for MySQL to accept connections.
257
- await retry( () => checkDatabaseConnection( fullConfig ), {
258
- times: 30,
259
- delay: 1000,
260
- } );
261
-
262
- // It takes 3-4 seconds for MySQL to be ready after it starts accepting connections.
263
- await sleep( 4000 );
264
- }
265
-
266
273
  // Retry WordPress installation in case MySQL *still* wasn't ready.
267
- await Promise.all( [
274
+ const configTasks = [
268
275
  retry(
269
276
  () =>
270
277
  configureWordPress(
@@ -276,13 +283,19 @@ class DockerRuntime {
276
283
  times: 2,
277
284
  }
278
285
  ),
279
- retry(
280
- () => configureWordPress( 'tests', fullConfig, spinner ),
281
- {
282
- times: 2,
283
- }
284
- ),
285
- ] );
286
+ ];
287
+ if ( testsEnabled ) {
288
+ configTasks.push(
289
+ retry(
290
+ () =>
291
+ configureWordPress( 'tests', fullConfig, spinner ),
292
+ {
293
+ times: 2,
294
+ }
295
+ )
296
+ );
297
+ }
298
+ await Promise.all( configTasks );
286
299
 
287
300
  // Set the cache key once everything has been configured.
288
301
  await setCache( CONFIG_CACHE_KEY, configHash, {
@@ -292,7 +305,6 @@ class DockerRuntime {
292
305
 
293
306
  // Get port information for the result message
294
307
  const siteUrl = fullConfig.env.development.config.WP_SITEURL;
295
- const testsSiteUrl = fullConfig.env.tests.config.WP_SITEURL;
296
308
 
297
309
  const mySQLPort = await this._getPublicDockerPort(
298
310
  'mysql',
@@ -300,12 +312,6 @@ class DockerRuntime {
300
312
  dockerComposeConfig
301
313
  );
302
314
 
303
- const testsMySQLPort = await this._getPublicDockerPort(
304
- 'tests-mysql',
305
- 3306,
306
- dockerComposeConfig
307
- );
308
-
309
315
  const phpmyadminPort = fullConfig.env.development.phpmyadminPort
310
316
  ? await this._getPublicDockerPort(
311
317
  'phpmyadmin',
@@ -314,31 +320,42 @@ class DockerRuntime {
314
320
  )
315
321
  : null;
316
322
 
317
- const testsPhpmyadminPort = fullConfig.env.tests.phpmyadminPort
318
- ? await this._getPublicDockerPort(
319
- 'tests-phpmyadmin',
320
- 80,
321
- dockerComposeConfig
322
- )
323
- : null;
324
-
325
323
  const message = [
326
324
  'WordPress development site started' +
327
325
  ( siteUrl ? ` at ${ siteUrl }` : '.' ),
328
- 'WordPress test site started' +
329
- ( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
330
326
  `MySQL is listening on port ${ mySQLPort }`,
331
- `MySQL for automated testing is listening on port ${ testsMySQLPort }`,
332
327
  phpmyadminPort &&
333
328
  `phpMyAdmin started at http://localhost:${ phpmyadminPort }`,
334
- testsPhpmyadminPort &&
335
- `phpMyAdmin for automated testing started at http://localhost:${ testsPhpmyadminPort }`,
336
- ]
337
- .filter( Boolean )
338
- .join( '\n' );
329
+ ];
330
+
331
+ if ( testsEnabled ) {
332
+ const testsSiteUrl = fullConfig.env.tests.config.WP_SITEURL;
333
+ const testsMySQLPort = await this._getPublicDockerPort(
334
+ 'tests-mysql',
335
+ 3306,
336
+ dockerComposeConfig
337
+ );
338
+ const testsPhpmyadminPort = fullConfig.env.tests.phpmyadminPort
339
+ ? await this._getPublicDockerPort(
340
+ 'tests-phpmyadmin',
341
+ 80,
342
+ dockerComposeConfig
343
+ )
344
+ : null;
345
+
346
+ message.push(
347
+ 'WordPress test site started' +
348
+ ( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
349
+ `MySQL for automated testing is listening on port ${ testsMySQLPort }`,
350
+ testsPhpmyadminPort &&
351
+ `phpMyAdmin for automated testing started at http://localhost:${ testsPhpmyadminPort }`
352
+ );
353
+ }
354
+
355
+ const formattedMessage = message.filter( Boolean ).join( '\n' );
339
356
 
340
357
  return {
341
- message,
358
+ message: formattedMessage,
342
359
  siteUrl,
343
360
  };
344
361
  }
@@ -369,6 +386,15 @@ class DockerRuntime {
369
386
  return 'WARNING! This will remove Docker containers, volumes, networks, and images associated with the WordPress instance.';
370
387
  }
371
388
 
389
+ /**
390
+ * Get the warning message for cleanup confirmation.
391
+ *
392
+ * @return {string} Warning message.
393
+ */
394
+ getCleanupWarningMessage() {
395
+ return 'WARNING! This will remove Docker containers, volumes, networks, and local files associated with the WordPress instance. Docker images will be preserved.';
396
+ }
397
+
372
398
  /**
373
399
  * Stop the Docker containers.
374
400
  *
@@ -381,6 +407,7 @@ class DockerRuntime {
381
407
  const { dockerComposeConfigPath } = await initConfig( {
382
408
  spinner,
383
409
  debug,
410
+ customConfigPath: config.customConfigPath,
384
411
  } );
385
412
 
386
413
  spinner.text = 'Stopping WordPress.';
@@ -413,7 +440,8 @@ class DockerRuntime {
413
440
  spinner.text = 'Removing local files.';
414
441
  // Note: there is a race condition where docker compose actually hasn't finished
415
442
  // by this point, which causes rimraf to fail. We need to wait at least 2.5-5s,
416
- // but using 10s in case it's dependant on the machine.
443
+ // but using 10s in case it's dependent on the machine. Removing images takes
444
+ // longer so we use a longer wait time here.
417
445
  await new Promise( ( resolve ) => setTimeout( resolve, 10000 ) );
418
446
  await rimraf( config.workDirectoryPath );
419
447
 
@@ -421,27 +449,79 @@ class DockerRuntime {
421
449
  }
422
450
 
423
451
  /**
424
- * Clean/reset the WordPress database.
452
+ * Cleanup the Docker containers and remove local files, but preserve images.
453
+ *
454
+ * @param {WPConfig} config The wp-env config object.
455
+ * @param {Object} options Cleanup options.
456
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
457
+ * @param {boolean} options.debug True if debug mode is enabled.
458
+ */
459
+ async cleanup( config, { spinner, debug } ) {
460
+ spinner.text = 'Removing docker containers, volumes, and networks.';
461
+
462
+ await dockerCompose.down( {
463
+ config: config.dockerComposeConfigPath,
464
+ commandOptions: [ '--volumes', '--remove-orphans' ],
465
+ log: debug,
466
+ } );
467
+
468
+ spinner.text = 'Removing local files.';
469
+ // Note: there is a race condition where docker compose actually hasn't finished
470
+ // by this point, which causes rimraf to fail. We need to wait at least 2.5-5s,
471
+ // but since we're not removing images, the wait can be shorter.
472
+ await new Promise( ( resolve ) => setTimeout( resolve, 3000 ) );
473
+ await rimraf( config.workDirectoryPath );
474
+
475
+ spinner.text = 'Cleaned up WordPress environment.';
476
+ }
477
+
478
+ /**
479
+ * Reset the WordPress database.
425
480
  *
426
481
  * @param {WPConfig} config The wp-env config object.
427
- * @param {Object} options Clean options.
428
- * @param {string} options.environment The environment to clean.
482
+ * @param {Object} options Reset options.
483
+ * @param {string} options.environment The environment to reset.
429
484
  * @param {Object} options.spinner A CLI spinner which indicates progress.
430
485
  * @param {boolean} options.debug True if debug mode is enabled.
431
486
  */
432
487
  async clean( config, { environment, spinner, debug } ) {
433
- const fullConfig = await initConfig( { spinner, debug } );
488
+ const fullConfig = await initConfig( {
489
+ spinner,
490
+ debug,
491
+ customConfigPath: config.customConfigPath,
492
+ } );
493
+
494
+ const testsEnabled = fullConfig.testsEnvironment !== false;
495
+
496
+ if ( ! testsEnabled && environment === 'tests' ) {
497
+ throw new Error(
498
+ 'Cannot reset the tests environment because it is disabled in the configuration.'
499
+ );
500
+ }
434
501
 
435
502
  const description = `${ environment } environment${
436
503
  environment === 'all' ? 's' : ''
437
504
  }`;
438
- spinner.text = `Cleaning ${ description }.`;
505
+ spinner.text = `Resetting ${ description }.`;
439
506
 
440
507
  const tasks = [];
441
508
 
442
- // Start the database first to avoid race conditions where all tasks create
443
- // different docker networks with the same name.
444
- await dockerCompose.upOne( 'mysql', {
509
+ // Start the appropriate MySQL service(s) first to avoid race conditions
510
+ // where parallel tasks try to create docker networks with the same name.
511
+ // The dependency chain (cli -> wordpress -> mysql with service_healthy)
512
+ // ensures MySQL is ready before database operations run.
513
+ const mysqlServices = [];
514
+ if ( environment === 'all' || environment === 'development' ) {
515
+ mysqlServices.push( 'mysql' );
516
+ }
517
+ if (
518
+ testsEnabled &&
519
+ ( environment === 'all' || environment === 'tests' )
520
+ ) {
521
+ mysqlServices.push( 'tests-mysql' );
522
+ }
523
+
524
+ await dockerCompose.upMany( mysqlServices, {
445
525
  config: fullConfig.dockerComposeConfigPath,
446
526
  log: fullConfig.debug,
447
527
  } );
@@ -456,7 +536,10 @@ class DockerRuntime {
456
536
  );
457
537
  }
458
538
 
459
- if ( environment === 'all' || environment === 'tests' ) {
539
+ if (
540
+ testsEnabled &&
541
+ ( environment === 'all' || environment === 'tests' )
542
+ ) {
460
543
  tasks.push(
461
544
  resetDatabase( 'tests', fullConfig )
462
545
  .then( () => configureWordPress( 'tests', fullConfig ) )
@@ -466,7 +549,7 @@ class DockerRuntime {
466
549
 
467
550
  await Promise.all( tasks );
468
551
 
469
- spinner.text = `Cleaned ${ description }.`;
552
+ spinner.text = `Reset ${ description }.`;
470
553
  }
471
554
 
472
555
  /**
@@ -493,7 +576,20 @@ class DockerRuntime {
493
576
  // Validate the container name (throws for deprecated containers)
494
577
  validateRunContainer( container );
495
578
 
496
- const fullConfig = await initConfig( { spinner, debug } );
579
+ if (
580
+ config.testsEnvironment === false &&
581
+ container.startsWith( 'tests-' )
582
+ ) {
583
+ throw new Error(
584
+ `Cannot run commands on "${ container }" because the tests environment is disabled in the configuration.`
585
+ );
586
+ }
587
+
588
+ const fullConfig = await initConfig( {
589
+ spinner,
590
+ debug,
591
+ customConfigPath: config.customConfigPath,
592
+ } );
497
593
 
498
594
  // Shows a contextual tip for the given command.
499
595
  const joinedCommand = command.join( ' ' );
@@ -520,7 +616,19 @@ class DockerRuntime {
520
616
  * @param {boolean} options.debug True if debug mode is enabled.
521
617
  */
522
618
  async logs( config, { environment, watch, spinner, debug } ) {
523
- const fullConfig = await initConfig( { spinner, debug } );
619
+ const fullConfig = await initConfig( {
620
+ spinner,
621
+ debug,
622
+ customConfigPath: config.customConfigPath,
623
+ } );
624
+
625
+ const testsEnabled = fullConfig.testsEnvironment !== false;
626
+
627
+ if ( ! testsEnabled && environment === 'tests' ) {
628
+ throw new Error(
629
+ 'Cannot show logs for the tests environment because it is disabled in the configuration.'
630
+ );
631
+ }
524
632
 
525
633
  // If we show text while watching the logs, it will continue showing up every
526
634
  // few lines in the logs as they happen, which isn't a good look. So only
@@ -529,10 +637,16 @@ class DockerRuntime {
529
637
  spinner.text = `Showing logs for the ${ environment } environment.`;
530
638
  }
531
639
 
532
- const servicesToWatch =
533
- environment === 'all'
640
+ let servicesToWatch;
641
+ if ( environment === 'all' ) {
642
+ servicesToWatch = testsEnabled
534
643
  ? [ 'tests-wordpress', 'wordpress' ]
535
- : [ environment === 'tests' ? 'tests-wordpress' : 'wordpress' ];
644
+ : [ 'wordpress' ];
645
+ } else {
646
+ servicesToWatch = [
647
+ environment === 'tests' ? 'tests-wordpress' : 'wordpress',
648
+ ];
649
+ }
536
650
 
537
651
  const output = await Promise.all( [
538
652
  ...servicesToWatch.map( ( service ) =>
@@ -577,6 +691,82 @@ class DockerRuntime {
577
691
  spinner.text = 'Finished showing logs.';
578
692
  }
579
693
 
694
+ /**
695
+ * Get the status of the Docker environment.
696
+ *
697
+ * @param {WPConfig} config The wp-env config object.
698
+ * @param {Object} options Status options.
699
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
700
+ * @param {boolean} options.debug True if debug mode is enabled.
701
+ * @return {Promise<Object>} Status object with environment information.
702
+ */
703
+ async getStatus( config, { spinner, debug } ) {
704
+ spinner.text = 'Getting environment status.';
705
+
706
+ const fullConfig = await initConfig( {
707
+ spinner,
708
+ debug,
709
+ customConfigPath: config.customConfigPath,
710
+ } );
711
+ const dockerComposeConfig = {
712
+ config: fullConfig.dockerComposeConfigPath,
713
+ log: debug,
714
+ };
715
+
716
+ // Check if containers are running by trying to get a port.
717
+ let isRunning = false;
718
+ let mySQLPort = null;
719
+ let phpmyadminPort = null;
720
+
721
+ try {
722
+ mySQLPort = await this._getPublicDockerPort(
723
+ 'mysql',
724
+ 3306,
725
+ dockerComposeConfig
726
+ );
727
+ isRunning = true;
728
+
729
+ if ( fullConfig.env.development.phpmyadminPort ) {
730
+ phpmyadminPort = await this._getPublicDockerPort(
731
+ 'phpmyadmin',
732
+ 80,
733
+ dockerComposeConfig
734
+ );
735
+ }
736
+ } catch {
737
+ // Containers are not running.
738
+ }
739
+
740
+ const siteUrl = fullConfig.env.development.config.WP_SITEURL;
741
+
742
+ const testsEnabled = fullConfig.testsEnvironment !== false;
743
+
744
+ return {
745
+ status: isRunning ? 'running' : 'stopped',
746
+ runtime: 'docker',
747
+ urls: {
748
+ development: isRunning ? siteUrl : null,
749
+ phpmyadmin:
750
+ isRunning && phpmyadminPort
751
+ ? `http://localhost:${ phpmyadminPort }`
752
+ : null,
753
+ },
754
+ ports: {
755
+ development: fullConfig.env.development.port,
756
+ ...( testsEnabled && {
757
+ tests: fullConfig.env.tests.port,
758
+ } ),
759
+ mysql: mySQLPort,
760
+ },
761
+ config: {
762
+ multisite: fullConfig.env.development.multisite,
763
+ xdebug: fullConfig.xdebug || 'off',
764
+ },
765
+ configPath: fullConfig.configDirectoryPath,
766
+ installPath: fullConfig.workDirectoryPath,
767
+ };
768
+ }
769
+
580
770
  /**
581
771
  * Runs an arbitrary command on the given Docker container.
582
772
  *
@@ -22,16 +22,17 @@ const buildDockerComposeConfig = require( './build-docker-compose-config' );
22
22
  * ./.wp-env.json, creates ~/.wp-env, ~/.wp-env/docker-compose.yml, and
23
23
  * ~/.wp-env/Dockerfile.
24
24
  *
25
- * @param {Object} options
26
- * @param {Object} options.spinner A CLI spinner which indicates progress.
27
- * @param {boolean} options.debug True if debug mode is enabled.
28
- * @param {string} options.xdebug The Xdebug mode to set. Defaults to "off".
29
- * @param {string} options.spx The SPX mode to set. Defaults to "off".
30
- * @param {boolean} options.writeChanges If true, writes the parsed config to the
31
- * required docker files like docker-compose
32
- * and Dockerfile. By default, this is false
33
- * and only the `start` command writes any
34
- * changes.
25
+ * @param {Object} options
26
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
27
+ * @param {boolean} options.debug True if debug mode is enabled.
28
+ * @param {string} options.xdebug The Xdebug mode to set. Defaults to "off".
29
+ * @param {string} options.spx The SPX mode to set. Defaults to "off".
30
+ * @param {boolean} options.writeChanges If true, writes the parsed config to the
31
+ * required docker files like docker-compose
32
+ * and Dockerfile. By default, this is false
33
+ * and only the `start` command writes any
34
+ * changes.
35
+ * @param {string|null} options.customConfigPath Path to a custom .wp-env.json configuration file.
35
36
  * @return {WPConfig} The-env config object.
36
37
  */
37
38
  module.exports = async function initConfig( {
@@ -40,8 +41,9 @@ module.exports = async function initConfig( {
40
41
  xdebug = 'off',
41
42
  spx = 'off',
42
43
  writeChanges = false,
44
+ customConfigPath = null,
43
45
  } ) {
44
- const config = await loadConfig( path.resolve( '.' ) );
46
+ const config = await loadConfig( path.resolve( '.' ), customConfigPath );
45
47
  config.debug = debug;
46
48
 
47
49
  // Adding this to the config allows the start command to understand that the
@@ -87,10 +89,16 @@ module.exports = async function initConfig( {
87
89
  yaml.dump( dockerComposeConfig )
88
90
  );
89
91
 
90
- // Write four Dockerfiles for each service we provided.
92
+ // Write Dockerfiles for each service we provided.
91
93
  // (WordPress and CLI services, then a development and test environment for each.)
92
94
  for ( const imageType of [ 'WordPress', 'CLI' ] ) {
93
95
  for ( const envType of [ 'development', 'tests' ] ) {
96
+ if (
97
+ envType === 'tests' &&
98
+ config.testsEnvironment === false
99
+ ) {
100
+ continue;
101
+ }
94
102
  await writeFile(
95
103
  path.resolve(
96
104
  config.workDirectoryPath,
@@ -47,20 +47,6 @@ function isWPMajorMinorVersionLower( version, compareVersion ) {
47
47
  return versionNumber < compareVersionNumber;
48
48
  }
49
49
 
50
- /**
51
- * Checks a WordPress database connection. An error is thrown if the test is
52
- * unsuccessful.
53
- *
54
- * @param {WPConfig} config The wp-env config object.
55
- */
56
- async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) {
57
- await dockerCompose.run( 'cli', 'wp db check', {
58
- config: dockerComposeConfigPath,
59
- commandOptions: [ '--rm' ],
60
- log: debug,
61
- } );
62
- }
63
-
64
50
  /**
65
51
  * Configures WordPress for the given environment by installing WordPress,
66
52
  * activating all plugins, and activating the first theme. These steps are
@@ -316,7 +302,6 @@ async function copyCoreFiles( fromPath, toPath ) {
316
302
  }
317
303
 
318
304
  module.exports = {
319
- checkDatabaseConnection,
320
305
  configureWordPress,
321
306
  resetDatabase,
322
307
  setupWordPressDirectories,
@@ -12,6 +12,17 @@ class UnsupportedCommandError extends Error {
12
12
  }
13
13
  }
14
14
 
15
+ /**
16
+ * Error thrown when the environment has not been initialized.
17
+ */
18
+ class EnvironmentNotInitializedError extends Error {
19
+ constructor() {
20
+ super( 'Environment not initialized. Run `wp-env start` first.' );
21
+ this.name = 'EnvironmentNotInitializedError';
22
+ }
23
+ }
24
+
15
25
  module.exports = {
16
26
  UnsupportedCommandError,
27
+ EnvironmentNotInitializedError,
17
28
  };