diff --git a/.travis.yml b/.travis.yml
index 2c6e9b0..96ce5e6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
sudo: false
language: node_js
node_js:
- - '6'
- '4'
- - '0.12'
- - '0.10'
+ - '6'
+ - '7'
diff --git a/index.js b/index.js
index c50c607..621fc93 100644
--- a/index.js
+++ b/index.js
@@ -1,72 +1,55 @@
'use strict';
-var domain = require('domain'); // eslint-disable-line no-restricted-modules
-var gutil = require('gulp-util');
-var through = require('through');
-var Mocha = require('mocha');
-var plur = require('plur');
-var reqCwd = require('req-cwd');
-module.exports = function (opts) {
- opts = opts || {};
-
- var mocha = new Mocha(opts);
- var cache = {};
-
- for (var key in require.cache) { // eslint-disable-line guard-for-in
- cache[key] = true;
- }
-
- function clearCache() {
- for (var key in require.cache) {
- if (!cache[key] && !/\.node$/.test(key)) {
- delete require.cache[key];
- }
- }
- }
-
- if (Array.isArray(opts.require) && opts.require.length) {
- opts.require.forEach(function (x) {
- reqCwd(x);
- });
- }
-
- return through(function (file) {
- mocha.addFile(file.path);
- this.queue(file);
- }, function () {
- var self = this;
- var d = domain.create();
- var runner;
-
- function handleException(err) {
- if (runner) {
- runner.uncaught(err);
- } else {
- clearCache();
- self.emit('error', new gutil.PluginError('gulp-mocha', err, {
- stack: err.stack,
- showStack: true
- }));
- }
- }
-
- d.on('error', handleException);
- d.run(function () {
- try {
- runner = mocha.run(function (errCount) {
- clearCache();
-
- if (errCount > 0) {
- self.emit('error', new gutil.PluginError('gulp-mocha', errCount + ' ' + plur('test', errCount) + ' failed.', {
- showStack: false
- }));
- }
-
- self.emit('end');
- });
- } catch (err) {
- handleException(err);
- }
- });
- });
+const dargs = require('dargs');
+const execa = require('execa');
+const gutil = require('gulp-util');
+const through = require('through2');
+
+module.exports = options => {
+ const defaults = {colors: true, suppress: false};
+
+ options = Object.assign(defaults, options);
+
+ if (Object.prototype.toString.call(options.globals) === '[object Array]') {
+ // typically wouldn't modify passed options, but mocha requires a comma-
+ // separated list of names, http://mochajs.org/#globals-names, whereas dargs
+ // will treat arrays differently.
+ options.globals = options.globals.join(',');
+ }
+
+ // exposing args for testing
+ const args = dargs(options, {excludes: ['suppress'], ignoreFalse: true});
+ const files = [];
+
+ function aggregate(file, encoding, done) {
+ if (file.isNull()) {
+ return done(null, file);
+ }
+
+ if (file.isStream()) {
+ return done(new gutil.PluginError('gulp-mocha', 'Streaming not supported'));
+ }
+
+ files.push(file.path);
+
+ return done();
+ }
+
+ function flush(done) {
+ execa('mocha', files.concat(args))
+ .then(result => {
+ if (!options.suppress) {
+ process.stdout.write(result.stdout);
+ }
+
+ this.emit('result', result);
+ done();
+ })
+ .catch(err => {
+ this.emit('error', new gutil.PluginError('gulp-mocha', err));
+ done();
+ });
+ }
+
+ return through.obj(aggregate, flush);
};
diff --git a/package.json b/package.json
index cf6ed0b..74886d7 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"url": "sindresorhus.com"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4"
},
"scripts": {
"test": "xo && mocha"
@@ -33,12 +33,11 @@
"tap"
],
"dependencies": {
+ "dargs": "^5.1.0",
+ "execa": "^0.6.0",
"gulp-util": "^3.0.0",
"mocha": "^3.0.0",
- "plur": "^2.1.0",
- "req-cwd": "^1.0.1",
- "temp": "^0.8.3",
- "through": "^2.3.4"
+ "through2": "^2.0.3"
},
"devDependencies": {
"xo": "*"
@@ -47,6 +46,7 @@
"envs": [
"node",
"mocha"
- ]
+ ],
+ "space": true
}
}
diff --git a/readme.md b/readme.md
index 1cd601c..1fd231f 100644
--- a/readme.md
+++ b/readme.md
@@ -26,7 +26,7 @@ $ npm install --save-dev gulp-mocha
const gulp = require('gulp');
const mocha = require('gulp-mocha');
-gulp.task('default', () =>
+gulp.task('default', () =>
gulp.src('test.js', {read: false})
// gulp-mocha needs filepaths so you can't have any plugins before it
.pipe(mocha({reporter: 'nyan'}))
@@ -42,6 +42,10 @@ gulp.task('default', () =>
#### options
+gulp-mocha will pass any options defined directly to the `mocha` binary. That
+means you have every [command line option](http://mochajs.org/#usage) available
+by default. Listed below are some of the more commonly used options:
+
##### ui
Type: `string`
@@ -80,12 +84,12 @@ Default: `false`
Bail on the first test failure.
-##### ignoreLeaks
+##### checkLeaks
Type: `boolean`
Default: `false`
-Ignore global leaks.
+Check for global variable leaks.
##### grep
@@ -107,7 +111,7 @@ Require custom modules before tests are run.
If your test suite is not exiting it might be because you still have a lingering callback, most often caused by an open database connection. You should close this connection or do the following:
```js
-gulp.task('default', () =>
+gulp.task('default', () =>
gulp.src('test.js')
.pipe(mocha())
.once('error', () => {
diff --git a/test/fixtures/fixture-async.js b/test/fixtures/fixture-async.js
index 332da87..49eb53c 100644
--- a/test/fixtures/fixture-async.js
+++ b/test/fixtures/fixture-async.js
@@ -3,7 +3,7 @@
var assert = require('assert');
it('should fail after timeout', function (done) {
- setTimeout(function () {
- assert(false);
- }, 10);
+ setTimeout(function () {
+ assert(false);
+ }, 10);
});
diff --git a/test/fixtures/fixture-fail.js b/test/fixtures/fixture-fail.js
index ae07f1d..1a19cfe 100644
--- a/test/fixtures/fixture-fail.js
+++ b/test/fixtures/fixture-fail.js
@@ -2,5 +2,5 @@
var assert = require('assert');
it('should fail', function () {
- assert(false);
+ assert(false);
});
diff --git a/test/fixtures/fixture-pass.js b/test/fixtures/fixture-pass.js
index 938a935..2f5472e 100644
--- a/test/fixtures/fixture-pass.js
+++ b/test/fixtures/fixture-pass.js
@@ -2,5 +2,5 @@
var assert = require('assert');
it('should pass', function () {
- assert(true);
+ assert(true);
});
diff --git a/test/fixtures/fixture-throws-uncaught.js b/test/fixtures/fixture-throws-uncaught.js
index 45b9b60..2231295 100644
--- a/test/fixtures/fixture-throws-uncaught.js
+++ b/test/fixtures/fixture-throws-uncaught.js
@@ -2,7 +2,7 @@
var assert = require('assert');
it('throws after timeout', function (done) {
- setTimeout(function () {
- throw new Error('Exception in delayed function');
- }, 10);
+ setTimeout(function () {
+ throw new Error('Exception in delayed function');
+ }, 10);
});
diff --git a/test/fixtures/fixture-throws.js b/test/fixtures/fixture-throws.js
index e87d2ab..ae70231 100644
--- a/test/fixtures/fixture-throws.js
+++ b/test/fixtures/fixture-throws.js
@@ -2,5 +2,5 @@
var assert = require('assert');
it('contains syntax errors', function () {
- assert false;
+ assert false;
});
diff --git a/test/require-test.js b/test/require-test.js
deleted file mode 100644
index 77b5f52..0000000
--- a/test/require-test.js
+++ /dev/null
@@ -1,49 +0,0 @@
-'use strict';
-var path = require('path');
-var fs = require('fs');
-var assert = require('assert');
-var temp = require('temp');
-var mocha = require('../');
-
-var tempFile;
-var tempFileBaseName;
-var filePrefix = './';
-
-function removeFile(file) {
- try {
- fs.unlinkSync(file);
- } catch (err) {}
-}
-
-beforeEach(function () {
- tempFile = temp.path({
- dir: process.cwd(),
- suffix: '.js'
- });
-
- tempFileBaseName = path.basename(tempFile);
-
- fs.writeFileSync(tempFile, '');
-});
-
-afterEach(function () {
- removeFile(tempFile);
-});
-
-it('should fail when trying to require a file that doesn\'t exist', function () {
- removeFile(tempFile);
-
- assert.throws(function () {
- mocha({require: [filePrefix + tempFileBaseName]});
- });
-});
-
-it('should be able to import js-files in cwd', function () {
- mocha({require: [filePrefix + tempFileBaseName]});
-});
-
-it('should fail when not having the ./ file prefix', function () {
- assert.throws(function () {
- mocha({require: [tempFileBaseName]});
- });
-});
diff --git a/test/test.js b/test/test.js
index 8b24687..98c50f0 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,140 +1,65 @@
'use strict';
-var assert = require('assert');
-var gutil = require('gulp-util');
-var mocha = require('../');
-var out = process.stdout.write.bind(process.stdout);
-var err = process.stderr.write.bind(process.stderr);
-
-afterEach(function () {
- process.stdout.write = out;
- process.stderr.write = err;
-});
-
-it('should run unit test and pass', function (cb) {
- var stream = mocha();
-
- process.stdout.write = function (str) {
- if (/1 passing/.test(str)) {
- assert(true);
- cb();
- }
- };
-
- stream.write(new gutil.File({path: './test/fixtures/fixture-pass.js'}));
- stream.end();
-});
-
-it('should run unit test and fail', function (cb) {
- var stream = mocha();
-
- process.stdout.write = function (str) {
- if (/1 failing/.test(str)) {
- assert(true);
- cb();
- }
- };
-
- stream.once('error', function () {});
- stream.write(new gutil.File({path: './test/fixtures/fixture-fail.js'}));
- stream.end();
-});
-
-it('should call the callback right after end', function (cb) {
- var stream = mocha();
-
- stream.once('end', function () {
- assert(true);
- cb();
- });
-
- stream.end();
-});
-
-it('should clear cache after successful run', function (done) {
- var stream = mocha();
-
- stream.once('end', function () {
- for (var key in require.cache) {
- if (/fixture-pass/.test(key.toString())) {
- done(new Error('require cache still contained: ' + key));
- return;
- }
- }
-
- done();
- });
-
- stream.write(new gutil.File({path: './test/fixtures/fixture-pass.js'}));
- stream.end();
-});
-
-it('should clear cache after failing run', function (done) {
- var stream = mocha();
-
- stream.once('error', function () {
- for (var key in require.cache) {
- if (/fixture-fail/.test(key.toString())) {
- done(new Error('require cache still contained: ' + key));
- return;
- }
- }
-
- done();
- });
-
- stream.write(new gutil.File({path: './test/fixtures/fixture-fail.js'}));
- stream.end();
-});
-
-it('should clear cache after mocha threw', function (done) {
- var stream = mocha();
-
- stream.once('error', function () {
- for (var key in require.cache) {
- if (/fixture-pass/.test(key.toString()) || /fixture-throws/.test(key.toString())) {
- done(new Error('require cache still contained: ' + key));
- return;
- }
- }
-
- done();
- });
- stream.write(new gutil.File({path: './test/fixtures/fixture-pass.js'}));
- stream.write(new gutil.File({path: './test/fixtures/fixture-throws.js'}));
- stream.end();
-});
-
-it('should clear cache after mocha threw uncaught exception', function (done) {
- var stream = mocha();
-
- stream.once('error', function () {
- for (var key in require.cache) {
- if (/fixture-pass/.test(key.toString()) || /fixture-throws/.test(key.toString())) {
- done(new Error('require cache still contained: ' + key));
- return;
- }
- }
-
- done();
- });
- stream.write(new gutil.File({path: './test/fixtures/fixture-pass.js'}));
- stream.write(new gutil.File({path: './test/fixtures/fixture-throws-uncaught.js'}));
- stream.end();
-});
-
-it('should pass async AssertionError to mocha', function (done) {
- var stream = mocha();
-
- process.stdout.write = function (str) {
- if (/throws after timeout/.test(str)) {
- done(new Error('mocha timeout not expected'));
- } else if (/Uncaught AssertionError: false == true/.test(str)) {
- done();
- }
- };
-
- stream.once('error', function () {});
- stream.write(new gutil.File({path: './test/fixtures/fixture-async.js'}));
- stream.end();
+const assert = require('assert');
+const fs = require('fs');
+const path = require('path');
+const gutil = require('gulp-util');
+const mocha = require('../');
+
+function fixture(name) {
+ let fileName = path.join(__dirname, 'fixtures', name);
+
+ return new gutil.File({
+ path: fileName,
+ contents: fs.existsSync(fileName) ? fs.readFileSync(fileName) : null
+ });
+}
+
+describe('mocha()', () => {
+ it('should run unit test and pass', done => {
+ let stream = mocha({suppress: true});
+
+ stream.once('result', result => {
+ assert(/1 passing/.test(result.stdout));
+ done();
+ });
+ stream.write(fixture('fixture-pass.js'));
+ stream.end();
+ });
+
+ it('should run unit test and fail', done => {
+ let stream = mocha({suppress: true});
+
+ stream.once('error', function (err) {
+ assert(/1 failing/.test(err.stdout));
+ done();
+ });
+ stream.write(fixture('fixture-fail.js'));
+ stream.end();
+ });
+
+ it('should pass async AssertionError to mocha', function (done) {
+ let stream = mocha({suppress: true});
+
+ stream.once('error', function (err) {
+ let throws = /throws after timeout/.test(err.stdout);
+ let uncaught = /Uncaught AssertionError: false == true/.test(err.stdout);
+
+ assert(throws || uncaught);
+ done();
+ });
+ stream.write(fixture('fixture-async.js'));
+ stream.end();
+ });
+
+ it('should not suppress output', done => {
+ let stream = mocha();
+
+ stream.once('result', result => {
+ assert(/should pass/.test(result.stdout));
+ done();
+ });
+ stream.write(fixture('fixture-pass.js'));
+ stream.end();
+ });
});