UNPKG

@testim/testim-cli

Version:

Command line interface for running Testing on you CI

291 lines (240 loc) 31.2 kB
'use strict'; var _createClass = require('babel-runtime/helpers/create-class')['default']; var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; var _Object$keys = require('babel-runtime/core-js/object/keys')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _helpersConstants = require('../helpers/constants'); var _helpersSanitize = require('../helpers/sanitize'); var _helpersSanitize2 = _interopRequireDefault(_helpersSanitize); var BANNER = '\n' + _helpersConstants.COLORS.yellow + '=======================================================================================' + _helpersConstants.COLORS.reset + '\nSelenium 2.0 / webdriver protocol bindings implementation with helper commands in nodejs.\nFor a complete list of commands, visit ' + _helpersConstants.COLORS.lime + 'http://webdriver.io/docs.html' + _helpersConstants.COLORS.reset + '.\n' + _helpersConstants.COLORS.yellow + '=======================================================================================' + _helpersConstants.COLORS.reset + '\n'; /** * Logger module * * A Logger helper with fancy colors */ var Logger = (function () { function Logger(options, eventHandler) { var _this = this; _classCallCheck(this, Logger); /** * log level * silent : no logs * command : command only * result : result only * error : error only * verbose : command + data + result */ this.logLevel = options.logLevel; this.setupWriteStream(options); /** * disable colors if coloredLogs is set to false or if we pipe output into files */ if (!JSON.parse(process.env.WEBDRIVERIO_COLORED_LOGS) || this.writeStream) { _Object$keys(_helpersConstants.COLORS).forEach(function (colorName) { return _helpersConstants.COLORS[colorName] = ''; }); } /** * print welcome message */ if (this.logLevel !== 'silent' && !this.infoHasBeenShown) { this.write(BANNER); this.infoHasBeenShown = true; } // register event handler to log command events eventHandler.on('command', function (data) { if (_this.logLevel === 'command' || _this.logLevel === 'verbose') { _this.command(data.method, data.uri.path); } if (_this.logLevel === 'data' || _this.logLevel === 'verbose') { _this.data(data.data); } }); // register event handler to log result events eventHandler.on('result', function (data) { // only log result events if they got executed successfully if (data.body && data.body.status === 0 && (_this.logLevel === 'result' || _this.logLevel === 'verbose')) { _this.result(typeof data.body.value ? data.body.value : data.body.orgStatusMessage); } }); // register event handler to log error events eventHandler.on('error', function (data) { if (data.err && data.err.code === 'ECONNREFUSED') { _this.error('Couldn\'t find a running selenium server instance on ' + data.requestOptions.uri); } else if (data.err && data.err.code === 'ENOTFOUND') { _this.error('Couldn\'t resolve hostname ' + data.requestOptions.uri); } else if (data.err && data.err.code === 'NOSESSIONID') { _this.error('Couldn\'t get a session ID - ' + data.err.message); } else if (_this.logLevel === 'error' || _this.logLevel === 'verbose') { if (data.body && _helpersConstants.ERROR_CODES[data.body.status]) { _this.error(_helpersConstants.ERROR_CODES[data.body.status].id + '\t' + _helpersConstants.ERROR_CODES[data.body.status].message + '\n\t\t\t' + data.body.value.message); } else if (typeof data.message === 'string') { _this.error('ServerError\t' + data.message); } else { _this.error(_helpersConstants.ERROR_CODES['-1'].id + '\t' + _helpersConstants.ERROR_CODES['-1'].message); } } }); } /** * helper method to check size of object * @param {Object} obj object you like to check * @return {Integer} number of own properties */ /** * create write stream if logOutput is a string */ _createClass(Logger, [{ key: 'setupWriteStream', value: function setupWriteStream(options) { if (typeof options.logOutput === 'string') { var newDate = new Date(); var dateString = newDate.toISOString().split(/\./)[0]; var filename = _helpersSanitize2['default'].caps(options.desiredCapabilities) + '.' + dateString + '.' + process.pid + '.log'; this.writeStream = _fs2['default'].createWriteStream(_path2['default'].join(process.cwd(), options.logOutput, filename)); this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel; } else if (typeof options.logOutput === 'object' && options.logOutput.writable) { this.writeStream = options.logOutput; this.logLevel = this.logLevel === 'silent' ? 'verbose' : this.logLevel; } } }, { key: 'write', value: function write() { for (var _len = arguments.length, messages = Array(_len), _key = 0; _key < _len; _key++) { messages[_key] = arguments[_key]; } var msgString = messages.join(' '); if (this.writeStream) { this.writeStream.write(msgString + '\n'); } else { console.log(msgString); } } /** * main log function */ }, { key: 'log', value: function log(message, content) { if (!this.logLevel || this.logLevel === 'silent') { return; } var currentDate = new Date(); var dateString = currentDate.toString().match(/\d\d:\d\d:\d\d/)[0]; var preamble = _helpersConstants.COLORS.dkgray + '[' + dateString + ']: ' + _helpersConstants.COLORS.reset; if (!content) { this.write(preamble, message); } else { this.write(preamble, message, '\t', JSON.stringify(content)); } } /** * logs command messages * @param {String} method method of command request * @param {String} path path of command request */ }, { key: 'command', value: function command(method, path) { if (method && path) { this.log(_helpersConstants.COLORS.violet + 'COMMAND\t' + _helpersConstants.COLORS.reset, method, path); } } /** * debugger info message */ }, { key: 'debug', value: function debug() { this.write('\n'); this.log(_helpersConstants.COLORS.yellow + 'DEBUG\t' + _helpersConstants.COLORS.reset + 'queue has stopped, you can now go into the browser'); this.log(_helpersConstants.COLORS.yellow + 'DEBUG\t' + _helpersConstants.COLORS.dkgray + 'continue by pressing the [ENTER] key ...' + _helpersConstants.COLORS.reset); } /** * logs data messages * @param {Object} data data object */ }, { key: 'data', value: function data(_data) { _data = JSON.stringify(_data); if (_data.length > 1000) { _data = '[String Buffer]'; } if (_data && keySize(_data) !== 0 && (this.logLevel === 'data' || this.logLevel === 'verbose')) { this.log(_helpersConstants.COLORS.brown + 'DATA\t\t' + _helpersConstants.COLORS.reset + _data); } } /** * logs result messages * @param {Object} result result object */ }, { key: 'result', value: function result(_result) { if (typeof _result === 'object') { _result = JSON.stringify(_result); } // prevent screenshot data output if (_result && _result.length > 1000) { _result = '[Buffer] screenshot data'; } this.log(_helpersConstants.COLORS.teal + 'RESULT\t\t' + _helpersConstants.COLORS.reset + _result); } /** * logs error messages * @param {String} msg error message */ }, { key: 'error', value: function error(msg) { if (msg && typeof msg === 'string' && msg.indexOf('caused by Request') !== -1) { msg = msg.substr(0, msg.indexOf('caused by Request') - 2); } if (msg && typeof msg === 'string' && msg.indexOf('Command duration or timeout') !== -1) { msg = msg.substr(0, msg.indexOf('Command duration or timeout')); } if (msg && typeof msg === 'string' && msg.indexOf('ID does not correspond to an open view') !== -1) { msg = msg.substr(0, msg.indexOf('ID does not correspond to an open view')); msg += 'NOTE: you probably try to continue your tests after closing a tab/window. Please set the focus on a current opened tab/window to continue. Use the window protocol command to do so.'; } if (msg) { this.log(_helpersConstants.COLORS.red + 'ERROR\t' + _helpersConstants.COLORS.reset + msg, null); } } /** * print exception if command fails * @param {String} type error type * @param {String} message error message * @param {String[]} stacktrace error stacktrace */ }], [{ key: 'printException', value: function printException(type, message, stacktrace) { stacktrace = stacktrace.map(function (trace) { return ' at ' + trace; }); this.write(_helpersConstants.COLORS.dkred + (type || 'Error') + ': ' + message + _helpersConstants.COLORS.reset, null); this.write(_helpersConstants.COLORS.dkgray + stacktrace.reverse().join('\n') + _helpersConstants.COLORS.reset, null); } }]); return Logger; })(); var keySize = function keySize(obj) { var size = 0; for (var key in obj) { if (obj.hasOwnProperty(key)) size++; } return size; }; exports['default'] = Logger; module.exports = exports['default']; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi91dGlscy9Mb2dnZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7a0JBQWUsSUFBSTs7OztvQkFDRixNQUFNOzs7O2dDQUVhLHNCQUFzQjs7K0JBQ3JDLHFCQUFxQjs7OztBQUUxQyxJQUFNLE1BQU0sVUFDVix5QkFBTyxNQUFNLCtGQUEwRix5QkFBTyxLQUFLLDRJQUU1RSx5QkFBTyxJQUFJLHFDQUFnQyx5QkFBTyxLQUFLLFdBQzlGLHlCQUFPLE1BQU0sK0ZBQTBGLHlCQUFPLEtBQUssT0FDcEgsQ0FBQTs7Ozs7Ozs7SUFPSyxNQUFNO0FBQ0ksYUFEVixNQUFNLENBQ0ssT0FBTyxFQUFFLFlBQVksRUFBRTs7OzhCQURsQyxNQUFNOzs7Ozs7Ozs7O0FBVUosWUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFBOztBQUVoQyxZQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUE7Ozs7O0FBSzlCLFlBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO0FBQ3ZFLGtEQUFtQixDQUFDLE9BQU8sQ0FBQyxVQUFBLFNBQVM7dUJBQUkseUJBQU8sU0FBUyxDQUFDLEdBQUcsRUFBRTthQUFBLENBQUMsQ0FBQTtTQUNuRTs7Ozs7QUFLRCxZQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFO0FBQ3RELGdCQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQ2xCLGdCQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFBO1NBQy9COzs7QUFHRCxvQkFBWSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsVUFBQyxJQUFJLEVBQUs7QUFDakMsZ0JBQUksTUFBSyxRQUFRLEtBQUssU0FBUyxJQUFJLE1BQUssUUFBUSxL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LEVBQUU7QUFDekIsUUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFBOztBQUVaLFNBQUssSUFBSSxHQUFHLElBQUksR0FBRyxFQUFFO0FBQ2pCLFlBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQTtLQUN0Qzs7QUFFRCxXQUFPLElBQUksQ0FBQTtDQUNkLENBQUE7O3FCQUVjLE1BQU0iLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ2ZzJ1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcblxuaW1wb3J0IHsgQ09MT1JTLCBFUlJPUl9DT0RFUyB9IGZyb20gJy4uL2hlbHBlcnMvY29uc3RhbnRzJ1xuaW1wb3J0IHNhbml0aXplIGZyb20gJy4uL2hlbHBlcnMvc2FuaXRpemUnXG5cbmNvbnN0IEJBTk5FUiA9IGBcbiR7Q09MT1JTLnllbGxvd309PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0ke0NPTE9SUy5yZXNldH1cblNlbGVuaXVtIDIuMCAvIHdlYmRyaXZlciBwcm90b2NvbCBiaW5kaW5ncyBpbXBsZW1lbnRhdGlvbiB3aXRoIGhlbHBlciBjb21tYW5kcyBpbiBub2RlanMuXG5Gb3IgYSBjb21wbGV0ZSBsaXN0IG9mIGNvbW1hbmRzLCB2aXNpdCAke0NPTE9SUy5saW1lfWh0dHA6Ly93ZWJkcml2ZXIuaW8vZG9jcy5odG1sJHtDT0xPUlMucmVzZXR9LlxuJHtDT0xPUlMueWVsbG93fT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSR7Q09MT1JTLnJlc2V0fVxuYFxuXG4vKipcbiAqIExvZ2dlciBtb2R1bGVcbiAqXG4gKiBBIExvZ2dlciBoZWxwZXIgd2l0aCBmYW5jeSBjb2xvcnNcbiAqL1xuY2xhc3MgTG9nZ2VyIHtcbiAgICBjb25zdHJ1Y3RvciAob3B0aW9ucywgZXZlbnRIYW5kbGVyKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBsb2cgbGV2ZWxcbiAgICAgICAgICogc2lsZW50IDogbm8gbG9nc1xuICAgICAgICAgKiBjb21tYW5kIDogY29tbWFuZCBvbmx5XG4gICAgICAgICAqIHJlc3VsdCA6IHJlc3VsdCBvbmx5XG4gICAgICAgICAqIGVycm9yIDogZXJyb3Igb25seVxuICAgICAgICAgKiB2ZXJib3NlIDogY29tbWFuZCArIGRhdGEgKyByZXN1bHRcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubG9nTGV2ZWwgPSBvcHRpb25zLmxvZ0xldmVsXG5cbiAgICAgICAgdGhpcy5zZXR1cFdyaXRlU3RyZWFtKG9wdGlvbnMpXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGRpc2FibGUgY29sb3JzIGlmIGNvbG9yZWRMb2dzIGlzIHNldCB0byBmYWxzZSBvciBpZiB3ZSBwaXBlIG91dHB1dCBpbnRvIGZpbGVzXG4gICAgICAgICAqL1xuICAgICAgICBpZiAoIUpTT04ucGFyc2UocHJvY2Vzcy5lbnYuV0VCRFJJVkVSSU9fQ09MT1JFRF9MT0dTKSB8fCB0aGlzLndyaXRlU3RyZWFtKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhDT0xPUlMpLmZvckVhY2goY29sb3JOYW1lID0+IENPTE9SU1tjb2xvck5hbWVdID0gJycpXG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogcHJpbnQgd2VsY29tZSBtZXNzYWdlXG4gICAgICAgICAqL1xuICAgICAgICBpZiAodGhpcy5sb2dMZXZlbCAhPT0gJ3NpbGVudCcgJiYgIXRoaXMuaW5mb0hhc0JlZW5TaG93bikge1xuICAgICAgICAgICAgdGhpcy53cml0ZShCQU5ORVIpXG4gICAgICAgICAgICB0aGlzLmluZm9IYXNCZWVuU2hvd24gPSB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyByZWdpc3RlciBldmVudCBoYW5kbGVyIHRvIGxvZyBjb21tYW5kIGV2ZW50c1xuICAgICAgICBldmVudEhhbmRsZXIub24oJ2NvbW1hbmQnLCAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMubG9nTGV2ZWwgPT09ICdjb21tYW5kJyB8fCB0aGlzLmxvZ0xldmVsID09PSAndmVyYm9zZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbW1hbmQoZGF0YS5tZXRob2QsIGRhdGEudXJpLnBhdGgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5sb2dMZXZlbCA9PT0gJ2RhdGEnIHx8IHRoaXMubG9nTGV2ZWwgPT09ICd2ZXJib3NlJykge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YShkYXRhLmRhdGEpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgLy8gcmVnaXN0ZXIgZXZlbnQgaGFuZGxlciB0byBsb2cgcmVzdWx0IGV2ZW50c1xuICAgICAgICBldmVudEhhbmRsZXIub24oJ3Jlc3VsdCcsIChkYXRhKSA9PiB7XG4gICAgICAgICAgICAvLyBvbmx5IGxvZyByZXN1bHQgZXZlbnRzIGlmIHRoZXkgZ290IGV4ZWN1dGVkIHN1Y2Nlc3NmdWxseVxuICAgICAgICAgICAgaWYgKGRhdGEuYm9keSAmJiBkYXRhLmJvZHkuc3RhdHVzID09PSAwICYmICh0aGlzLmxvZ0xldmVsID09PSAncmVzdWx0JyB8fCB0aGlzLmxvZ0xldmVsID09PSAndmVyYm9zZScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXN1bHQodHlwZW9mIGRhdGEuYm9keS52YWx1ZSA/IGRhdGEuYm9keS52YWx1ZSA6IGRhdGEuYm9keS5vcmdTdGF0dXNNZXNzYWdlKVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIC8vIHJlZ2lzdGVyIGV2ZW50IGhhbmRsZXIgdG8gbG9nIGVycm9yIGV2ZW50c1xuICAgICAgICBldmVudEhhbmRsZXIub24oJ2Vycm9yJywgKGRhdGEpID0+IHtcbiAgICAgICAgICAgIGlmIChkYXRhLmVyciAmJiBkYXRhLmVyci5jb2RlID09PSAnRUNPTk5SRUZVU0VEJykge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IoYENvdWxkbid0IGZpbmQgYSBydW5uaW5nIHNlbGVuaXVtIHNlcnZlciBpbnN0YW5jZSBvbiAke2RhdGEucmVxdWVzdE9wdGlvbnMudXJpfWApXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuZXJyICYmIGRhdGEuZXJyLmNvZGUgPT09ICdFTk9URk9VTkQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvcihgQ291bGRuJ3QgcmVzb2x2ZSBob3N0bmFtZSAke2RhdGEucmVxdWVzdE9wdGlvbnMudXJpfWApXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuZXJyICYmIGRhdGEuZXJyLmNvZGUgPT09ICdOT1NFU1NJT05JRCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVycm9yKGBDb3VsZG4ndCBnZXQgYSBzZXNzaW9uIElEIC0gJHtkYXRhLmVyci5tZXNzYWdlfWApXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMubG9nTGV2ZWwgPT09ICdlcnJvcicgfHwgdGhpcy5sb2dMZXZlbCA9PT0gJ3ZlcmJvc2UnKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuYm9keSAmJiBFUlJPUl9DT0RFU1tkYXRhLmJvZHkuc3RhdHVzXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9yKEVSUk9SX0NPREVTW2RhdGEuYm9keS5zdGF0dXNdLmlkICsgJ1xcdCcgKyBFUlJPUl9DT0RFU1tkYXRhLmJvZHkuc3RhdHVzXS5tZXNzYWdlICsgJ1xcblxcdFxcdFxcdCcgKyBkYXRhLmJvZHkudmFsdWUubWVzc2FnZSlcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLm1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IoJ1NlcnZlckVycm9yXFx0JyArIGRhdGEubWVzc2FnZSlcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9yKEVSUk9SX0NPREVTWyctMSddLmlkICsgJ1xcdCcgKyBFUlJPUl9DT0RFU1snLTEnXS5tZXNzYWdlKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBjcmVhdGUgd3JpdGUgc3RyZWFtIGlmIGxvZ091dHB1dCBpcyBhIHN0cmluZ1xuICAgICAqL1xuICAgIHNldHVwV3JpdGVTdHJlYW0gKG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ091dHB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGxldCBuZXdEYXRlID0gbmV3IERhdGUoKVxuICAgICAgICAgICAgbGV0IGRhdGVTdHJpbmcgPSBuZXdEYXRlLnRvSVNPU3RyaW5nKCkuc3BsaXQoL1xcLi8pWzBdXG4gICAgICAgICAgICBsZXQgZmlsZW5hbWUgPSBzYW5pdGl6ZS5jYXBzKG9wdGlvbnMuZGVzaXJlZENhcGFiaWxpdGllcykgKyAnLicgKyBkYXRlU3RyaW5nICsgJy4nICsgcHJvY2Vzcy5waWQgKyAnLmxvZydcblxuICAgICAgICAgICAgdGhpcy53cml0ZVN0cmVhbSA9IGZzLmNyZWF0ZVdyaXRlU3RyZWFtKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBvcHRpb25zLmxvZ091dHB1dCwgZmlsZW5hbWUpKVxuICAgICAgICAgICAgdGhpcy5sb2dMZXZlbCA9IHRoaXMubG9nTGV2ZWwgPT09ICdzaWxlbnQnID8gJ3ZlcmJvc2UnIDogdGhpcy5sb2dMZXZlbFxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ091dHB1dCA9PT0gJ29iamVjdCcgJiYgb3B0aW9ucy5sb2dPdXRwdXQud3JpdGFibGUpIHtcbiAgICAgICAgICAgIHRoaXMud3JpdGVTdHJlYW0gPSBvcHRpb25zLmxvZ091dHB1dFxuICAgICAgICAgICAgdGhpcy5sb2dMZXZlbCA9IHRoaXMubG9nTGV2ZWwgPT09ICdzaWxlbnQnID8gJ3ZlcmJvc2UnIDogdGhpcy5sb2dMZXZlbFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3JpdGUgKC4uLm1lc3NhZ2VzKSB7XG4gICAgICAgIGxldCBtc2dTdHJpbmcgPSBtZXNzYWdlcy5qb2luKCcgJylcblxuICAgICAgICBpZiAodGhpcy53cml0ZVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy53cml0ZVN0cmVhbS53cml0ZShtc2dTdHJpbmcgKyAnXFxuJylcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKG1zZ1N0cmluZylcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIG1haW4gbG9nIGZ1bmN0aW9uXG4gICAgICovXG4gICAgbG9nIChtZXNzYWdlLCBjb250ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5sb2dMZXZlbCB8fCB0aGlzLmxvZ0xldmVsID09PSAnc2lsZW50Jykge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpXG4gICAgICAgIGxldCBkYXRlU3RyaW5nID0gY3VycmVudERhdGUudG9TdHJpbmcoKS5tYXRjaCgvXFxkXFxkOlxcZFxcZDpcXGRcXGQvKVswXVxuICAgICAgICBsZXQgcHJlYW1ibGUgPSBgJHtDT0xPUlMuZGtncmF5fVske2RhdGVTdHJpbmd9XTogJHtDT0xPUlMucmVzZXR9YFxuXG4gICAgICAgIGlmICghY29udGVudCkge1xuICAgICAgICAgICAgdGhpcy53cml0ZShwcmVhbWJsZSwgbWVzc2FnZSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMud3JpdGUocHJlYW1ibGUsIG1lc3NhZ2UsICdcXHQnLCBKU09OLnN0cmluZ2lmeShjb250ZW50KSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGxvZ3MgY29tbWFuZCBtZXNzYWdlc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbWV0aG9kICBtZXRob2Qgb2YgY29tbWFuZCByZXF1ZXN0XG4gICAgICogQHBhcmFtICB7U3RyaW5nfSBwYXRoICAgIHBhdGggb2YgY29tbWFuZCByZXF1ZXN0XG4gICAgICovXG4gICAgY29tbWFuZCAobWV0aG9kLCBwYXRoKSB7XG4gICAgICAgIGlmIChtZXRob2QgJiYgcGF0aCkge1xuICAgICAgICAgICAgdGhpcy5sb2coYCR7Q09MT1JTLnZpb2xldH1DT01NQU5EXFx0JHtDT0xPUlMucmVzZXR9YCwgbWV0aG9kLCBwYXRoKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZGVidWdnZXIgaW5mbyBtZXNzYWdlXG4gICAgICovXG4gICAgZGVidWcgKCkge1xuICAgICAgICB0aGlzLndyaXRlKCdcXG4nKVxuICAgICAgICB0aGlzLmxvZyhgJHtDT0xPUlMueWVsbG93fURFQlVHXFx0JHtDT0xPUlMucmVzZXR9cXVldWUgaGFzIHN0b3BwZWQsIHlvdSBjYW4gbm93IGdvIGludG8gdGhlIGJyb3dzZXJgKVxuICAgICAgICB0aGlzLmxvZyhgJHtDT0xPUlMueWVsbG93fURFQlVHXFx0JHtDT0xPUlMuZGtncmF5fWNvbnRpbnVlIGJ5IHByZXNzaW5nIHRoZSBbRU5URVJdIGtleSAuLi4ke0NPTE9SUy5yZXNldH1gKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGxvZ3MgZGF0YSBtZXNzYWdlc1xuICAgICAqIEBwYXJhbSAge09iamVjdH0gZGF0YSAgZGF0YSBvYmplY3RcbiAgICAgKi9cbiAgICBkYXRhIChkYXRhKSB7XG4gICAgICAgIGRhdGEgPSBKU09OLnN0cmluZ2lmeShkYXRhKVxuXG4gICAgICAgIGlmIChkYXRhLmxlbmd0aCA+IDEwMDApIHtcbiAgICAgICAgICAgIGRhdGEgPSAnW1N0cmluZyBCdWZmZXJdJ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGEgJiYga2V5U2l6ZShkYXRhKSAhPT0gMCAmJiAodGhpcy5sb2dMZXZlbCA9PT0gJ2RhdGEnIHx8IHRoaXMubG9nTGV2ZWwgPT09ICd2ZXJib3NlJykpIHtcbiAgICAgICAgICAgIHRoaXMubG9nKGAke0NPTE9SUy5icm93bn1EQVRBXFx0XFx0JHtDT0xPUlMucmVzZXR9JHtkYXRhfWApXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBsb2dzIHJlc3VsdCBtZXNzYWdlc1xuICAgICAqIEBwYXJhbSAge09iamVjdH0gcmVzdWx0ICByZXN1bHQgb2JqZWN0XG4gICAgICovXG4gICAgcmVzdWx0IChyZXN1bHQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBKU09OLnN0cmluZ2lmeShyZXN1bHQpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBwcmV2ZW50IHNjcmVlbnNob3QgZGF0YSBvdXRwdXRcbiAgICAgICAgaWYgKHJlc3VsdCAmJiByZXN1bHQubGVuZ3RoID4gMTAwMCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gJ1tCdWZmZXJdIHNjcmVlbnNob3QgZGF0YSdcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubG9nKGAke0NPTE9SUy50ZWFsfVJFU1VMVFxcdFxcdCR7Q09MT1JTLnJlc2V0fSR7cmVzdWx0fWApXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogbG9ncyBlcnJvciBtZXNzYWdlc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbXNnICBlcnJvciBtZXNzYWdlXG4gICAgICovXG4gICAgZXJyb3IgKG1zZykge1xuICAgICAgICBpZiAobXNnICYmIHR5cGVvZiBtc2cgPT09ICdzdHJpbmcnICYmIG1zZy5pbmRleE9mKCdjYXVzZWQgYnkgUmVxdWVzdCcpICE9PSAtMSkge1xuICAgICAgICAgICAgbXNnID0gbXNnLnN1YnN0cigwLCBtc2cuaW5kZXhPZignY2F1c2VkIGJ5IFJlcXVlc3QnKSAtIDIpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobXNnICYmIHR5cGVvZiBtc2cgPT09ICdzdHJpbmcnICYmIG1zZy5pbmRleE9mKCdDb21tYW5kIGR1cmF0aW9uIG9yIHRpbWVvdXQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIG1zZyA9IG1zZy5zdWJzdHIoMCwgbXNnLmluZGV4T2YoJ0NvbW1hbmQgZHVyYXRpb24gb3IgdGltZW91dCcpKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1zZyAmJiB0eXBlb2YgbXNnID09PSAnc3RyaW5nJyAmJiBtc2cuaW5kZXhPZignSUQgZG9lcyBub3QgY29ycmVzcG9uZCB0byBhbiBvcGVuIHZpZXcnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIG1zZyA9IG1zZy5zdWJzdHIoMCwgbXNnLmluZGV4T2YoJ0lEIGRvZXMgbm90IGNvcnJlc3BvbmQgdG8gYW4gb3BlbiB2aWV3JykpXG4gICAgICAgICAgICBtc2cgKz0gJ05PVEU6IHlvdSBwcm9iYWJseSB0cnkgdG8gY29udGludWUgeW91ciB0ZXN0cyBhZnRlciBjbG9zaW5nIGEgdGFiL3dpbmRvdy4gUGxlYXNlIHNldCB0aGUgZm9jdXMgb24gYSBjdXJyZW50IG9wZW5lZCB0YWIvd2luZG93IHRvIGNvbnRpbnVlLiBVc2UgdGhlIHdpbmRvdyBwcm90b2NvbCBjb21tYW5kIHRvIGRvIHNvLidcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtc2cpIHtcbiAgICAgICAgICAgIHRoaXMubG9nKENPTE9SUy5yZWQgKyAnRVJST1JcXHQnICsgQ09MT1JTLnJlc2V0ICsgbXNnLCBudWxsKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogcHJpbnQgZXhjZXB0aW9uIGlmIGNvbW1hbmQgZmFpbHNcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gICB0eXBlICAgICAgICBlcnJvciB0eXBlXG4gICAgICogQHBhcmFtIHtTdHJpbmd9ICAgbWVzc2FnZSAgICAgZXJyb3IgbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IHN0YWNrdHJhY2UgIGVycm9yIHN0YWNrdHJhY2VcbiAgICAgKi9cbiAgICBzdGF0aWMgcHJpbnRFeGNlcHRpb24gKHR5cGUsIG1lc3NhZ2UsIHN0YWNrdHJhY2UpIHtcbiAgICAgICAgc3RhY2t0cmFjZSA9IHN0YWNrdHJhY2UubWFwKHRyYWNlID0+ICcgICAgYXQgJyArIHRyYWNlKVxuICAgICAgICB0aGlzLndyaXRlKENPTE9SUy5ka3JlZCArICh0eXBlIHx8ICdFcnJvcicpICsgJzogJyArIG1lc3NhZ2UgKyBDT0xPUlMucmVzZXQsIG51bGwpXG4gICAgICAgIHRoaXMud3JpdGUoQ09MT1JTLmRrZ3JheSArIHN0YWNrdHJhY2UucmV2ZXJzZSgpLmpvaW4oJ1xcbicpICsgQ09MT1JTLnJlc2V0LCBudWxsKVxuICAgIH1cbn1cblxuLyoqXG4gKiBoZWxwZXIgbWV0aG9kIHRvIGNoZWNrIHNpemUgb2Ygb2JqZWN0XG4gKiBAcGFyYW0gICB7T2JqZWN0fSAgIG9iaiAgb2JqZWN0IHlvdSBsaWtlIHRvIGNoZWNrXG4gKiBAcmV0dXJuICB7SW50ZWdlcn0gICAgICAgbnVtYmVyIG9mIG93biBwcm9wZXJ0aWVzXG4gKi9cbmxldCBrZXlTaXplID0gZnVuY3Rpb24gKG9iaikge1xuICAgIGxldCBzaXplID0gMFxuXG4gICAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHNpemUrK1xuICAgIH1cblxuICAgIHJldHVybiBzaXplXG59XG5cbmV4cG9ydCBkZWZhdWx0IExvZ2dlclxuIl19