Merge pull request #26432 from woocommerce/add/npm-publish

Add npm publish script for /tests/e2e
This commit is contained in:
Ron Rennick 2020-06-22 14:05:47 -03:00 committed by GitHub
commit fbc66f3b2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 7044 additions and 36 deletions

4
.gitignore vendored
View File

@ -13,7 +13,7 @@ project.properties
*.swp
# Grunt
/node_modules/
node_modules/
none
# Sass
@ -47,6 +47,8 @@ tests/cli/vendor
/tests/e2e/config/local.json
/tests/e2e/docker
/tests/e2e/env/docker/wp-cli/initialize.sh
/tests/e2e/env/build/
/tests/e2e/env/build-module/
# Logs
/logs

View File

@ -36,6 +36,7 @@ jobs:
script:
- composer require wp-cli/i18n-command
- npm run build
- npm run build:packages
- npm install jest --global
- npm run docker:up
- npm run test:e2e

View File

@ -1,4 +1,4 @@
version: '3.7'
version: '3.3'
services:

10
lerna.json Normal file
View File

@ -0,0 +1,10 @@
{
"command": {
"publish": {
"message": "chore(release): publish"
}
},
"ignoreChanges": [ "**/CHANGELOG.md", "**/test/**" ],
"packages": [ "tests/e2e/*" ],
"version": "independent"
}

6691
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
"scripts": {
"build": "grunt && npm run makepot",
"build-watch": "grunt watch",
"build:packages": "node ./tests/e2e/bin/build.js",
"build:zip": "./bin/build-zip.sh",
"lint:js": "eslint assets/js --ext=js",
"docker:up": "npm explore @woocommerce/e2e-environment -- npm run docker:up",
@ -20,6 +21,7 @@
"test:e2e-dev": "npm explore @woocommerce/e2e-environment -- npm run test:e2e-dev",
"makepot": "composer run-script makepot",
"packages:fix:textdomain": "node ./bin/package-update-textdomain.js",
"publish-packages": "npm run build:packages && lerna publish from-package",
"git:update-hooks": "rm -r .git/hooks && mkdir -p .git/hooks && node ./node_modules/husky/husky.js install"
},
"devDependencies": {
@ -30,7 +32,9 @@
"@babel/register": "7.9.0",
"@jest/test-sequencer": "^25.0.0",
"@woocommerce/e2e-environment": "file:tests/e2e/env",
"@wordpress/e2e-test-utils": "4.3.1",
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
"@wordpress/babel-preset-default": "3.0.2",
"@wordpress/e2e-test-utils": "4.6.0",
"autoprefixer": "9.7.5",
"babel-eslint": "10.1.0",
"chai": "4.2.0",
@ -38,6 +42,7 @@
"commander": "4.1.1",
"config": "3.3.1",
"cross-env": "6.0.3",
"deasync": "0.1.19",
"eslint": "6.8.0",
"eslint-config-wpcalypso": "5.0.0",
"eslint-plugin-jest": "23.8.2",
@ -59,6 +64,7 @@
"istanbul": "1.0.0-alpha.2",
"jest": "25.1.0",
"jest-puppeteer": "4.4.0",
"lerna": "3.20.2",
"lint-staged": "9.5.0",
"mocha": "7.0.1",
"node-sass": "4.13.0",

163
tests/e2e/bin/build.js Executable file
View File

@ -0,0 +1,163 @@
/**
* script to build packages into `build/` directory.
*
* Example:
* node ./bin/packages/build.js
*/
/**
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );
const glob = require( 'glob' );
const babel = require( '@babel/core' );
const chalk = require( 'chalk' );
const mkdirp = require( 'mkdirp' );
const deasync = require( 'deasync' );
/**
* Internal dependencies
*/
const getPackages = require( './get-packages' );
const getBabelConfig = require( './get-babel-config' );
/**
* Module Constants
*/
const PACKAGES_DIR = path.resolve( __dirname, '../' );
const SRC_DIR = 'src';
const BUILD_DIR = {
main: 'build',
module: 'build-module',
};
const DONE = chalk.reset.inverse.bold.green( ' DONE ' );
/**
* Get the package name for a specified file
*
* @param {string} file File name
* @return {string} Package name
*/
function getPackageName( file ) {
return path.relative( PACKAGES_DIR, file ).split( path.sep )[ 0 ];
}
const isJsFile = ( filepath ) => {
return /.\.js$/.test( filepath );
};
/**
* Get Build Path for a specified file
*
* @param {string} file File to build
* @param {string} buildFolder Output folder
* @return {string} Build path
*/
function getBuildPath( file, buildFolder ) {
const pkgName = getPackageName( file );
const pkgSrcPath = path.resolve( PACKAGES_DIR, pkgName, SRC_DIR );
const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder );
const relativeToSrcPath = path.relative( pkgSrcPath, file );
return path.resolve( pkgBuildPath, relativeToSrcPath );
}
/**
* Given a list of scss and js filepaths, divide them into sets them and rebuild.
*
* @param {Array} files list of files to rebuild
*/
function buildFiles( files ) {
// Reduce files into a unique sets of javaScript files and scss packages.
const buildPaths = files.reduce(
( accumulator, filePath ) => {
if ( isJsFile( filePath ) ) {
accumulator.jsFiles.add( filePath );
}
return accumulator;
},
{ jsFiles: new Set() }
);
buildPaths.jsFiles.forEach( buildJsFile );
}
/**
* Build a javaScript file for the required environments (node and ES5)
*
* @param {string} file File path to build
* @param {boolean} silent Show logs
*/
function buildJsFile( file, silent ) {
buildJsFileFor( file, silent, 'main' );
buildJsFileFor( file, silent, 'module' );
}
/**
* Build a file for a specific environment
*
* @param {string} file File path to build
* @param {boolean} silent Show logs
* @param {string} environment Dist environment (node or es5)
*/
function buildJsFileFor( file, silent, environment ) {
const buildDir = BUILD_DIR[ environment ];
const destPath = getBuildPath( file, buildDir );
const babelOptions = getBabelConfig( environment );
babelOptions.sourceMaps = true;
babelOptions.sourceFileName = file;
mkdirp.sync( path.dirname( destPath ) );
const transformed = babel.transformFileSync( file, babelOptions );
fs.writeFileSync( destPath + '.map', JSON.stringify( transformed.map ) );
fs.writeFileSync(
destPath,
transformed.code +
'\n//# sourceMappingURL=' +
path.basename( destPath ) +
'.map'
);
if ( ! silent ) {
process.stdout.write(
chalk.green( ' \u2022 ' ) +
path.relative( PACKAGES_DIR, file ) +
chalk.green( ' \u21D2 ' ) +
path.relative( PACKAGES_DIR, destPath ) +
'\n'
);
}
}
/**
* Build the provided package path
*
* @param {string} packagePath absolute package path
*/
function buildPackage( packagePath ) {
const srcDir = path.resolve( packagePath, SRC_DIR );
const jsFiles = glob.sync( `${ srcDir }/**/*.js`, {
ignore: [
`${ srcDir }/**/test/**/*.js`,
`${ srcDir }/**/__mocks__/**/*.js`,
],
nodir: true,
} );
process.stdout.write( `${ path.basename( packagePath ) }\n` );
// Build js files individually.
jsFiles.forEach( ( file ) => buildJsFile( file, true ) );
process.stdout.write( `${ DONE }\n` );
}
const files = process.argv.slice( 2 );
if ( files.length ) {
buildFiles( files );
} else {
process.stdout.write( chalk.inverse( '>> Building packages \n' ) );
getPackages().forEach( buildPackage );
process.stdout.write( '\n' );
}

View File

@ -0,0 +1,71 @@
/**
* External dependencies
*/
const { get, map } = require( 'lodash' );
const babel = require( '@babel/core' );
/**
* WordPress dependencies
*/
const { options: babelDefaultConfig } = babel.loadPartialConfig( {
configFile: '@wordpress/babel-preset-default',
} );
const plugins = babelDefaultConfig.plugins;
if ( ! process.env.SKIP_JSX_PRAGMA_TRANSFORM ) {
plugins.push( [ '@wordpress/babel-plugin-import-jsx-pragma', {
scopeVariable: 'createElement',
source: '@wordpress/element',
isDefault: false,
} ] );
}
const overrideOptions = ( target, targetName, options ) => {
if ( get( target, [ 'file', 'request' ] ) === targetName ) {
return [ targetName, Object.assign(
{},
target.options,
options
) ];
}
return target;
};
const babelConfigs = {
main: Object.assign(
{},
babelDefaultConfig,
{
plugins,
presets: map(
babelDefaultConfig.presets,
( preset ) => overrideOptions( preset, '@babel/preset-env', {
modules: 'commonjs',
} )
),
}
),
module: Object.assign(
{},
babelDefaultConfig,
{
plugins: map(
plugins,
( plugin ) => overrideOptions( plugin, '@babel/plugin-transform-runtime', {
useESModules: true,
} )
),
presets: map(
babelDefaultConfig.presets,
( preset ) => overrideOptions( preset, '@babel/preset-env', {
modules: false,
} )
),
}
),
};
function getBabelConfig( environment ) {
return babelConfigs[ environment ];
}
module.exports = getBabelConfig;

View File

@ -0,0 +1,83 @@
/**
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );
const { overEvery, compact, includes, negate } = require( 'lodash' );
/**
* Absolute path to packages directory.
*
* @type {string}
*/
const PACKAGES_DIR = path.resolve( __dirname, '../' );
const {
/**
* Comma-separated string of packages to include in build.
*
* @type {string}
*/
INCLUDE_PACKAGES,
/**
* Comma-separated string of packages to exclude from build.
*
* @type {string}
*/
EXCLUDE_PACKAGES,
} = process.env;
/**
* Given a comma-separated string, returns a filter function which returns true
* if the item is contained within as a comma-separated entry.
*
* @param {Function} filterFn Filter function to call with item to test.
* @param {string} list Comma-separated list of items.
*
* @return {Function} Filter function.
*/
const createCommaSeparatedFilter = ( filterFn, list ) => {
const listItems = list.split( ',' );
return ( item ) => filterFn( listItems, item );
};
/**
* Returns true if the given base file name for a file within the packages
* directory is itself a directory.
*
* @param {string} file Packages directory file.
*
* @return {boolean} Whether file is a directory.
*/
function isDirectory( file ) {
return fs.lstatSync( path.resolve( PACKAGES_DIR, file ) ).isDirectory();
}
/**
* Filter predicate, returning true if the given base file name is to be
* included in the build.
*
* @param {string} pkg File base name to test.
*
* @return {boolean} Whether to include file in build.
*/
const filterPackages = overEvery( compact( [
isDirectory,
INCLUDE_PACKAGES && createCommaSeparatedFilter( includes, INCLUDE_PACKAGES ),
EXCLUDE_PACKAGES && createCommaSeparatedFilter( negate( includes ), EXCLUDE_PACKAGES ),
] ) );
/**
* Returns the absolute path of all WordPress packages
*
* @return {Array} Package paths
*/
function getPackages() {
return fs
.readdirSync( PACKAGES_DIR )
.filter( filterPackages )
.map( ( file ) => path.resolve( PACKAGES_DIR, file ) );
}
module.exports = getPackages;

View File

@ -5,4 +5,3 @@ echo "Initializing WooCommerce E2E"
wp plugin install woocommerce --activate
wp theme install twentynineteen --activate
wp user create customer customer@woocommercecoree2etestsuite.com --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.'

View File

@ -136,9 +136,15 @@ echo "Initializing WooCommerce E2E"
wp plugin install woocommerce --activate
wp theme install twentynineteen --activate
wp user create customer customer@woocommercecoree2etestsuite.com --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.'
```
### Additional Packages
There are a few packages you may find useful in writing tests scripts. You can see these in use in the `tests/e2e/utils` and `tests/e2e/specs` folders.
- `@wordpress/e2e-test-utils`
- `config`
### Travis CI
Add the following to the appropriate sections of your `.travis.yml` config file.

View File

@ -13,12 +13,13 @@ 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 ] ) {
arg = options.args ? options.args[ 0 ] : options[ 0 ];
if ( 'up' === arg ) {
command = 'up';
dockerArgs.push( 'up', '--build', '-d' );
}
if ( 'down' === options[ 0 ] ) {
if ( 'down' === arg ) {
command = 'down';
dockerArgs.push( 'down', '-v' );
}

View File

@ -7,7 +7,7 @@ module.exports = {
moduleNameMapper: {
'@woocommerce/e2e-tests/(.*)':
'<rootDir>/node_modules/woocommerce/tests/e2e/$1',
'<rootDir>/tests/e2e/$1',
},
preset: 'jest-puppeteer',
@ -16,7 +16,7 @@ module.exports = {
// A list of paths to modules that run some code to configure or set up the testing framework
// before each test
setupFilesAfterEnv: [
'<rootDir>/config/jest.setup.js',
'<rootDir>/build/setup/jest.setup.js',
'expect-puppeteer',
],

View File

@ -1,4 +1,4 @@
version: '3.7'
version: '3.3'
services:

View File

@ -33,6 +33,7 @@ if $(wp core is-installed);
then
echo "Wordpress is already installed..."
else
WORDPRESS_INSTALLING=1
declare -p WORDPRESS_TITLE >/dev/null
declare -p WORDPRESS_LOGIN >/dev/null
declare -p WORDPRESS_PASSWORD >/dev/null
@ -61,5 +62,14 @@ if ! [[ ${CURRENT_DOMAIN} == ${URL} ]]; then
wp search-replace ${CURRENT_DOMAIN} ${URL}
fi
if [[ $WORDPRESS_INSTALLING ]];
then
wp post create \
--post_type=page \
--post_status=publish \
--post_title='Ready' \
--post_content='E2E-tests.'
fi
echo "Visit $(wp option get siteurl)"
touch /var/www/html/.initialized

View File

@ -1,6 +1,6 @@
{
"name": "@woocommerce/e2e-environment",
"version": "0.1.0",
"version": "0.1.5",
"description": "WooCommerce End to End Testing Environment Configuration.",
"author": "Automattic",
"license": "GPL-3.0-or-later",
@ -19,19 +19,22 @@
"url": "https://github.com/woocommerce/woocommerce/issues"
},
"main": "index.js",
"module": "build-module/index.js",
"dependencies": {
"@wordpress/e2e-test-utils": "^4.6.0",
"@wordpress/jest-preset-default": "^5.4.0",
"app-root-path": "^3.0.0",
"jest": "^25.1.0",
"jest-puppeteer": "^4.4.0",
"puppeteer": "^2.1.1"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
"@babel/polyfill": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"@wordpress/e2e-test-utils": "^4.3.0",
"@wordpress/eslint-plugin": "^4.0.0",
"@wordpress/jest-preset-default": "^5.4.0",
"app-root-path": "^3.0.0",
"jest": "^25.1.0",
"jest-puppeteer": "^4.4.0",
"ndb": "^1.1.5",
"puppeteer": "^2.1.1",
"woocommerce": "git+https://github.com/woocommerce/woocommerce.git"
},
"publishConfig": {