UNPKG

kasmir

Version:

Amazing multi-browser automation tool

1,469 lines (1,217 loc) 43.2 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "/"; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 14); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unserialize = exports.serialize = undefined; var _serializeJavascript = __webpack_require__(2); var serializer = _interopRequireWildcard(_serializeJavascript); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } var serialize = exports.serialize = function serialize(obj) { return serializer.default(obj); }; var unserialize = exports.unserialize = function unserialize(obj) { return eval('(' + obj + ')'); }; /***/ }), /* 1 */ /***/ (function(module, exports) { module.exports = require("path"); /***/ }), /* 2 */ /***/ (function(module, exports) { module.exports = require("serialize-javascript"); /***/ }), /* 3 */, /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // Kasmir default configuration file module.exports = { // How many browsers to launch browsers: 1, // Verbosity level // 0 - ensure no output // 1 - only fatal errors // 2 - output action process and child errors // 3 - output task progress // 4 - output selenium logs // 5 - output everything verbosity: 1, // Collect reports report: true, // Load action files here actionsPath: null, // Download selenium & chromedriver downloadDrivers: true, // Output path downloadPath: '_bin', // Action definitions actions: {}, // Runner settings runner: { // Colored output colors: true, // Runner verbose output silent: true, // Live output log live_output: false, // Task result settings result_settings: { // Embed images in result images: false }, // Selenium server settings selenium_settings: { // Start process on run start_process: true, // Selenium executable path server_path: "./_bin/selenium.jar", // Bind port port: 4444, // Additional client arguments cli_args: { "webdriver.chrome.driver": "./_bin/chromedriver" } }, // Test settings per run environment test_settings: { // Default run environment settings "default": { // Selenium server port selenium_port: 4444, // Selenium server host selenium_host: "localhost", // Global configuration globals: { waitForConditionTimeout: 15000, abortOnAssertionFailure: false }, // Enable screenshots screenshots: { path: './', enabled: false, on_failure: false, on_error: false }, // Browser capabilities desiredCapabilities: { browserName: "chrome", javascriptEnabled: true, acceptSslCerts: true } } }, // Runner timeouts timeouts: { // Wait for page to load in ms before fail pageLoad: 10000, // Pause after operation in ms (recommended >= 250) pauseAfter: 250 } } }; /***/ }), /* 5 */, /* 6 */ /***/ (function(module, exports) { module.exports = require("child_process"); /***/ }), /* 7 */ /***/ (function(module, exports) { module.exports = require("fs"); /***/ }), /* 8 */, /* 9 */ /***/ (function(module, exports) { module.exports = require("nightwatch/lib/runner/selenium"); /***/ }), /* 10 */ /***/ (function(module, exports) { module.exports = require("require-dir"); /***/ }), /* 11 */ /***/ (function(module, exports) { module.exports = require("selenium-download"); /***/ }), /* 12 */, /* 13 */, /* 14 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _selenium = __webpack_require__(9); var Selenium = _interopRequireWildcard(_selenium); var _seleniumDownload = __webpack_require__(11); var SeleniumDownload = _interopRequireWildcard(_seleniumDownload); var _path = __webpack_require__(1); var path = _interopRequireWildcard(_path); var _fs = __webpack_require__(7); var fs = _interopRequireWildcard(_fs); var _child_process = __webpack_require__(6); var _serialize = __webpack_require__(0); var _requireDir = __webpack_require__(10); var _requireDir2 = _interopRequireDefault(_requireDir); var _defaults = __webpack_require__(4); var _defaults2 = _interopRequireDefault(_defaults); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Kasmir = function () { function Kasmir() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, Kasmir); this.childCount = 1; this.readyCount = 0; this.actionsToRun = []; this.state = []; this.reports = []; this.returns = []; this.runners = []; this.stdout = []; this.func = null; this.config = config; this.continuous = false; this.configure(); this.init(); } _createClass(Kasmir, [{ key: 'init', value: function init() { var _this = this; // Test environments for each child this.envs = ['default']; // Ensure selenium & chromedriver is installed this.ensureDrivers().then(function () { // Find child environments if (typeof _this.config.browsers === 'number') { _this.childCount = _this.config.browsers; _this.envs = Array(_this.childCount).fill('default'); } else if (Array.isArray(_this.config.browsers)) { _this.childCount = _this.config.browsers.length; _this.envs = _this.config.browsers; } // Initialize reports _this.reports = Array(_this.childCount).fill({ actions: [], actionSummary: [], tasks: [], taskSummary: [], errors: [] }); // Spawn child nodes to run the instances for (var inst = 0; inst < _this.childCount; inst++) { var child = (0, _child_process.spawn)('node', [_this.resolvePath('childrunner.js'), '--id=' + inst, '--settings=' + (0, _serialize.serialize)(_this.config.runner.test_settings[_this.envs[inst]])], { stdio: ['ignore', 'pipe', 'pipe', 'ipc'] }); // Catch stdout, we trust that child checks config.verbosity child.stdout.on('data', function (data) { _this.message(data.toString(), 1, true); }); // Catch ipc messages child.on('message', function (data) { _this.handleRunners(data); }); // Send serialized config to child node child.send({ message: 'configure', value: (0, _serialize.serialize)(_this.config) }); _this.runners.push(child); } }); // Ensure children are killed when parent exits // istanbul ignore next process.on('exit', function () { _this.killRunners(); }); } // Returns promise that resolves when init is ready }, { key: 'initReady', value: function initReady() { var _this2 = this; return new Promise(function (resolve, reject) { var readyWait = setInterval(function () { if (_this2.readyCount === _this2.childCount) { clearInterval(readyWait); resolve(); } }, 100); }); } // Ensure selenium is available }, { key: 'ensureDrivers', value: function ensureDrivers() { var _this3 = this; return new Promise(function (resolve, reject) { // istanbul ignore if if (!_this3.config.downloadDrivers) { resolve(); } // Use selenium-download to always download the latest version of drivers SeleniumDownload.ensure(_this3.config.downloadPath, function (error) { // istanbul ignore if if (error) { _this3.message(error, 1); } else { _this3.message('[OK] Selenium & Chromedriver updated to: ' + _this3.config.downloadPath, 5); } resolve(); }); }); } // Creates a new value definition that can be used as dynamic task argument }, { key: 'createValue', value: function createValue(name, value) { var byChildIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; this.runners.map(function (runner, instance) { // Value is array and we want to update each child with value by index if (Array.isArray(value) && byChildIndex === true) { runner.send({ message: 'createvalue', value: (0, _serialize.serialize)({ name: name, value: value[instance] || '' }) }); } else { runner.send({ message: 'createvalue', value: (0, _serialize.serialize)({ name: name, value: value }) }); } }); } // Import actions from a directory }, { key: 'getActions', value: function getActions(pathToActions) { var actionExports = (0, _requireDir2.default)(path.resolve(pathToActions)); // Map required action exports to global exports for (var action in actionExports) { if ({}.hasOwnProperty.call(actionExports, action)) { for (var actionName in actionExports[action]) { if ({}.hasOwnProperty.call(actionExports[action], actionName)) { this.config.actions[actionName] = actionExports[action][actionName]; } } } } } // Get report }, { key: 'getReport', value: function getReport(type) { if (typeof type === 'undefined') { return this.childCount > 1 ? this.reports : this.reports[0]; } var states = []; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = this.reports[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var report = _step.value; states.push(report[type]); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return this.runners.length > 1 ? states : states[0]; } // Get current complete state }, { key: 'getState', value: function getState(type) { var result = []; var index = 0; try { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = this.reports[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var runnerReport = _step2.value; var state = {}; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = runnerReport.tasks[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var taskState = _step3.value; if (typeof state[taskState.action] === 'undefined') { state[taskState.action] = []; } else if (_typeof(state[taskState.action][index]) === 'object' && typeof state[taskState.action][index][taskState.name] !== 'undefined') { index++; } if (_typeof(state[taskState.action][index]) !== 'object') { state[taskState.action][index] = {}; } state[taskState.action][index][taskState.name] = taskState; } // Collapse arrays if single indice } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } for (var actionName in state) { if ({}.hasOwnProperty.call(state, actionName) && state[actionName].length === 1) { state[actionName] = state[actionName][0]; } } result.push(state); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return result.length > 1 ? result : result[0]; } catch (e) { // istanbul ignore next this.message(e.message, 1); // istanbul ignore next return null; } } // Get state by action or task }, { key: 'getReportsByName', value: function getReportsByName(name) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'actions'; var result = []; for (var i = 0; i < this.childCount; i++) { var result2 = []; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = this.reports[i][type][Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var report = _step4.value; if (report.name === name) { result2.push(report); } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } result.push(result2); } return this.childCount > 1 ? result : result[0] || []; } // Get state by task }, { key: 'getActionReports', value: function getActionReports(action) { var reports = this.getReportsByName(action, 'actions'); return reports.length > 1 ? reports : reports[0]; } // Get task summary }, { key: 'getActionReport', value: function getActionReport() { return this.getReport('actions'); } // Get task summary }, { key: 'getActionSummary', value: function getActionSummary() { return this.getReport('actionSummary'); } // Get state by task }, { key: 'getTaskReports', value: function getTaskReports(task) { var reports = this.getReportsByName(task, 'tasks'); return reports.length > 1 ? reports : reports[0]; } // Get task summary }, { key: 'getTaskReport', value: function getTaskReport() { return this.getReport('tasks'); } // Get task summary }, { key: 'getTaskSummary', value: function getTaskSummary() { return this.getReport('taskSummary'); } // Get extended summary }, { key: 'getErrors', value: function getErrors() { return this.getReport('errors'); } // Pretty print JSON }, { key: 'prettyPrint', value: function prettyPrint(json) { // istanbul ignore next console.dir(json, { depth: null, colors: true }); } // Pretty print report by type }, { key: 'report', value: function report(type) { // istanbul ignore next return type ? this.prettyPrint(this.getReport(type)) : this.prettyPrint(this.getReport()); } // Clear reports }, { key: 'clearReports', value: function clearReports() { var _this4 = this; return new Promise(function (resolve, reject) { _this4.state = []; _this4.reports = []; _this4.clearCount = 0; var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = _this4.runners[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var runner = _step5.value; runner.send({ message: 'clear', value: true }); } // Poll clear count } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } var clearWait = setInterval(function () { if (_this4.clearCount === _this4.runners.length) { clearInterval(clearWait); resolve(); } }, 50); }); } // Clone object }, { key: 'clone', value: function clone(obj) { return JSON.parse(JSON.stringify(obj)); } // Extend configuration objects }, { key: 'extend', value: function extend() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var userConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // Clone object var result = this.clone(config); // Loop through default config props for (var prop in config) { // If known prop found in user config if (typeof userConfig[prop] !== "undefined") { // For object props, extended recursively if (_typeof(result[prop]) === "object" && _typeof(userConfig[prop]) === "object" && Array.isArray(result[prop]) === false && Array.isArray(userConfig[prop]) === false) { result[prop] = this.extend(config[prop], userConfig[prop]); } // Take value from user config else { result[prop] = userConfig[prop]; } } } return result; } // Parse configuration }, { key: 'configure', value: function configure() { // Extend default config var config = this.extend(_defaults2.default, this.config); config.actions = this.config.actions || {}; this.config = config; // Import actions from actions path if (config.actionsPath) { this.getActions(config.actionsPath); } // Resolve download path if (this.config.downloadPath) { this.config.downloadPath = path.resolve(this.config.downloadPath); this.ensurePath(this.config.downloadPath); } // Resolve server path this.config.runner.selenium_settings.server_path = path.resolve(config.runner.selenium_settings.server_path); // Resolve selenium cli_args if (this.config.runner.selenium_settings.cli_args) { for (var arg in this.config.runner.selenium_settings.cli_args) { // Resolve webdriver bin path if (arg.match(/\webdriver\..*\.driver$/)) { this.config.runner.selenium_settings.cli_args[arg] = path.resolve(this.config.runner.selenium_settings.cli_args[arg]); } } } this.test_settings = config.runner.test_settings; for (var env in this.test_settings) { if (config.runner.silent) { this.test_settings[env].silent = config.runner.silent; } if (this.test_settings[env].screenshots.path) { this.test_settings[env].screenshots.path = path.resolve(this.test_settings[env].screenshots.path); this.ensurePath(this.test_settings[env].screenshots.path); } // If path was not specified, we disable the screenshots option // otherwise nightwatch will throw an error else { this.test_settings[env].screenshots.enabled = false; this.message('screenshots output path not specified for \'' + env + '\'. screenshots are disabled', 2); } // on_failure and on_error are not supported yet this.test_settings[env].screenshots.on_failure = false; this.test_settings[env].screenshots.on_error = false; } // Full selenium config in standard format this.seleniumConfig = { live_output: config.runner.live_output, output_folder: null, selenium: config.runner.selenium_settings, test_settings: this.test_settings }; } // Launch the runner }, { key: 'run', value: function run() { var _this5 = this; var actionsToRun = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var continuous = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; this.actionsToRun = actionsToRun; this.continuous = continuous; return this.initReady() // Start sequence before running actions .then(function () { return _this5.start(); }) // Launch instances .then(function () { return _this5.runRunners(actionsToRun); }) // Done running actions .then(function () { return _this5.end(); }); } // Before running actions }, { key: 'start', value: function start() { var _this6 = this; // Run silent mode; hook stdout to prevent selenium output // istanbul ignore next this.hookStdout(function (message) { _this6.collectStdout(message); }); return new Promise(function (resolve, reject) { if (_this6.seleniumRunning === true) { resolve(); } else { _this6.runSelenium(resolve, reject); } }); } // When done running actions }, { key: 'end', value: function end() { // If we are running continuous mode, simply unhook stdout if (this.continuous === true) { return this.unhookStdout(); } // If not we want to kill runners and stop selenium server this.killRunners(); return this.stopSelenium(); } // Launch selenium server instance }, { key: 'runSelenium', value: function runSelenium(success, fail) { var _this7 = this; Selenium.startServer(this.seleniumConfig, function (message, n, error) { _this7.seleniumRunning = true; // istanbul ignore if if (error) { _this7.message(error, 1); fail({ message: message, error: error }); } success(); }); } // Stop selenium instance }, { key: 'stopSelenium', value: function stopSelenium() { var _this8 = this; return new Promise(function (resolve, reject) { // We might be running external selenium server so resolve immediately // istanbul ignore if if (_this8.seleniumRunning === false) { resolve(); } Selenium.stopServer(function () { var readyWait = setInterval(function () { if (!_this8.seleniumRunning || typeof _this8.unhookStdoutFunc !== 'function') { clearInterval(readyWait); resolve(); } }, 50); }); }); } // Run runners }, { key: 'runRunners', value: function runRunners() { var actionsToRun = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; this.runners.map(function (runner, instance) { runner.done = false; runner.send({ message: 'run', value: (0, _serialize.serialize)(actionsToRun) }); }); return this.waitRunnersDone(); } // Handle child process message }, { key: 'handleRunners', value: function handleRunners() { var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // Unserialize data from runner child process data = { id: data.id, message: data.message, value: (0, _serialize.unserialize)(data.value) }; switch (data.message) { // When runners are done running actions, they post 'complete'. The value // contains the report or error if the promise ends in 'catch' case 'complete': this.runners[data.id].done = true; this.reports[data.id] = data.value; this.state = this.getState(); break; // Runner generic errors are logged // istanbul ignore next case 'error': this.message(data.value.toString(), 1); break; // Runners post 'ready' when child process initialization is done case 'ready': this.readyCount += 1; break; // Runners post 'clear_done' when reports are cleared case 'clear_done': this.clearCount += 1; break; // Runners post status with current report state every time // a task completes case 'status': this.reports[data.id] = data.value; this.state = this.getState(); break; // If the next action is function, the runners will emit // this event and halt. // We wait for all runners to halt and then run the function and // continue runner execution. case 'function': this.runners[data.id].halted = true; this.func = this.actionsToRun[data.value]; this.waitRunnersHalt(); break; } } // Continue runners after halt }, { key: 'continueRunners', value: function continueRunners() { this.func = null; var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = this.runners[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var runner = _step6.value; runner.halted = false; runner.send({ message: 'continue', value: (0, _serialize.serialize)(this.returns) }); } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } } // Kill runners }, { key: 'killRunners', value: function killRunners() { try { this.runners.map(function (runner, instance) { runner.kill(); }); } catch (e) { // istanbul ignore next this.message('No runner instances to kill', 2); } } // Execute action function }, { key: 'executeActionFunc', value: function executeActionFunc() { var _this9 = this; return new Promise(function (resolve, reject) { if (typeof _this9.func === 'function') { // Feed current status to the function, call and get result var result = _this9.func(_this9.reports); // The function returned a promise if (result && (typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && typeof result.then === 'function') { result.then(function (returnValue) { // Save return value _this9.returns.push(returnValue); resolve(); }); } // If action function returns {_yield: <array>} those values are interpreted // as new actions else if (result && (typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && _typeof(result._yield) === 'object') { if (_this9.yieldActions(result._yield) === false) { _this9.message('functions that yield actions must return {_yield: <Array>}', 2); } resolve(); } // Save return value resolve else if (result) { _this9.returns.push(result); resolve(); } // Resolve without result else { resolve(); } } }); } // Yield new actions to runners }, { key: 'yieldActions', value: function yieldActions(newActions) { if (Array.isArray(newActions)) { this.runners.map(function (runner, instance) { runner.send({ message: 'yield', value: (0, _serialize.serialize)(newActions) }); }); return true; } return false; } // Wait till runners are done }, { key: 'waitRunnersDone', value: function waitRunnersDone() { var _this10 = this; return new Promise(function (resolve, reject) { var readyWait = setInterval(function () { var readyStatus = true; var _iteratorNormalCompletion7 = true; var _didIteratorError7 = false; var _iteratorError7 = undefined; try { for (var _iterator7 = _this10.runners[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { var runner = _step7.value; readyStatus = readyStatus && runner.done; } } catch (err) { _didIteratorError7 = true; _iteratorError7 = err; } finally { try { if (!_iteratorNormalCompletion7 && _iterator7.return) { _iterator7.return(); } } finally { if (_didIteratorError7) { throw _iteratorError7; } } } if (readyStatus === true) { clearInterval(readyWait); resolve(); } }, 50); }); } // Wait till all runners are halted and execute next function }, { key: 'waitRunnersHalt', value: function waitRunnersHalt() { var _this11 = this; if (!this.haltWait) { this.haltWait = setInterval(function () { var haltStatus = true; var _iteratorNormalCompletion8 = true; var _didIteratorError8 = false; var _iteratorError8 = undefined; try { for (var _iterator8 = _this11.runners[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { var runner = _step8.value; haltStatus = haltStatus && runner.halted; } // All runners halted } catch (err) { _didIteratorError8 = true; _iteratorError8 = err; } finally { try { if (!_iteratorNormalCompletion8 && _iterator8.return) { _iterator8.return(); } } finally { if (_didIteratorError8) { throw _iteratorError8; } } } if (haltStatus === true) { clearInterval(_this11.haltWait); _this11.executeActionFunc().then(function () { _this11.continueRunners(); }); } }, 50); } } // Hook process.stdout to prevent output when we don't want it. // ...such as when selenium initializes the missing settings.output // check causes it to output process pid and startup message }, { key: 'hookStdout', value: function hookStdout() { var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var file = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'stdout'; // We don't hook stdout if verbosity is greater or equal to 4 if (this.config.verbosity >= 4) { return false; } // istanbul ignore if if (typeof callback !== 'function') { callback = function callback() {}; } // This is not included in unit tests because it would suppress // the test output var oldWrite = process[file].write; // Capture callable process.<file>.write this.processWrite = function (s) { oldWrite.call(process[file], s); }; // Replace process.<file>.write // istanbul ignore next process[file].write = function (message) { callback(message); }; // Return unhook function return this.unhookStdoutFunc = function () { process[file].write = oldWrite.bind(process[file]); }; } // Unhook stdout }, { key: 'unhookStdout', value: function unhookStdout() { // istanbul ignore if if (typeof this.unhookStdoutFunc === 'function') { this.unhookStdoutFunc(); return true; } // istanbul ignore next return false; } // Collect stdout; selenium will log the failures in task order // with process.stdout.write so collect output if stdout is hoooked }, { key: 'collectStdout', value: function collectStdout(message) { this.stdout.push(message); if (message.match(/Selenium\ process\ finished\./gi)) { this.unhookStdout(); this.seleniumRunning = false; } } // Resolve path to module get an absolute filename }, { key: 'resolvePath', value: function resolvePath(filename) { var basePath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var levels = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 4; // Return if levels go below 1 if (levels < 1) return null; // Resolve base path basePath = this.getBasePath(basePath); // Get directories in base path var dirs = this.getDirectories(basePath); // Get resolve options by filename var options = this.getResolveOptions(filename); var abspath = void 0; var abspath2 = void 0; var _iteratorNormalCompletion9 = true; var _didIteratorError9 = false; var _iteratorError9 = undefined; try { for (var _iterator9 = dirs[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { var dir = _step9.value; var _iteratorNormalCompletion10 = true; var _didIteratorError10 = false; var _iteratorError10 = undefined; try { for (var _iterator10 = options[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { var opt = _step10.value; abspath = path.join(basePath, dir, opt); abspath2 = path.join(process.cwd(), opt); // istanbul ignore if if (fs.existsSync(abspath)) return abspath; // istanbul ignore if if (fs.existsSync(abspath2)) return abspath2; // istanbul ignore if if (fs.existsSync(opt)) return opt; } } catch (err) { _didIteratorError10 = true; _iteratorError10 = err; } finally { try { if (!_iteratorNormalCompletion10 && _iterator10.return) { _iterator10.return(); } } finally { if (_didIteratorError10) { throw _iteratorError10; } } } } } catch (err) { _didIteratorError9 = true; _iteratorError9 = err; } finally { try { if (!_iteratorNormalCompletion9 && _iterator9.return) { _iterator9.return(); } } finally { if (_didIteratorError9) { throw _iteratorError9; } } } return this.resolvePath(filename, path.join(basePath, '../'), levels - 1); } // Ensure path exists }, { key: 'ensurePath', value: function ensurePath(location) { // istanbul ignore if if (!fs.existsSync(location)) { fs.mkdirSync(location); } } // Get module base path }, { key: 'getBasePath', value: function getBasePath() { var basePath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; if (basePath === '') { try { return path.resolve(path.parse(process.mainModule.filename).dir); } catch (e) { // istanbul ignore next return './'; } } return basePath; } // Get base paths in directories }, { key: 'getDirectories', value: function getDirectories(basePath) { return fs.readdirSync(basePath).filter(function (file) { return fs.statSync(path.join(basePath, file)).isDirectory(); }); } // Get resolve options by filename }, { key: 'getResolveOptions', value: function getResolveOptions(filename) { return [filename, path.join('build', filename), path.join('kasmir', filename), path.join('node_modules', filename), path.join('node_modules', 'kasmir', filename)]; } // Log a message }, { key: 'message', value: function message(text) { var minVerbosity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var fromChild = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (this.isStackTraceMessage(text)) { minVerbosity = 4; } if (typeof this.config.verbosity === "number" && this.config.verbosity < minVerbosity) { return; } var outText = text; if (fromChild) { if (this.config.verbosity > 3) { outText = outText.replace(/\n$/, ''); } } else { outText = 'Kasmir: ' + outText; } if (typeof this.processWrite === "function") { this.processWrite(outText); } else { console.log(outText); } } // Detect nightwatch stack trace messages, // TODO: This need more thought }, { key: 'isStackTraceMessage', value: function isStackTraceMessage(message) { return Boolean(message.match(/\(eval at/g) || message.match(/ERROR\:/g) || message.match(/at process\./g)); } }]); return Kasmir; }(); exports.default = Kasmir; module.exports = exports['default']; /***/ }) /******/ ]);