Skip to content

Commit

Permalink
initial e2e-env component, props @jeffstieler
Browse files Browse the repository at this point in the history
  • Loading branch information
rrennick authored and jeffstieler committed Apr 14, 2020
1 parent 18ff396 commit c8d643b
Show file tree
Hide file tree
Showing 28 changed files with 1,454 additions and 0 deletions.
15 changes: 15 additions & 0 deletions assets/components/e2e-env/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# WordPress container environment
WORDPRESS_DB_HOST=db
WORDPRESS_DB_NAME=testdb
WORDPRESS_DB_USER=wordpress
WORDPRESS_DB_PASSWORD=wordpress
WORDPRESS_TABLE_PREFIX=wp_
WORDPRESS_DEBUG=1

# WordPress CLI environment
WORDPRESS_PORT=8084
WORDPRESS_HOST=wordpress-www:80
WORDPRESS_TITLE=WooCommerce Core E2E Test Suite
WORDPRESS_LOGIN=admin
WORDPRESS_PASSWORD=password
WORDPRESS_EMAIL=[email protected]
15 changes: 15 additions & 0 deletions assets/components/e2e-env/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
extends: [
'plugin:jest/recommended',
],
env: {
'jest/globals': true,
},
globals: {
page: true,
browser: true,
context: true,
jestPuppeteer: true,
},
plugins: [ 'jest' ],
};
1 change: 1 addition & 0 deletions assets/components/e2e-env/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
53 changes: 53 additions & 0 deletions assets/components/e2e-env/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
version: ~> 1.0

language: php

dist: trusty

sudo: false

cache:
directories:
- vendor
- node_modules
- $HOME/.npm
- $HOME/.composer/cache

branches:
only:
- master
- /release\/.*/

before_install:
- timedatectl
- nvm install --latest-npm

before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- npm install
- |
if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then
phpenv config-rm xdebug.ini
else
echo "xdebug.ini does not exist"
fi
- |
if [[ ! -z "$WP_VERSION" ]] ; then
composer install --no-dev
npm explore @woocommerce/e2e-env -- npm run install-wp-tests -- wc_e2e_tests root ' ' localhost $WP_VERSION
composer global require "phpunit/phpunit=4.8.*|5.7.*"
fi
- |
if [[ "$WP_TRAVISCI" == "phpcs" ]] ; then
composer install
fi
jobs:
fast_finish: true
include:
- name: E2E Tests
script:
- npm explore @woocommerce/e2e-env -- npm run docker:up
- composer install
- npm run build
- npm explore @woocommerce/e2e-env -- npm run test:e2e
3 changes: 3 additions & 0 deletions assets/components/e2e-env/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1.0.0 (unreleased)

- Initial release
174 changes: 174 additions & 0 deletions assets/components/e2e-env/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# End to End Testing Environment

A reusable and extendable E2E testing environment for WooCommerce extensions.

## Installation

```bash
npm install @woocommerce/e2e-env --save
```

## Configuration

The `@woocommerce/e2e-env` package exports configuration objects that can be consumed in JavaScript config files in your project. Additionally, it contains several files to serve as the base for a Docker container and Travis CI setup.

### Babel Config

Extend your project's Babel config to contain the expected presets for E2E testing.

```js
const { babelConfig: e2eBabelConfig } = require( '@woocommerce/e2e-env' );

module.exports = function( api ) {
api.cache( true );

return {
...e2eBabelConfig,
presets: [
...e2eBabelConfig.presets,
'@wordpress/babel-preset-default',
],
....
};
};
```

### ES Lint Config

The E2E environment uses Puppeteer for headless browser testing, which uses certain globals variables. Avoid ES Lint errors by extending the config.

```js
const { esLintConfig: baseConfig } = require( '@woocommerce/e2e-env' );

module.exports = {
...baseConfig,
root: true,
parser: 'babel-eslint',
extends: [
...baseConfig.extends,
'wpcalypso/react',
'plugin:jsx-a11y/recommended',
],
plugins: [
...baseConfig.plugins,
'jsx-a11y',
],
env: {
...baseConfig.env,
browser: true,
node: true,
},
globals: {
...baseConfig.globals,
wp: true,
wpApiSettings: true,
wcSettings: true,
},
....
};
```

### Jest Config

The E2E environment uses Jest as a test runner. Extending the base config is needed in order for Jest to run your project's test files.

```js
const path = require( 'path' );
const { jestConfig: baseE2Econfig } = require( '@woocommerce/e2e-env' );

module.exports = {
...baseE2Econfig,
// Specify the path of your project's E2E tests here.
roots: [ path.resolve( __dirname, '../specs' ) ],
};
```

**NOTE:** Your project's Jest config file is expected to found at: `tests/e2e-tests/config/jest.config.js`.

### Webpack Config

The E2E environment provides a `@woocommerce/e2e-tests` alias for easy use of the WooCommerce E2E test helpers.

```js
const { webpackAlias: coreE2EAlias } = require( '@woocommerce/e2e-env' );

module.exports = {
....
resolve: {
alias: {
...coreE2EAlias,
....
},
},
};
```

### Docker Setup

The E2E environment will look for a `docker-compose.yaml` file in your project root. This will be combined with the base Docker config in the package. This is where you'll map your local project files into the Docker container(s).

```yaml
version: '3.3'

services:

wordpress-www:
volumes:
# This path is relative to the first config file
# which is in node_modules/@woocommerce/e2e-env
- "../../../:/var/www/html/wp-content/plugins/your-project-here"

wordpress-cli:
volumes:
- "../../../:/var/www/html/wp-content/plugins/your-project-here"
```
#### Docker Container Initialization Script
You can provide an initialization script that will run in the WP-CLI Docker container. Place an executable file at `tests/e2e-tests/docker/initialize.sh` in your project and it will be copied into the container and executed. While you can run any commands you wish, the intent here is to use WP-CLI to set up your testing environment. E.g.:

```
#!/bin/bash

echo "Initializing WooCommerce E2E"

wp plugin install woocommerce --activate
wp theme install twentynineteen --activate
wp user create customer [email protected] --user_pass=password --role=customer --path=/var/www/html
wp post create --post_type=page --post_status=publish --post_title='Ready' --post_content='E2E-tests.'
```
### Travis CI
The E2E environment includes a base `.travis.yml` file that sets up a WordPress testing environment and defines a job for running E2E tests. Opt in to [Travis Build Config Imports](https://docs.travis-ci.com/user/build-config-imports/) using `version: ~> 1.0` in your config file.
```yaml
version: ~> 1.0
import:
- source: node_modules/@woocommerce/e2e-env/.travis.yml
mode: deep_merge_prepend # Merge the package config first.
....
```

## Usage

Start Docker

```bash
npm explore @woocommerce/e2e-env -- npm run docker:up
```

Run E2E Tests

```bash
npm explore @woocommerce/e2e-env -- npm run test:e2e
npm explore @woocommerce/e2e-env -- npm run test:e2e-dev
```

Stop Docker

```bash
npm explore @woocommerce/e2e-env -- npm run docker:down
```
12 changes: 12 additions & 0 deletions assets/components/e2e-env/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
73 changes: 73 additions & 0 deletions assets/components/e2e-env/bin/docker-compose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env node

const { spawnSync } = require( 'child_process' );
const program = require( 'commander' );
const path = require( 'path' );
const fs = require( 'fs' );
const getAppPath = require( '../utils/app-root' );

const dockerArgs = [];
let command = '';

program
.command( 'up', 'Start and build the Docker container' )
.command( 'down', 'Stop the Docker container and remove volumes' )
.action( ( cmd, options ) => {
if ( 'up' === options[ 0 ] ) {
command = 'up';
dockerArgs.push( 'up', '--build', '-d' );
}

if ( 'down' === options[ 0 ] ) {
command = 'down';
dockerArgs.push( 'down', '-v' );
}
} )
.parse( process.argv );

const appPath = getAppPath();
const envVars = {};

if ( appPath ) {
// Look for a Docker compose file in the dependent app's path.
const appDockerComposefile = path.resolve( appPath, 'docker-compose.yaml' );

// Specify the app's Docker compose file in our command.
if ( fs.existsSync( appDockerComposefile ) ) {
dockerArgs.unshift( '-f', appDockerComposefile );
}

if ( 'up' === command ) {
// Look for an initialization script in the dependent app.
const appInitFile = path.resolve( appPath, 'tests/e2e-tests/docker/initialize.sh' );

// If found, copy it into the wp-cli Docker context so
// it gets picked up by the entrypoint script.
if ( fs.existsSync( appInitFile ) ) {
fs.copyFileSync(
appInitFile,
path.resolve( __dirname, '../docker/wp-cli/initialize.sh' )
);
}
}

// Provide an "app name" to use in Docker container names.
envVars.APP_NAME = path.basename( appPath );
}

// Ensure that the first Docker compose file loaded is from our local env.
dockerArgs.unshift( '-f', path.resolve( __dirname, '../docker-compose.yaml' ) );

const dockerProcess = spawnSync(
'docker-compose',
dockerArgs,
{
stdio: 'inherit',
env: Object.assign( {}, process.env, envVars ),
}
);

console.log( 'Docker exit code: ' + dockerProcess.status );

// Pass Docker exit code to npm
process.exit( dockerProcess.status );
Loading

0 comments on commit c8d643b

Please sign in to comment.