Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/gulp-mocha
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 212def2e520a120d901dd35f2c34b86316630f89
Choose a base ref
...
head repository: sindresorhus/gulp-mocha
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: be439ff5aca864a35af6f5e9e30d59b51a4fb707
Choose a head ref
  • 3 commits
  • 12 files changed
  • 2 contributors

Commits on Feb 20, 2017

  1. Copy the full SHA
    3e55175 View commit details
  2. Cleanup #151

    sindresorhus committed Feb 20, 2017
    Copy the full SHA
    f9de4ec View commit details
  3. 4.0.0

    sindresorhus committed Feb 20, 2017
    Copy the full SHA
    be439ff View commit details
Showing with 124 additions and 267 deletions.
  1. +1 −0 .gitattributes
  2. +0 −2 .travis.yml
  3. +49 −61 index.js
  4. +5 −6 package.json
  5. +9 −12 readme.md
  6. +3 −4 test/fixtures/fixture-async.js
  7. +2 −2 test/fixtures/fixture-fail.js
  8. +2 −2 test/fixtures/fixture-pass.js
  9. +3 −3 test/fixtures/fixture-throws-uncaught.js
  10. +2 −2 test/fixtures/fixture-throws.js
  11. +0 −49 test/require-test.js
  12. +48 −124 test/test.js
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* text=auto
*.js text eol=lf
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -3,5 +3,3 @@ language: node_js
node_js:
- '6'
- '4'
- '0.12'
- '0.10'
110 changes: 49 additions & 61 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,60 @@
'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;
const dargs = require('dargs');
const execa = require('execa');
const gutil = require('gulp-util');
const through = require('through2');

module.exports = opts => {
opts = Object.assign({
colors: true,
suppress: false
}, opts);

if (Array.isArray(opts.globals)) {
// `globals` option should end up as a comma-separated list
opts.globals = opts.globals.join(',');
}

function clearCache() {
for (var key in require.cache) {
if (!cache[key] && !/\.node$/.test(key)) {
delete require.cache[key];
}
}
}
const args = dargs(opts, {
excludes: ['suppress'],
ignoreFalse: true
});

if (Array.isArray(opts.require) && opts.require.length) {
opts.require.forEach(function (x) {
reqCwd(x);
});
}
const files = [];

return through(function (file) {
mocha.addFile(file.path);
this.queue(file);
}, function () {
var self = this;
var d = domain.create();
var runner;
function aggregate(file, encoding, done) {
if (file.isNull()) {
done(null, file);
return;
}

function handleException(err) {
if (runner) {
runner.uncaught(err);
} else {
clearCache();
self.emit('error', new gutil.PluginError('gulp-mocha', err, {
stack: err.stack,
showStack: true
}));
}
if (file.isStream()) {
done(new gutil.PluginError('gulp-mocha', 'Streaming not supported'));
return;
}

d.on('error', handleException);
d.run(function () {
try {
runner = mocha.run(function (errCount) {
clearCache();
files.push(file.path);

done();
}

if (errCount > 0) {
self.emit('error', new gutil.PluginError('gulp-mocha', errCount + ' ' + plur('test', errCount) + ' failed.', {
showStack: false
}));
}
function flush(done) {
execa('mocha', files.concat(args))
.then(result => {
if (!opts.suppress) {
process.stdout.write(result.stdout);
}

// For testing
this.emit('_result', result);

done();
})
.catch(err => {
this.emit('error', new gutil.PluginError('gulp-mocha', err));
done();
});
}

self.emit('end');
});
} catch (err) {
handleException(err);
}
});
});
return through.obj(aggregate, flush);
};
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gulp-mocha",
"version": "3.0.1",
"version": "4.0.0",
"description": "Run Mocha tests",
"license": "MIT",
"repository": "sindresorhus/gulp-mocha",
@@ -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": "*"
21 changes: 9 additions & 12 deletions readme.md
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@

---

<p align="center"><b>🔥 Want to strengthen your core JavaScript skills and master ES6?</b><br>I would personally recommend this awesome <a href="https://ES6.io/friend/AWESOME">ES6 course</a> by Wes Bos.</p>
<p align="center"><b>🔥 Want to strengthen your core JavaScript skills and master ES6?</b><br>I would personally recommend this awesome <a href="https://ES6.io/friend/AWESOME">ES6 course</a> by Wes Bos. You might also like his <a href="https://ReactForBeginners.com/friend/AWESOME">React course</a>.</p>

---

@@ -26,22 +26,23 @@ $ 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
// `gulp-mocha` needs filepaths so you can't have any plugins before it
.pipe(mocha({reporter: 'nyan'}))
);
```

> If you are writing a watch task to run your tests as you modify your `.js` files, be aware that you might run into issues. This plugin runs your Mocha tests within the same process as your watch task and state isn't reset between runs. If your tests eventually fail within the watch task but pass when run in a standalone task or with `mocha test`, then you need to use the [`gulp-spawn-mocha`](https://github.com/KenPowers/gulp-spawn-mocha) plugin.

## API

### mocha([options])

#### options

Options are passed directly to the `mocha` binary, so you can use any its [command-line options](http://mochajs.org/#usage) in a camelCased form. Listed below are some of the more commonly used options:


##### ui

Type: `string`<br>
@@ -80,12 +81,12 @@ Default: `false`

Bail on the first test failure.

##### ignoreLeaks
##### checkLeaks

Type: `boolean`<br>
Default: `false`

Ignore global leaks.
Check for global variable leaks.

##### grep

@@ -107,7 +108,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', () => {
@@ -119,10 +120,6 @@ gulp.task('default', () =>
);
```

### Babel

Add `require('babel-core/register');` to the top of your `gulpfile.js`. Make sure to read the [Babel docs](https://babeljs.io/docs/usage/require/).


## License

7 changes: 3 additions & 4 deletions test/fixtures/fixture-async.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* global it */
'use strict';
var assert = require('assert');
const assert = require('assert');

it('should fail after timeout', function (done) {
setTimeout(function () {
it('should fail after timeout', (done) => {
setTimeout(() => {
assert(false);
}, 10);
});
4 changes: 2 additions & 2 deletions test/fixtures/fixture-fail.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
var assert = require('assert');
const assert = require('assert');

it('should fail', function () {
it('should fail', () => {
assert(false);
});
4 changes: 2 additions & 2 deletions test/fixtures/fixture-pass.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
var assert = require('assert');
const assert = require('assert');

it('should pass', function () {
it('should pass', () => {
assert(true);
});
6 changes: 3 additions & 3 deletions test/fixtures/fixture-throws-uncaught.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';
var assert = require('assert');
const assert = require('assert');

it('throws after timeout', function (done) {
setTimeout(function () {
it('throws after timeout', () => {
setTimeout(() => {
throw new Error('Exception in delayed function');
}, 10);
});
4 changes: 2 additions & 2 deletions test/fixtures/fixture-throws.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
var assert = require('assert');
const assert = require('assert');

it('contains syntax errors', function () {
it('contains syntax errors', () => {
assert false;
});
49 changes: 0 additions & 49 deletions test/require-test.js

This file was deleted.

172 changes: 48 additions & 124 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,140 +1,64 @@
'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();
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const gutil = require('gulp-util');
const mocha = require('..');

function fixture(name) {
const fileName = path.join(__dirname, 'fixtures', name);

return new gutil.File({
path: fileName,
contents: fs.existsSync(fileName) ? fs.readFileSync(fileName) : null
});
}

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;
}
}
describe('mocha()', () => {
it('should run unit test and pass', done => {
const stream = mocha({suppress: true});

done();
stream.once('_result', result => {
assert(/1 passing/.test(result.stdout));
done();
});
stream.write(fixture('fixture-pass.js'));
stream.end();
});

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;
}
}
it('should run unit test and fail', done => {
const stream = mocha({suppress: true});

done();
stream.once('error', err => {
assert(/1 failing/.test(err.stdout));
done();
});
stream.write(fixture('fixture-fail.js'));
stream.end();
});
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();
it('should pass async AssertionError to mocha', done => {
const stream = mocha({suppress: true});

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;
}
}
stream.once('error', err => {
const throws = /throws after timeout/.test(err.stdout);
const uncaught = /Uncaught AssertionError: false == true/.test(err.stdout);

done();
assert(throws || uncaught);
done();
});
stream.write(fixture('fixture-async.js'));
stream.end();
});
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();
it('should not suppress output', done => {
const 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)) {
stream.once('_result', result => {
assert(/should pass/.test(result.stdout));
done();
}
};

stream.once('error', function () {});
stream.write(new gutil.File({path: './test/fixtures/fixture-async.js'}));
stream.end();
});
stream.write(fixture('fixture-pass.js'));
stream.end();
});
});