TheBrainFamily/chimpy

View on GitHub
src/lib/cucumberjs/cucumber-wrapper.js

Summary

Maintainability
A
2 hrs
Test Coverage
/*
 * This file does some minor modifications on how Cucumber is started.
 *
 * Modifications to the original code from cucumber:
 * - Adds the IPC listener
 * - Modify the argv that are passed to the Cucumber CLI
 * - Use exit instead of process.exit
 */

var Cucumber = require('cucumber');
var exit = require('exit');

// This is a modified version of cucumber/lib/cli
function Cli(argv) {
  var Cucumber = require('cucumber');
  var Command = require('commander').Command;
  var path = require('path');

  function collect(val, memo) {
    memo.push(val);
    return memo;
  }

  function getProgram() {
    var program = new Command(path.basename(argv[1]));

    program
      .usage('[options] [<DIR|FILE[:LINE]>...]')
      .version(Cucumber.VERSION, '-v, --version')
      .option('-b, --backtrace', 'show full backtrace for errors')
      .option('--compiler <EXTENSION:MODULE>', 'require files with the given EXTENSION after requiring MODULE (repeatable)', collect, [])
      .option('-d, --dry-run', 'invoke formatters without executing steps')
      .option('--fail-fast', 'abort the run on first failure')
      .option('-f, --format <TYPE[:PATH]>', 'specify the output format, optionally supply PATH to redirect formatter output (repeatable)', collect, ['pretty'])
      .option('--name <REGEXP>', 'only execute the scenarios with name matching the expression (repeatable)', collect, [])
      .option('--no-colors', 'disable colors in formatter output')
      .option('--no-snippets', 'hide step definition snippets for pending steps')
      .option('--no-source', 'hide source uris')
      .option('-p, --profile <NAME>', 'specify the profile to use (repeatable)', collect, [])
      .option('-r, --require <FILE|DIR>', 'require files before executing features (repeatable)', collect, [])
      .option('--snippet-syntax <FILE>', 'specify a custom snippet syntax')
      .option('-S, --strict', 'fail if there are any undefined or pending steps')
      .option('-t, --tags <EXPRESSION>', 'only execute the features or scenarios with tags matching the expression (repeatable)', collect, []);

    program.on('--help', function () {
      console.log('  For more details please visit https://github.com/cucumber/cucumber-js#cli\n');
    });

    return program;
  }

  function getConfiguration() {
    var program = getProgram();
    program.parse(argv);
    var profileArgs = Cucumber.Cli.ProfilesLoader.getArgs(program.profile);
    if (profileArgs.length > 0) {
      var fullArgs = argv.slice(0, 2).concat(profileArgs).concat(argv.slice(2));
      program = getProgram();
      program.parse(fullArgs);
    }
    var configuration = Cucumber.Cli.Configuration(program.opts(), program.args);
    return configuration;
  }

  var self = {
    run: function run(callback) {
      var configuration = getConfiguration();
      var runtime = Cucumber.Runtime(configuration);
      var formatters = [createIpcFormatter()].concat(configuration.getFormatters());
      formatters.forEach(function (formatter) {
        runtime.attachListener(formatter);
      });
      try {
        runtime.start(callback);
      } catch (e) {
        console.log(e.stack || e)
        callback(false)
      }
    }
  };
  return self;
}

function createIpcFormatter() {
  // add a json formatter that sends results over IPC
  const ipcFormatter = new Cucumber.Listener.JsonFormatter();
  const finish = ipcFormatter.finish;
  ipcFormatter.finish = function sendResultToChimp(callback) {
    finish.call(this, (error, result) => {
      const results = this.getLogs();
      process.send(results, () => {
        callback(error, result);
      });
    });
  };
  return ipcFormatter;
}


// This is a modified version of cucumber/bin/cucumber
var argv = process.argv.slice(1);
argv = argv.slice(argv.indexOf('node'));
var cli = Cli(argv);
cli.run(function (succeeded) {
  var code = succeeded ? 0 : 2;

  function exitNow() {
    exit(code);
  }

  if (process.stdout.write('')) {
    exitNow();
  } else {
    // write() returned false, kernel buffer is not empty yet...
    process.stdout.on('drain', exitNow);
  }
});