child-process.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. var child_process = require('child_process');
  2. var util = require('util');
  3. var events = require('events');
  4. var Logger = require('../../util/logger.js');
  5. function ChildProcess(environment, index, env_output, settings, args) {
  6. events.EventEmitter.call(this);
  7. this.env_output = env_output || [];
  8. this.mainModule = process.mainModule.filename;
  9. this.index = index;
  10. this.itemKey = this.getChildProcessEnvKey(environment);
  11. this.startDelay = settings.parallel_process_delay || ChildProcess.defaultStartDelay;
  12. this.environment = environment;
  13. this.settings = settings;
  14. this.child = null;
  15. this.globalExitCode = 0;
  16. this.processRunning = false;
  17. this.env_label = '';
  18. this.args = args || [];
  19. }
  20. util.inherits(ChildProcess, events.EventEmitter);
  21. ChildProcess.prevIndex = 0;
  22. ChildProcess.defaultStartDelay = 10;
  23. ChildProcess.prototype.setLabel = function(label) {
  24. this.env_itemKey = label;
  25. this.env_label = this.settings.disable_colors ?
  26. (' ' + label + ' ') : Logger.colors.yellow(' ' + label + ' ', Logger.colors.background.black);
  27. return this;
  28. };
  29. ChildProcess.prototype.run = function(colors, done) {
  30. this.availColors = colors;
  31. var cliArgs = this.getArgs();
  32. var env = {};
  33. Object.keys(process.env).forEach(function(key) {
  34. env[key] = process.env[key];
  35. });
  36. var self = this;
  37. setTimeout(function() {
  38. env.__NIGHTWATCH_PARALLEL_MODE = 1;
  39. env.__NIGHTWATCH_ENV = self.environment;
  40. env.__NIGHTWATCH_ENV_KEY = self.itemKey;
  41. env.__NIGHTWATCH_ENV_LABEL = self.env_itemKey;
  42. self.child = child_process.spawn(process.execPath, cliArgs, {
  43. cwd: process.cwd(),
  44. encoding: 'utf8',
  45. env: env,
  46. stdio: [null, null, null, 'ipc']
  47. });
  48. self.child.on('message', function(data) {
  49. self.emit('result', JSON.parse(data));
  50. });
  51. self.processRunning = true;
  52. if (self.settings.output) {
  53. console.log('Started child process for:' + self.env_label);
  54. }
  55. self.child.stdout.on('data', function (data) {
  56. self.writeToStdout(data);
  57. });
  58. self.child.stderr.on('data', function (data) {
  59. self.writeToStdout(data);
  60. });
  61. self.child.on('exit', function (code) {
  62. if (self.settings.output) {
  63. console.log('\n >>' + self.env_label + 'finished. ', '\n');
  64. }
  65. if (code) {
  66. self.globalExitCode = 2;
  67. }
  68. self.processRunning = false;
  69. done(self.env_output, code);
  70. });
  71. }, this.index * this.startDelay);
  72. };
  73. ChildProcess.prototype.getChildProcessEnvKey = function(env) {
  74. return env + '_' + (this.index+1);
  75. };
  76. /**
  77. * Returns an array of cli arguments to be passed to the child process,
  78. * based on the args passed to the main process
  79. * @returns {Array}
  80. */
  81. ChildProcess.prototype.getArgs = function() {
  82. var args = [this.mainModule];
  83. args.push.apply(args, this.args);
  84. args.push('--parallel-mode');
  85. return args;
  86. };
  87. ChildProcess.prototype.writeToStdout = function(data) {
  88. data = data.toString().trim();
  89. var color_pair = this.availColors[this.index%4];
  90. var output = '';
  91. if (ChildProcess.prevIndex !== this.index) {
  92. ChildProcess.prevIndex = this.index;
  93. if (this.settings.live_output) {
  94. output += '\n';
  95. }
  96. }
  97. if (this.settings.output) {
  98. if (this.settings.disable_colors) {
  99. output += ' ' + this.environment + ' ';
  100. } else {
  101. output += Logger.colors[color_pair[1]](' ' + this.environment + ' ',
  102. Logger.colors.background[color_pair[0]]);
  103. }
  104. output += ' ';
  105. }
  106. output += data;
  107. if (this.settings.live_output) {
  108. process.stdout.write(output + '\n');
  109. } else {
  110. this.env_output.push(output);
  111. }
  112. };
  113. module.exports = ChildProcess;