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
);
});