TheBrainFamily/chimpy

View on GitHub
src/lib/mocha/mocha.js

Summary

Maintainability
F
3 days
Test Coverage
var path = require('path'),
  cp = require('child-process-debug'),
  processHelper = require('./../process-helper.js'),
  booleanHelper = require('../boolean-helper'),
  log = require('./../log'),
  _ = require('underscore'),
  colors = require('colors'),
  glob = require('glob'),
  fs = require('fs-extra');

/**
 * Mocha Constructor
 *
 * @param {Object} options
 * @api public
 */

function Mocha(options) {
  this.options = options;
  this.child = null;
}

/**
 * Run Mocha specs
 *
 * @param {Function} callback
 * @api public
 */

Mocha.prototype.start = function (callback) {

  var self = this;
  if (glob.sync(self.options.path).length === 0) {
    const infoMessage = `[chimp][mocha] Directory ${self.options.path} does not exist. Not running`;
    if (booleanHelper.isTruthy(self.options['fail-when-no-tests-run'])) {
      callback(infoMessage);
    }
    else {
      log.info(infoMessage);
      callback();
    }
    return;
  }

  log.debug('[chimp][mocha] Running...');

  var opts = {
    env: process.env,
    silent: true
  };

  var port;
  if (this.options.debugMocha) {
    port = parseInt(this.options.debugMocha);
    if (port > 1) {
      opts.execArgv = ['--debug=' + port];
    } else {
      opts.execArgv = ['--debug'];
    }
  }

  if (this.options.debugBrkMocha) {
    port = parseInt(this.options.debugBrkMocha);
    if (port > 1) {
      opts.execArgv = ['--debug-brk=' + port];
    } else {
      opts.execArgv = ['--debug-brk'];
    }
  }

  if (this.options.inspectMocha) {
    port = parseInt(this.options.inspectMocha);
    if (port > 1) {
      opts.execArgv = ['--inspect=' + port];
    } else {
      opts.execArgv = ['--inspect'];
    }
  }

  if (this.options.inspectBrkMocha) {
    port = parseInt(this.options.inspectBrkMocha);
    if (port > 1) {
      opts.execArgv = ['--inspect-brk=' + port];
    } else {
      opts.execArgv = ['--inspect-brk'];
    }
  }

  let _specs = [];
  if (this.options._ && this.options._.length > 2) {
    _specs = this.options._.slice(2);
  }

  opts.env = _.extend(process.env, {
    mochaConfig: JSON.stringify(this.options.mochaConfig)
  });
  self.child = cp.fork(path.join(__dirname, 'mocha-wrapper-instance.js'), _specs, opts);
  self.child.stdout.pipe(process.stdout);
  self.child.stderr.pipe(process.stderr);
  process.stdin.pipe(self.child.stdin);


  let noTestsFound = false;
  self.child.stdout.on('data', function(data) {
    const colorCodesRegExp = new RegExp(`\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]`, 'g');
    const dataFromStdout = data.toString().replace(colorCodesRegExp, '').trim();
    if (/^0 passing/.test(dataFromStdout)) {
      noTestsFound = true;
    }
  });

  var result = null;
  self.child.on('message', function (res) {
    log.debug('[chimp][mocha] Received message from Mocha child. Result:', res);
    result = res;
  });

  self.child.on('close', (code) => {
    log.debug('[chimp][mocha] Closed with code', code);
    const failWhenNoTestsRun = booleanHelper.isTruthy(self.options['fail-when-no-tests-run']);
    if (!self.child.stopping) {
      log.debug('[chimp][mocha] Mocha not in a stopping state');
      callback(code !== 0 || (code === 0 && noTestsFound && failWhenNoTestsRun) ? 'Mocha failed' : null, result);
    }
  });

};

Mocha.prototype.interrupt = function (callback) {

  log.debug('[chimp][mocha] interrupting mocha');

  var self = this;

  if (!self.child) {
    log.debug('[chimp][mocha] no child to interrupt');
    return callback();
  }
  self.child.stopping = true;

  var options = {
    child: self.child,
    prefix: 'mocha'
  };

  processHelper.kill(options, function (err, res) {
    self.child = null;
    if (callback) {
      callback(err, res);
    }
  });

};

module.exports = Mocha;