UNPKG

gulp-spawn-mocha

Version:
131 lines (123 loc) 4.48 kB
// Module Requirements var _ = require('lodash'), fs = require('fs'), through = require('through'), proc = require('child_process'), join = require('path').join, PluginError = require('plugin-error'); /** * Returns a stream to use with Gulp which executes the passed files as Mocha * tests with given options. Child process inherits stdin and stdout. * @param {Object} ops Options to pass to the mocha executable (see `mocha * -h`). Also accepts additional `bin` property to specifiy custom mocha * binary. * @return {Stream} A readable and writable stream which excutes Mocha, * piping stdout and stderr to the process stdout and stderr. */ module.exports = function (ops, coverage) { // Default ops ops = ops || {}; // Setup var ist = ops.istanbul; var output = ops.output; // Using istanbul? Use _mocha, otherwise use mocha in order to support full node options (e.g., --debug-brk) var bin = ops.bin || join(require.resolve('mocha'), '..', 'bin', ist ? '_mocha' : 'mocha'); var env = _.extend(_.clone(process.env), ops.env || {}); var cwd = ops.cwd; var execPath = ops.execPath || process.execPath; ops = _.omit(ops, ['bin', 'env', 'istanbul', 'cwd', 'execPath']); // Create stream var stream = through(function (file) { this._files.push(file.path); }, function () { // make sure there are files to test if (this._files.length === 0) { this.emit('end'); return; }; // Save refernce to this (bindless context cheat) var that = this; // Parse arguments var args = parseArgs(ops); // Using istanbul? if (ist) { args.unshift('--', bin); // The non-standard location of istanbul's bin makes me a wee bit nervous. Find it by inspecting package.json. bin = ist.bin || join(require.resolve('istanbul'), '..', require('istanbul/package.json').bin.istanbul); // If the value for istanbul is literally true, just keep the arguments array. Otherwise, parse istanbul options. args = ist === true ? args : parseArgs(_.omit(ist, ['bin'])).concat(args); args.unshift('cover'); } // Execute Mocha, stdin and stdout are inherited this._child = proc.fork(bin, args.concat(this._files), {cwd: cwd, env: env, execPath: execPath, silent: !!output, execArgv: []}); // If there's an error running the process. See http://nodejs.org/api/child_process.html#child_process_event_error this._child.on('error', function (e) { that.emit('error', new PluginError('gulp-spawn-mocha', e)); that.emit('end'); }); // When done... this._child.on('close', function (code, signal) { // If code is not zero (falsy) if (code) { that.emit('error', new PluginError('gulp-spawn-mocha', 'Mocha exited with code ' + code)); } // If code is null (process was terminated due to a signal) if (code == null && signal) { that.emit('error', new PluginError('gulp-spawn-mocha', 'Mocha was terminated by ' + signal)); } that.emit('end'); }); // Output to a file if (output) { var s = _.isString(output) ? fs.createWriteStream(output) : output; that._child.stdout.pipe(s); that._child.stderr.pipe(s); } }); // Attach files array to stream stream._files = []; // Return stream return stream; }; /** * Parses the arugments from a configuration object for passing to a mocha * executable. * @param {Object} obj The object to parse from. * @return {Array} An array of parsed arguments. */ function parseArgs(obj) { var args = []; _.each(obj, function (val, key) { if (_.isArray(val)) { _.each(val, function (val) { addArg(args, key, val); }); } else { addArg(args, key, val); } }); return args; } /** * Adds a given argument with name and value to arugment array. * @param {Array} args String array of arguments. * @param {String} name Name of the argument. * @param {String} val Value of the argument. Returns without doing anything * if falsy and not zero. */ function addArg(args, name, val) { if (!val && val !== 0) { return; } var arg = name.length > 1 ? '--' + _.kebabCase(name) : '-' + name; // --max-old-space-size argument requires an `=` if (arg === '--max-old-space-size') { args.push(arg + '=' + val); return; } else { args.push(arg); } if (_.isString(val) || _.isNumber(val)) { args.push(val); } }