diff --git a/bin/parallel-mocha b/bin/parallel-mocha index 1e4589a..ace88cb 100755 --- a/bin/parallel-mocha +++ b/bin/parallel-mocha @@ -1,49 +1,63 @@ #!/usr/bin/env node +'use strict'; const program = require('commander'); const fs = require('fs'); const glob = require('glob'); const Runner = require('../lib/runner'); const async = require('async'); +const chalk = require('chalk'); program - .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version) - .usage('[options] ') - .option('-p, --processes ', 'Set number of processes', parseInt) - .option('-t, --timeout ', 'Timeout between testes', parseInt) - .option('-s, --slow ', 'Wait for slow tests', parseInt) - .parse(process.argv); - -// TODO: how can i make sure workers is integer? + .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version) + .usage('[options] ') + .option('-p, --processes ', 'Set number of processes', parseInt) + .option('-t, --timeout ', 'Timeout between testes', parseInt) + .option('-s, --slow ', 'Wait for slow tests', parseInt) + .parse(process.argv); + let processes = program.processes || 20; let timeout = program.timeout || 10000; let slow = program.slow || 2000; let files = program.args; +let environment = program.environment || 'test'; let resolveFilesQueue = files.map( - file=>(cb)=> { - glob(file, cb) - } + file=>(cb)=> { + glob(file, cb) + } ); async.parallel(resolveFilesQueue, (err, files)=> { - if (err) { - throw err; - } + if (err) { + throw err; + } + + files = files.reduce((files, file)=> { + return files.concat(file); + }, []); - var runner = new Runner(files, { - processes: files.length, - timeout: timeout, - slow: slow - }); - - runner.run((error) => { - if (error) { - console.log('==== Failed: %s', error.message); - } else { - console.log('==== Pass!'); - } - }); + var runner = new Runner(files, { + processes: files.length, + timeout: timeout, + slow: slow, + env: environment + }); + + process.stderr.on('data', (data)=> { + console.log(chalk.red(data)); + }) + + runner.run((error) => { + if (error) { + console.log(chalk.red(`Failed: ${error.message}`)); + // Force epic fail + process.exit(1); + } else { + console.log(chalk.green('All test passed!!')); + process.exit(0); + } + }); }); diff --git a/lib/pool.js b/lib/pool.js index 376126b..eb4a82c 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -1,45 +1,44 @@ -var EventEmitter = require('events').EventEmitter - , util = require('util') - , DoneCriteria = require('done-criteria') - , underscore = require('underscore'); +'use strict'; -function Pool(paths, workers) { - EventEmitter.call(this); +const EventEmitter = require('events').EventEmitter; +const DoneCriteria = require('done-criteria'); +const underscore = require('underscore'); - this.paths = paths; - this.workers = workers; -} - -util.inherits(Pool, EventEmitter); +class Pool extends EventEmitter { -Pool.prototype.start = function() { - var self = this - , doneCriteria = new DoneCriteria(this.paths, function() { - self.emit('done'); - }); + constructor(paths, workers) { + super(Pool); + this.paths = paths; + this.workers = workers; + } - self.on('next', function() { - self.next(function(path) { - doneCriteria.done(path); + start() { + let doneCriteria = new DoneCriteria(this.paths, () => { + this.emit('done'); }); - }); - - underscore.range(this.workers).forEach(function() { - self.next(function(path) { - doneCriteria.done(path); - self.emit('next'); + this.on('next', ()=> { + this.next((path)=> { + doneCriteria.done(path); + }); }); - }); -}; - -Pool.prototype.next = function(callback) { - var path = this.paths.shift(); - if (path) { - this.emit('ready', path, function() { - return callback(path); + + underscore.range(this.workers).forEach(()=> { + this.next((path)=> { + doneCriteria.done(path); + this.emit('next'); + }); }); + }; + + next(callback) { + let path = this.paths.shift(); + if (path) { + this.emit('ready', path, ()=> { + return callback(path); + }); + } } -}; +} module.exports = Pool; diff --git a/lib/runner.js b/lib/runner.js index b06db52..8b567a8 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -1,82 +1,73 @@ -var spawn = require('child_process').spawn -var fs = require('fs') -var underscore = require('underscore'); +'use strict'; -var Pool = require('./pool'); +const spawn = require('child_process').spawn; +const fs = require('fs'); +const underscore = require('underscore'); -function Runner(paths, config) { +const Pool = require('./pool'); + +class Runner { + + constructor(paths, config) { this.paths = paths; this.config = underscore.extend( - { - bin: ['./node_modules/.bin/mocha'] - , processes: 2 - } - , config + { + bin: ['./node_modules/.bin/mocha'] + , processes: 2 + } + , config ); this.mocha = null; this.exitCodes = []; -} + } -Runner.prototype.run = function (callback) { - var self = this - , pool = new Pool(self.paths, self.config.processes); + run(callback) { + let pool = new Pool(this.paths, this.config.processes); + let exitCodes = []; - pool.on('done', function () { - var success = underscore.every(self.exitCodes, function (code) { - return code === 0; - }); - // TODO: return better result rather than just error or not - var error = success ? null : new Error('Not all tests passed'); - return callback(error); - }); + pool.on('ready', (path, callback) => { + var args = { + path: path, + timeout: this.config.timeout, + slow: this.config.slow, + env: this.config.env + }; - pool.on('ready', function (path, callback) { - var args = { - path: path, - timeout: self.config.timeout, - slow: self.config.slow - }; + this.spawn(args, (code)=> { + exitCodes.push(code); + callback(); + }); + }); - self.spawn(args, callback); + pool.on('done', () => { + var success = underscore.every(this.exitCodes, code=>code === 0); + var error = success ? null : new Error('Not all tests passed'); + return callback(error); }); + pool.start(); -}; + } -Runner.prototype.spawn = function (args, callback) { - var self = this - , mocha = self.findMocha() - , child = spawn(mocha, [ + spawn(args, callback) { + let mocha = this.findMocha(); + let child = spawn(mocha, [ '--timeout', args.timeout, '--slow', args.timeout, args.path - ], {stdio: "inherit", env: underscore.extend(process.env, {NODE_ENV: 'test'})}); - - /*child.stdout.once('data', function (data) { - process.stdout.write('.'); - self.exitCodes.push(0); - return callback(null); - }); - - child.stderr.on('data', function (data) { - process.stdout.write('%s', data); - process.exit(); - });*/ - - child.on('exit', function (code) { - - }); + ], + {stdio: "inherit", env: underscore.extend(process.env, {NODE_ENV: args.env})} + ); -}; + child.on('exit', callback); + } -Runner.prototype.findMocha = function () { + findMocha() { if (!this.mocha) { - this.mocha = underscore.find(this.config.bin, function (bin) { - return fs.existsSync(bin); - }); - this.mocha = this.mocha || 'mocha'; + this.mocha = underscore.find(this.config.bin, bin =>fs.existsSync(bin)); + this.mocha = this.mocha || 'mocha'; } - return this.mocha; -}; + } +} module.exports = Runner;