Skip to content

Commit

Permalink
Tests: Setup Jest as an alternative test runner (#1382)
Browse files Browse the repository at this point in the history
  • Loading branch information
gziolo authored and nylen committed Jul 6, 2017
1 parent 313e6c3 commit 1406fe8
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 89 deletions.
14 changes: 9 additions & 5 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
"extends": [
"wordpress",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended"
],
"plugin:jsx-a11y/recommended",
"plugin:jest/recommended"
],
"env": {
"browser": false,
"es6": true,
"node": true,
"mocha": true
},
"mocha": true,
"jest/globals": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
Expand All @@ -26,7 +28,8 @@
},
"plugins": [
"react",
"jsx-a11y"
"jsx-a11y",
"jest"
],
"settings": {
"react": {
Expand All @@ -46,6 +49,7 @@
"eol-last": "error",
"func-call-spacing": "error",
"indent": [ "error", "tab", { "SwitchCase": 1 } ],
"jest/valid-expect": "off",
"jsx-quotes": "error",
"key-spacing": "error",
"keyword-spacing": "error",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
build
coverage
gutenberg.pot
.vscode
*.log
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Gutenberg contains both PHP and JavaScript code, and encourages testing and code

### JavaScript Testing

Tests for JavaScript use [Mocha](https://mochajs.org/) as the test runner and [Chai BDD](http://chaijs.com/api/bdd/) as an assertion library (with a [small variation](https://github.com/prodatakey/dirty-chai) on assertion properties). If needed, you can also use [Sinon](http://sinonjs.org/) for mocking and [Enzyme](https://github.com/airbnb/enzyme) for React component testing.
Tests for JavaScript use [Jest](http://facebook.github.io/jest//) as the test runner. If needed, you can also use [Sinon](http://sinonjs.org/) for mocking and [Enzyme](https://github.com/airbnb/enzyme) for React component testing.

Assuming you've followed the instructions above to install Node and project dependencies, tests can be run from the command-line with NPM:

Expand Down
11 changes: 6 additions & 5 deletions blocks/api/test/paste.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { describe, it } from 'mocha';
/**
* External dependencies
*/
import { equal } from 'assert';
import { JSDOM } from 'jsdom';

const { window } = new JSDOM();
const { document } = window;

/**
* Internal dependencies
*/
import { normaliseToBlockLevelNodes } from '../paste';

describe( 'normaliseToBlockLevelNodes', () => {
Expand Down
5 changes: 5 additions & 0 deletions blocks/test/full-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ function normalizeParsedBlocks( blocks ) {
}

describe( 'full post content fixture', () => {
before( () => {
// Registers all blocks
require( 'blocks' );
} );

fileBasenames.forEach( f => {
it( f, () => {
const content = readFixtureFile( f + '.html' );
Expand Down
15 changes: 2 additions & 13 deletions components/form-token-field/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ const charCodes = {
comma: 44,
};

describe( 'FormTokenField', function() {
if ( ! process.env.RUN_SLOW_TESTS ) {
return;
}
const maybeDescribe = process.env.RUN_SLOW_TESTS ? describe : describe.skip;

maybeDescribe( 'FormTokenField', function() {
let wrapper, tokenFieldNode, textInputNode;

function setText( text ) {
Expand Down Expand Up @@ -181,9 +179,6 @@ describe( 'FormTokenField', function() {
} );

it( 'should manage the selected suggestion based on both keyboard and mouse events', test( function() {
// We need a high timeout here to accomodate Travis CI
this.timeout( 10000 );

setText( 'th' );
expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.th );
expect( getSelectedSuggestion() ).to.equal( null );
Expand Down Expand Up @@ -397,12 +392,6 @@ describe( 'FormTokenField', function() {
expect( textInputNode.prop( 'value' ) ).to.equal( ' quux' );
} );

it( 'should skip empty tokens at the beginning of a paste', function() {
setText( ', ,\t \t ,,baz, quux' );
expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'baz' ] );
expect( textInputNode.prop( 'value' ) ).to.equal( ' quux' );
} );

it( 'should skip empty tokens in the middle of a paste', function() {
setText( 'baz, ,\t \t ,,quux' );
expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'baz' ] );
Expand Down
2 changes: 1 addition & 1 deletion editor/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ describe( 'selectors', () => {
expect( getMultiSelectedBlockUids( state ) ).to.eql( [] );
} );

it( 'should return empty if there is no multi selection', () => {
it( 'should return selected block uids if there is multi selection', () => {
const state = {
editor: {
blockOrder: [ 5, 4, 3, 2, 1 ],
Expand Down
58 changes: 51 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@
"enzyme": "^2.8.2",
"eslint": "^3.17.1",
"eslint-config-wordpress": "^1.1.0",
"eslint-plugin-jest": "~20.0.3",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.3",
"expose-loader": "^0.7.3",
"extract-text-webpack-plugin": "^2.1.0",
"gettext-parser": "^1.2.2",
"glob": "^7.1.1",
"jsdom": "^10.1.0",
"mocha": "^3.2.0",
"jest": "~20.0.4",
"jest-junit-reporter": "~1.1.0",
"node-sass": "^4.5.0",
"pegjs": "^0.10.0",
"pegjs-loader": "^0.5.1",
Expand All @@ -82,11 +82,9 @@
"sinon-test": "^1.0.2",
"style-loader": "^0.14.1",
"tinymce": "^4.5.6",
"webpack": "^2.2.1",
"webpack-node-externals": "^1.5.4"
"webpack": "^2.2.1"
},
"scripts": {
"test-unit": "cross-env NODE_ENV=test webpack && mocha build --require bootstrap-test.js",
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
"gettext-strings": "cross-env BABEL_ENV=gettext webpack",
"lint": "eslint . .storybook",
Expand All @@ -95,6 +93,52 @@
"ci": "concurrently \"npm run build\" \"npm test\"",
"package-plugin": "./bin/build-plugin-zip.sh",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
"build-storybook": "build-storybook",
"test-unit": "jest",
"test-unit:coverage": "jest --coverage",
"test-unit:watch": "jest --watch"
},
"jest": {
"collectCoverageFrom": [
"**/blocks/**/*.js",
"**/components/**/*.js",
"**/date/**/*.js",
"**/editor/**/*.js",
"**/element/**/*.js",
"**/i18n/**/*.js",
"**/utils/**/*.js"
],
"coveragePathIgnorePatterns": [
"<rootDir>/components/clipboard-button/index.js",
"<rootDir>/components/notice/index.js",
"<rootDir>/components/notice/list.js",
"<rootDir>/components/form-toggle/index.js",
"<rootDir>/components/form-token-field/token.js"
],
"moduleNameMapper": {
"\\.scss$": "<rootDir>/test/style-mock.js"
},
"modulePaths": [
"<rootDir>"
],
"setupFiles": [
"<rootDir>/test/setup-globals.js",
"<rootDir>/test/setup-wp-aliases.js"
],
"setupTestFrameworkScriptFile": "<rootDir>/test/setup-test-framework.js",
"testMatch": [
"**/blocks/**/test/*.js",
"**/components/**/test/*.js",
"**/date/**/test/*.js",
"**/editor/**/test/*.js",
"**/element/**/test/*.js",
"**/i18n/**/test/*.js",
"**/utils/**/test/*.js" ],
"timers": "fake",
"transform": {
"^.+\\.jsx?$": "babel-jest",
"\\.pegjs$": "<rootDir>/test/pgejs-transform.js"
},
"verbose": true
}
}
16 changes: 16 additions & 0 deletions test/pgejs-transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const pegjs = require( 'pegjs' );

module.exports = {
process( src ) {
// Description of PEG.js options: https://github.com/pegjs/pegjs#javascript-api
const pegOptions = {
output: 'source',
cache: false,
optimize: 'speed',
trace: false,
};
const methodName = ( typeof pegjs.generate === 'function' ) ? 'generate' : 'buildParser';

return `module.exports = ${ pegjs[ methodName ]( src, pegOptions ) };`;
},
};
27 changes: 1 addition & 26 deletions bootstrap-test.js → test/setup-globals.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
// Chai plugins
require( 'chai' )
.use( require( 'dirty-chai' ) )
.use( require( 'sinon-chai' ) );

// Sinon plugins
const sinon = require( 'sinon' );
const sinonTest = require( 'sinon-test' );
sinon.test = sinonTest.configureTest( sinon );
sinon.testCase = sinonTest.configureTestCase( sinon );

// Fake DOM
const { JSDOM } = require( 'jsdom' );
const dom = new JSDOM( '', {
features: {
FetchExternalResources: false,
ProcessExternalResources: false,
SkipExternalResources: true,
},
} );

global.window = dom.window;
global.document = dom.window.document;
global.navigator = dom.window.navigator;
global.requestAnimationFrame = window.setTimeout;

// These are necessary to load TinyMCE successfully
global.URL = window.URL;
global.window.tinyMCEPreInit = {
Expand Down Expand Up @@ -60,6 +34,7 @@ global.window._wpDateSettings = {
string: 'America/New_York',
},
};

global.wp = global.wp || {};
global.wp.a11y = {
speak: () => {},
Expand Down
17 changes: 17 additions & 0 deletions test/setup-test-framework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require( 'core-js/modules/es7.object.values' );

// Chai plugins
require( 'chai' )
.use( require( 'dirty-chai' ) )
.use( require( 'sinon-chai' ) );

// Sinon plugins
const sinon = require( 'sinon' );
const sinonTest = require( 'sinon-test' );
sinon.test = sinonTest.configureTest( sinon );
sinon.testCase = sinonTest.configureTestCase( sinon );

// Make sure we can share test helpers between Mocha and Jest
global.after = global.afterAll;
global.before = global.beforeAll;
global.context = global.describe;
18 changes: 18 additions & 0 deletions test/setup-wp-aliases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const lazySetupAlias = object =>
name =>
Object.defineProperty( object, name, {
get: () => require( name ),
} );
const lazySetupWpAlias = lazySetupAlias( global.wp );

const entryPointNames = [
'element',
'i18n',
'components',
'utils',
'blocks',
'date',
'editor',
];

entryPointNames.forEach( lazySetupWpAlias );
1 change: 1 addition & 0 deletions test/style-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {};
31 changes: 0 additions & 31 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/**
* External dependencies
*/

const glob = require( 'glob' );
const webpack = require( 'webpack' );
const ExtractTextPlugin = require( 'extract-text-webpack-plugin' );

Expand Down Expand Up @@ -149,35 +147,6 @@ switch ( process.env.NODE_ENV ) {
config.plugins.push( new webpack.optimize.UglifyJsPlugin() );
break;

case 'test':
config.target = 'node';
config.node = {
__dirname: true,
};
config.module.rules = [
...entryPointNames.map( ( entry ) => ( {
test: require.resolve( './' + entry + '/index.js' ),
use: 'expose-loader?wp.' + entry,
} ) ),
...config.module.rules,
];
const testFiles = glob.sync(
'./{' + Object.keys( config.entry ).sort() + '}/**/test/*.js'
);
config.entry = [
...entryPointNames.map(
entryPointName => './' + entryPointName + '/index.js'
),
...testFiles.filter( f => /full-content\.js$/.test( f ) ),
...testFiles.filter( f => ! /full-content\.js$/.test( f ) ),
];
config.externals = [ require( 'webpack-node-externals' )() ];
config.output = {
filename: 'build/test.js',
path: __dirname,
};
break;

default:
config.devtool = 'source-map';
}
Expand Down

0 comments on commit 1406fe8

Please sign in to comment.