diff --git a/docs/_includes/head.html b/docs/_includes/head.html index a3ef57cd85..e362b8ca95 100644 --- a/docs/_includes/head.html +++ b/docs/_includes/head.html @@ -2,6 +2,7 @@ {{ page.title }} + diff --git a/docs/index.md b/docs/index.md index 126a9c4544..a194b3643e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,7 @@ --- layout: default title: 'Mocha - the fun, simple, flexible JavaScript test framework' +description: 'Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun.' --- Mocha is a feature-rich JavaScript test framework running on [Node.js](https://nodejs.org) and in the browser, making asynchronous testing *simple* and *fun*. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on [GitHub](https://github.com/mochajs/mocha). diff --git a/lib/cli/run-helpers.js b/lib/cli/run-helpers.js index 5212d386db..95d1c2fc08 100644 --- a/lib/cli/run-helpers.js +++ b/lib/cli/run-helpers.js @@ -14,7 +14,6 @@ const path = require('path'); const utils = require('../utils'); const minimatch = require('minimatch'); const ansi = require('ansi-colors'); -const symbols = require('log-symbols'); const cwd = (exports.cwd = process.cwd()); @@ -138,13 +137,14 @@ exports.handleFiles = ({ spec = [] } = {}) => { let files = []; + const errors = []; spec.forEach(arg => { let newFiles; try { newFiles = utils.lookupFiles(arg, extension, recursive); } catch (err) { if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') { - console.warn('Warning: %s: %O', err.message, err.pattern); + errors.push(err.message); return; } @@ -164,8 +164,16 @@ exports.handleFiles = ({ }); if (!files.length) { - console.error(ansi.red(`${symbols.error} No test files found`)); + // print messages as an error + errors.forEach(message => { + console.error(ansi.red(`Error: ${message}`)); + }); process.exit(1); + } else { + // print messages as an warning + errors.forEach(message => { + console.warn(ansi.yellow(`Warning: ${message}`)); + }); } const fileArgs = file.map(filepath => path.resolve(filepath)); diff --git a/lib/mocha.js b/lib/mocha.js index 100d6f2a9d..687f5c77a3 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -238,13 +238,6 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) { } } } - if (!_reporter && reporter === 'teamcity') { - console.warn( - 'The Teamcity reporter was moved to a package named ' + - 'mocha-teamcity-reporter ' + - '(https://npmjs.org/package/mocha-teamcity-reporter).' - ); - } if (!_reporter) { throw createInvalidReporterError( 'invalid reporter "' + reporter + '"', diff --git a/lib/utils.js b/lib/utils.js index f2f2af4145..c6d42ba9a5 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -520,7 +520,7 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) { files = glob.sync(filepath); if (!files.length) { throw createNoFilesMatchPatternError( - 'cannot find any files matching pattern "' + filepath + '"', + 'Cannot find any files matching pattern "' + filepath + '"', filepath ); } diff --git a/test/integration/events.spec.js b/test/integration/events.spec.js new file mode 100644 index 0000000000..dc08a57381 --- /dev/null +++ b/test/integration/events.spec.js @@ -0,0 +1,59 @@ +'use strict'; + +var helpers = require('./helpers'); +var runMochaJSON = helpers.runMochaJSON; + +describe('event order', function() { + describe('trivial test case', function() { + it('should assert trivial event order', function(done) { + runMochaJSON('runner/events-basic.fixture.js', [], function(err, res) { + if (err) { + done(err); + return; + } + expect(res, 'to have passed') + .and('to have passed test count', 2) + .and('to have passed test order', 'test A', 'test B') + .and('to have failed test count', 0); + done(); + }); + }); + }); + + describe('--bail test case', function() { + it('should assert --bail event order', function(done) { + runMochaJSON('runner/events-bail.fixture.js', ['--bail'], function( + err, + res + ) { + if (err) { + done(err); + return; + } + expect(res, 'to have failed with error', 'error test A') + .and('to have failed test count', 1) + .and('to have passed test count', 0); + done(); + }); + }); + }); + + describe('--retries test case', function() { + it('should assert --retries event order', function(done) { + runMochaJSON( + 'runner/events-retries.fixture.js', + ['--retries', '1'], + function(err, res) { + if (err) { + done(err); + return; + } + expect(res, 'to have failed with error', 'error test A') + .and('to have failed test count', 1) + .and('to have passed test count', 0); + done(); + } + ); + }); + }); +}); diff --git a/test/integration/fixtures/runner/events-bail.fixture.js b/test/integration/fixtures/runner/events-bail.fixture.js new file mode 100644 index 0000000000..3a345f8169 --- /dev/null +++ b/test/integration/fixtures/runner/events-bail.fixture.js @@ -0,0 +1,29 @@ +'use strict'; +var Runner = require('../../../../lib/runner.js'); +var assert = require('assert'); + +var emitOrder = [ + 'suite'/* incorrect order*/, 'start', 'suite', + 'hook', 'hook end', 'test', 'hook', 'hook end', 'fail', 'test end', 'hook', 'hook end', + 'hook', 'hook end', 'suite end', 'suite end', 'end' +]; + +var realEmit = Runner.prototype.emit; +Runner.prototype.emit = function(event, ...args) { + // console.log(`emit: ${event}`); + assert.strictEqual(event, emitOrder.shift()); + return realEmit.call(this, event, ...args); +}; + +describe('suite A', function() { + before('before', function() {}); + beforeEach('beforeEach', function() {}); + it('test A', function() { + throw new Error('error test A'); + }); + describe('suite B', function() { + it('test B', function() {}); + }); + afterEach('afterEach', function() {}); + after('after', function() {}); +}); diff --git a/test/integration/fixtures/runner/events-basic.fixture.js b/test/integration/fixtures/runner/events-basic.fixture.js new file mode 100644 index 0000000000..81c55a8bb4 --- /dev/null +++ b/test/integration/fixtures/runner/events-basic.fixture.js @@ -0,0 +1,28 @@ +'use strict'; +var Runner = require('../../../../lib/runner.js'); +var assert = require('assert'); + +var emitOrder = [ + 'suite'/* incorrect order*/, 'start', 'suite', + 'hook', 'hook end', 'test', 'hook', 'hook end', 'pass', 'test end', 'hook', 'hook end', + 'suite', 'test', 'hook', 'hook end', 'pass', 'test end', 'hook', 'hook end', + 'suite end', 'hook', 'hook end', 'suite end', 'suite end', 'end' +]; + +var realEmit = Runner.prototype.emit; +Runner.prototype.emit = function(event, ...args) { + // console.log(`emit: ${event}`); + assert.strictEqual(event, emitOrder.shift()); + return realEmit.call(this, event, ...args); +}; + +describe('suite A', function() { + before('before', function() {}); + beforeEach('beforeEach', function() {}); + it('test A', function() {}); + describe('suite B', function() { + it('test B', function() {}); + }); + afterEach('afterEach', function() {}); + after('after', function() {}); +}); diff --git a/test/integration/fixtures/runner/events-retries.fixture.js b/test/integration/fixtures/runner/events-retries.fixture.js new file mode 100644 index 0000000000..a4547c8fa8 --- /dev/null +++ b/test/integration/fixtures/runner/events-retries.fixture.js @@ -0,0 +1,27 @@ +'use strict'; +var Runner = require('../../../../lib/runner.js'); +var assert = require('assert'); + +var emitOrder = [ + 'suite'/* incorrect order*/, 'start', 'suite', + 'hook', 'hook end', 'test', 'hook', 'hook end', 'retry', 'hook', 'hook end', + 'test', 'hook', 'hook end', 'fail', 'test end', 'hook', 'hook end', 'hook', 'hook end', + 'suite end', 'suite end', 'end' +]; + +var realEmit = Runner.prototype.emit; +Runner.prototype.emit = function(event, ...args) { + // console.log(`emit: ${event}`); + assert.strictEqual(event, emitOrder.shift()); + return realEmit.call(this, event, ...args); +}; + +describe('suite A', function() { + before('before', function() {}); + beforeEach('beforeEach', function() {}); + it('test A', function() { + throw new Error('error test A'); + }); + afterEach('afterEach', function() {}); + after('after', function() {}); +}); diff --git a/test/integration/glob.spec.js b/test/integration/glob.spec.js index 6aa7563bf5..da1f5f35c6 100644 --- a/test/integration/glob.spec.js +++ b/test/integration/glob.spec.js @@ -28,7 +28,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern "./*-none.js"' + 'Error: Cannot find any files matching pattern "./*-none.js"' ); }, done @@ -47,7 +47,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern' + 'Warning: Cannot find any files matching pattern' ); }, done @@ -77,7 +77,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern' + 'Error: Cannot find any files matching pattern "./*-none.js"' ); }, done @@ -96,7 +96,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern' + 'Warning: Cannot find any files matching pattern' ); }, done @@ -125,7 +125,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern' + 'Error: Cannot find any files matching pattern "./**/*-none.js"' ); }, done @@ -144,7 +144,7 @@ describe('globbing', function() { expect( results.stderr, 'to contain', - 'cannot find any files matching pattern' + 'Warning: Cannot find any files matching pattern' ); }, done diff --git a/test/node-unit/cli/run-helpers.spec.js b/test/node-unit/cli/run-helpers.spec.js index b3a0fb5520..a2a63335f5 100644 --- a/test/node-unit/cli/run-helpers.spec.js +++ b/test/node-unit/cli/run-helpers.spec.js @@ -19,7 +19,7 @@ describe('cli "run" command', function() { it('should disallow an array of module names', function() { expect( () => validatePlugin({foo: ['bar']}, 'foo'), - 'to throw', + 'to throw a', TypeError ); });