selenium.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /**
  2. * Module dependencies
  3. */
  4. var path = require('path');
  5. var fs = require('fs');
  6. var child_process = require('child_process');
  7. var util = require('util');
  8. var Logger = require('../util/logger.js');
  9. var SENTINEL = [
  10. 'Started org.openqa.jetty.jetty.Server',
  11. 'INFO - Selenium Server is up and running',
  12. 'INFO [SeleniumServer.boot] - Selenium Server is up and running on port'
  13. ];
  14. var DEFAULT_PORT = 4444;
  15. var DEFAULT_HOST = '127.0.0.1';
  16. var DEFAULT_LOG_FILE = 'selenium-debug.log';
  17. function SeleniumServer(settings, callback) {
  18. this.settings = settings;
  19. this.onStarted = callback;
  20. this.port = this.settings.selenium.port || DEFAULT_PORT;
  21. this.host = this.settings.selenium.host;
  22. this.output = '';
  23. this.error_out = '';
  24. this.process = null;
  25. }
  26. SeleniumServer.prototype.setCliArgs = function() {
  27. this.cliOpts = [
  28. '-jar', this.settings.selenium.server_path,
  29. '-port', this.port
  30. ];
  31. if (this.host && this.host != DEFAULT_HOST) {
  32. this.cliOpts.push('-host', this.host);
  33. Logger.warn('\n\n[!] The host argument has been removed from Selenium 3 and will throw an exception.\n');
  34. }
  35. if (typeof this.settings.selenium.cli_args == 'object') {
  36. var cli_args = this.settings.selenium.cli_args;
  37. for (var keyName in cli_args) {
  38. if (cli_args[keyName]) {
  39. var property = '';
  40. if (keyName.indexOf('-D') !== 0) {
  41. property += '-D';
  42. }
  43. property += keyName + '=' + cli_args[keyName];
  44. this.cliOpts.unshift(property);
  45. }
  46. }
  47. }
  48. };
  49. SeleniumServer.prototype.start = function() {
  50. if (this.settings.output) {
  51. process.stdout.write(Logger.colors.light_purple('Starting selenium server' + (this.settings.parallelMode ? ' in parallel mode' : '') +'... '));
  52. }
  53. this.setCliArgs();
  54. this.process = child_process.spawn('java', this.cliOpts, {
  55. stdio: ['ignore', 'pipe', 'pipe']
  56. });
  57. this.process.host = this.host;
  58. this.process.port = this.port;
  59. this.exitHandlerFn = this.exitHandler.bind(this);
  60. this.process.on('error', this.onError.bind(this));
  61. this.process.on('exit', this.exitHandlerFn);
  62. this.process.on('close', this.closeHandler.bind(this));
  63. this.process.stdout.on('data', this.onStdoutData.bind(this));
  64. this.process.stderr.on('data', this.onStderrData.bind(this));
  65. };
  66. SeleniumServer.prototype.stop = function(callback) {
  67. if (!this.process || this.process.killed) {
  68. Logger.warn('Selenium process is not started.');
  69. callback(false);
  70. return;
  71. }
  72. try {
  73. this.process.kill();
  74. this.writeLogFile(callback);
  75. } catch (e) {
  76. Logger.warn('Selenium process could not be stopped.');
  77. console.log(e);
  78. callback();
  79. }
  80. };
  81. SeleniumServer.prototype.exitHandler = function (code) {
  82. this.onStarted('Could not start Selenium.', null, this.error_out, code);
  83. };
  84. SeleniumServer.prototype.closeHandler = function() {
  85. Logger.info('Selenium process finished.');
  86. };
  87. SeleniumServer.prototype.writeLogFile = function(callback) {
  88. if (this.settings.selenium.log_path === false) {
  89. callback();
  90. return;
  91. }
  92. if (typeof this.settings.selenium.log_path == 'undefined') {
  93. this.settings.selenium.log_path = '';
  94. }
  95. var filePath = path.resolve(path.join(this.settings.selenium.log_path, DEFAULT_LOG_FILE));
  96. fs.writeFile(filePath, this.output, function(err) {
  97. if (err) {
  98. console.log(Logger.colors.light_red('\nError writing log file to:'), err.path);
  99. }
  100. callback();
  101. });
  102. };
  103. SeleniumServer.prototype.onError = function(err) {
  104. if (err.code == 'ENOENT') {
  105. console.log(Logger.colors.red('\nAn error occurred while trying to start Selenium. ' +
  106. 'Check if JAVA is installed on your machine.'));
  107. console.log(util.inspect(err, false, 1, true));
  108. }
  109. };
  110. SeleniumServer.prototype.onStderrData = function(data) {
  111. this.error_out += data.toString();
  112. this.checkProcessStarted(data);
  113. };
  114. SeleniumServer.prototype.onStdoutData = function(data) {
  115. this.checkProcessStarted(data);
  116. };
  117. SeleniumServer.prototype.checkProcessStarted = function(data) {
  118. var output = data.toString();
  119. this.output += output;
  120. var isStarted = SENTINEL.some(function(item) {
  121. return output.indexOf(item) != -1;
  122. });
  123. if (isStarted) {
  124. var exitHandler = this.exitHandlerFn;
  125. this.process.removeListener('exit', exitHandler);
  126. process.stdout.write(Logger.colors.light_purple('started - PID: ' ) + ' ' +
  127. this.process.pid + '\n' + (this.settings.parallelMode ? '\n' : ''));
  128. this.onStarted(null, this.process);
  129. }
  130. };
  131. module.exports = new (function() {
  132. var server;
  133. this.startServer = function (settings, callback) {
  134. if (!settings.selenium || !settings.selenium.start_process || !settings.selenium.server_path) {
  135. callback();
  136. return;
  137. }
  138. server = new SeleniumServer(settings, callback);
  139. server.start();
  140. };
  141. this.stopServer = function (callback) {
  142. callback = callback || function() {};
  143. if (!server) {
  144. console.log('Selenium server is not running.');
  145. callback();
  146. return;
  147. }
  148. server.stop(callback);
  149. };
  150. })();