@testim/testim-cli
Version:
Command line interface for running Testing on you CI
262 lines (215 loc) • 22.4 kB
JavaScript
;
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 _Promise = require('babel-runtime/core-js/promise')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _q = require('q');
var _q2 = _interopRequireDefault(_q);
/**
* Multibrowser
*/
var Multibrowser = (function () {
function Multibrowser() {
_classCallCheck(this, Multibrowser);
this.instances = {};
this.promiseBucket = [];
var defer = _q2['default'].defer();
this.qResolve = defer.resolve.toString();
}
/**
* add instance to multibrowser instance
*/
_createClass(Multibrowser, [{
key: 'addInstance',
value: function addInstance(browserName, client) {
if (this.instances[browserName]) {
throw new Error('webdriver instance "' + browserName + '" is already defined');
}
this.instances[browserName] = client;
}
/**
* modifier for multibrowser instance
*/
}, {
key: 'getModifier',
value: function getModifier() {
return multiremoteModifier.bind(this);
}
/**
* flush bucket and return current pending promises
*/
}, {
key: 'flushPromiseBucket',
value: function flushPromiseBucket() {
var bucket = this.promiseBucket.filter(function (promise) {
return promise.inspect().state === 'pending';
});
this.promiseBucket = [];
return bucket;
}
/**
* modifier for single webdriverio instances
*/
}, {
key: 'getInstanceModifier',
value: function getInstanceModifier() {
return instanceModifier.bind(this);
}
}]);
return Multibrowser;
})();
function instanceModifier(client) {
var _next = client.next;
var multibrowser = this;
/**
* Overwrite next (bind) method to put each command into a bucket.
* This provides us useful information about all current running
* commands.
*/
client.next = function () {
multibrowser.promiseBucket.push(this.promise);
return _next.apply(this, arguments);
};
return client;
}
function multiremoteModifier(client) {
var multibrowser = this;
var browserNames = _Object$keys(multibrowser.instances);
client.next = function () {
var _this = this;
var promises = [];
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var fnName = args.pop();
/**
* no need for actual function here
*/
args.shift();
/**
* flush promise bucket
*/
multibrowser.promiseBucket = [];
var commandArgs = args.pop();
return this.lastPromise.done(function () {
browserNames.forEach(function (browserName) {
var instance = multibrowser.instances[browserName];
promises.push(instance[fnName].apply(instance, commandArgs).promise);
});
return _Promise.all(promises).then(function (result) {
/**
* custom event handling since multibrowser instance
* actually never executes any command
*/
var payload = {
fnName: fnName
};
for (var i = 0; i < browserNames.length; ++i) {
payload[browserNames[i]] = result[i];
}
if (fnName.match(/(init|end)/)) {
_this.emit(fnName, payload);
}
_this.emit('result', payload);
_this.defer.resolve(result);
}, function (err) {
_this.emit('error', err);
_this.defer.reject(err);
});
});
};
var _then = client.then;
client.then = function (onFulfilled, onRejected) {
/**
* curry arguments
* as multibrowser commands return with an array of results for each instance
* respectively (see q.all) we need to curry them (expand arguments) to help
* users to better work with the results
*
* uncurried original version:
* ```js
* matrix.getTitle().then(function (result) {
* expect(result[0]).to.be.equal('title of browser A')
* expect(result[1]).to.be.equal('title of browser B')
* })
* ```
*
* curried version:
* ```js
* matrix.getTitle().then(function (titleBrowserA, titleBrowserB) {
* expect(titleBrowserA).to.be.equal('title of browser A')
* expect(titleBrowserB).to.be.equal('title of browser B')
* })
* ```
*/
var curryArguments = function curryArguments(args) {
/**
* when returning with a promise within a multibrowser promise like
*
* ```js
* matrix.url(...).getTitle().then(function () {
* return matrix.getSource()
* })
* ```
*
* we will have problems as we are running through curryArguments twice.
* Therefor check if the onFulFilled handler is from the Q library and
* handle that promise as usual here.
* It's an ugly hack but the only way to get around with this and having
* nice curried arguments.
*
*/
if (onFulfilled.toString() === multibrowser.qResolve) {
return onFulfilled.apply(this, arguments);
}
if (arguments.length === 1 && !Array.isArray(args)) {
return onFulfilled.call(this, args);
}
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments);
}
return onFulfilled.apply(this, args);
};
if (!onFulfilled && !onRejected) {
return this;
}
if (onFulfilled && !onRejected) {
return _then.call(this, curryArguments);
}
if (onFulfilled && onRejected) {
return _then.call(this, curryArguments, onRejected);
}
return _then.call(this, undefined, onRejected);
};
client.select = function (browserName) {
var instance = multibrowser.instances[browserName];
if (!instance) {
throw new Error('browser name "' + browserName + '" was not defined');
}
instance.isMultibrowser = false;
return instance;
};
client.sync = function () {
var bucket = multibrowser.flushPromiseBucket();
return this.call(function () {
return _Promise.all(bucket);
});
};
var _addCommand = client.addCommand;
client.addCommand = function (fnName, fn, forceOverwrite) {
_addCommand.call(this, fnName, fn, forceOverwrite);
_Object$keys(multibrowser.instances).forEach(function (browserName) {
var instance = multibrowser.instances[browserName];
instance.addCommand(fnName, fn, forceOverwrite);
});
return this;
};
return client;
}
exports['default'] = Multibrowser;
module.exports = exports['default'];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9tdWx0aWJyb3dzZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztpQkFBYyxHQUFHOzs7Ozs7OztJQUtYLFlBQVk7QUFDRixhQURWLFlBQVksR0FDQzs4QkFEYixZQUFZOztBQUVWLFlBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFBO0FBQ25CLFlBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFBOztBQUV2QixZQUFJLEtBQUssR0FBRyxlQUFFLEtBQUssRUFBRSxDQUFBO0FBQ3JCLFlBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQTtLQUMzQzs7Ozs7O2lCQVBDLFlBQVk7O2VBWUYscUJBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRTtBQUM5QixnQkFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxFQUFFO0FBQzdCLHNCQUFNLElBQUksS0FBSywwQkFBd0IsV0FBVywwQkFBdUIsQ0FBQTthQUM1RTtBQUNELGdCQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sQ0FBQTtTQUN2Qzs7Ozs7OztlQUtXLHVCQUFHO0FBQ1gsbUJBQU8sbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1NBQ3hDOzs7Ozs7O2VBS2tCLDhCQUFHO0FBQ2xCLGdCQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxVQUFBLE9BQU87dUJBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssS0FBSyxTQUFTO2FBQUEsQ0FBQyxDQUFBO0FBQ3hGLGdCQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQTtBQUN2QixtQkFBTyxNQUFNLENBQUE7U0FDaEI7Ozs7Ozs7ZUFLbUIsK0JBQUc7QUFDbkIsbUJBQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1NBQ3JDOzs7V0F4Q0MsWUFBWTs7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SyxvQkFBa0IsV0FBVyx1QkFBb0IsQ0FBQTtTQUNuRTs7QUFFRCxnQkFBUSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUE7QUFDL0IsZUFBTyxRQUFRLENBQUE7S0FDbEIsQ0FBQTs7QUFFRCxVQUFNLENBQUMsSUFBSSxHQUFHLFlBQVk7QUFDdEIsWUFBSSxNQUFNLEdBQUcsWUFBWSxDQUFDLGtCQUFrQixFQUFFLENBQUE7QUFDOUMsZUFBTyxJQUFJLENBQUMsSUFBSSxDQUFDO21CQUFNLFNBQVEsR0FBRyxDQUFDLE1BQU0sQ0FBQztTQUFBLENBQUMsQ0FBQTtLQUM5QyxDQUFBOztBQUVELFFBQUksV0FBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUE7QUFDbkMsVUFBTSxDQUFDLFVBQVUsR0FBRyxVQUFVLE1BQU0sRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFO0FBQ3RELG1CQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLGNBQWMsQ0FBQyxDQUFBO0FBQ2xELHFCQUFZLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBQyxXQUFXLEVBQUs7QUFDekQsZ0JBQUksUUFBUSxHQUFHLFlBQVksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUE7QUFDbEQsb0JBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQTtTQUNsRCxDQUFDLENBQUE7QUFDRixlQUFPLElBQUksQ0FBQTtLQUNkLENBQUE7O0FBRUQsV0FBTyxNQUFNLENBQUE7Q0FDaEI7O3FCQUVjLFlBQVkiLCJmaWxlIjoibXVsdGlicm93c2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHEgZnJvbSAncSdcblxuLyoqXG4gKiBNdWx0aWJyb3dzZXJcbiAqL1xuY2xhc3MgTXVsdGlicm93c2VyIHtcbiAgICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgICAgIHRoaXMuaW5zdGFuY2VzID0ge31cbiAgICAgICAgdGhpcy5wcm9taXNlQnVja2V0ID0gW11cblxuICAgICAgICB2YXIgZGVmZXIgPSBxLmRlZmVyKClcbiAgICAgICAgdGhpcy5xUmVzb2x2ZSA9IGRlZmVyLnJlc29sdmUudG9TdHJpbmcoKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGFkZCBpbnN0YW5jZSB0byBtdWx0aWJyb3dzZXIgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBhZGRJbnN0YW5jZSAoYnJvd3Nlck5hbWUsIGNsaWVudCkge1xuICAgICAgICBpZiAodGhpcy5pbnN0YW5jZXNbYnJvd3Nlck5hbWVdKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHdlYmRyaXZlciBpbnN0YW5jZSBcIiR7YnJvd3Nlck5hbWV9XCIgaXMgYWxyZWFkeSBkZWZpbmVkYClcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmluc3RhbmNlc1ticm93c2VyTmFtZV0gPSBjbGllbnRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBtb2RpZmllciBmb3IgbXVsdGlicm93c2VyIGluc3RhbmNlXG4gICAgICovXG4gICAgZ2V0TW9kaWZpZXIgKCkge1xuICAgICAgICByZXR1cm4gbXVsdGlyZW1vdGVNb2RpZmllci5iaW5kKHRoaXMpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZmx1c2ggYnVja2V0IGFuZCByZXR1cm4gY3VycmVudCBwZW5kaW5nIHByb21pc2VzXG4gICAgICovXG4gICAgZmx1c2hQcm9taXNlQnVja2V0ICgpIHtcbiAgICAgICAgdmFyIGJ1Y2tldCA9IHRoaXMucHJvbWlzZUJ1Y2tldC5maWx0ZXIocHJvbWlzZSA9PiBwcm9taXNlLmluc3BlY3QoKS5zdGF0ZSA9PT0gJ3BlbmRpbmcnKVxuICAgICAgICB0aGlzLnByb21pc2VCdWNrZXQgPSBbXVxuICAgICAgICByZXR1cm4gYnVja2V0XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogbW9kaWZpZXIgZm9yIHNpbmdsZSB3ZWJkcml2ZXJpbyBpbnN0YW5jZXNcbiAgICAgKi9cbiAgICBnZXRJbnN0YW5jZU1vZGlmaWVyICgpIHtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlTW9kaWZpZXIuYmluZCh0aGlzKVxuICAgIH1cbn1cblxuZnVuY3Rpb24gaW5zdGFuY2VNb2RpZmllciAoY2xpZW50KSB7XG4gICAgbGV0IF9uZXh0ID0gY2xpZW50Lm5leHRcbiAgICBsZXQgbXVsdGlicm93c2VyID0gdGhpc1xuXG4gICAgLyoqXG4gICAgICogT3ZlcndyaXRlIG5leHQgKGJpbmQpIG1ldGhvZCB0byBwdXQgZWFjaCBjb21tYW5kIGludG8gYSBidWNrZXQuXG4gICAgICogVGhpcyBwcm92aWRlcyB1cyB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgYWxsIGN1cnJlbnQgcnVubmluZ1xuICAgICAqIGNvbW1hbmRzLlxuICAgICAqL1xuICAgIGNsaWVudC5uZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBtdWx0aWJyb3dzZXIucHJvbWlzZUJ1Y2tldC5wdXNoKHRoaXMucHJvbWlzZSlcbiAgICAgICAgcmV0dXJuIF9uZXh0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICB9XG5cbiAgICByZXR1cm4gY2xpZW50XG59XG5cbmZ1bmN0aW9uIG11bHRpcmVtb3RlTW9kaWZpZXIgKGNsaWVudCkge1xuICAgIGxldCBtdWx0aWJyb3dzZXIgPSB0aGlzXG4gICAgbGV0IGJyb3dzZXJOYW1lcyA9IE9iamVjdC5rZXlzKG11bHRpYnJvd3Nlci5pbnN0YW5jZXMpXG5cbiAgICBjbGllbnQubmV4dCA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCBwcm9taXNlcyA9IFtdXG4gICAgICAgIGxldCBmbk5hbWUgPSBhcmdzLnBvcCgpXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG5vIG5lZWQgZm9yIGFjdHVhbCBmdW5jdGlvbiBoZXJlXG4gICAgICAgICAqL1xuICAgICAgICBhcmdzLnNoaWZ0KClcblxuICAgICAgICAvKipcbiAgICAgICAgICogZmx1c2ggcHJvbWlzZSBidWNrZXRcbiAgICAgICAgICovXG4gICAgICAgIG11bHRpYnJvd3Nlci5wcm9taXNlQnVja2V0ID0gW11cbiAgICAgICAgbGV0IGNvbW1hbmRBcmdzID0gYXJncy5wb3AoKVxuICAgICAgICByZXR1cm4gdGhpcy5sYXN0UHJvbWlzZS5kb25lKCgpID0+IHtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lcy5mb3JFYWNoKChicm93c2VyTmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBpbnN0YW5jZSA9IG11bHRpYnJvd3Nlci5pbnN0YW5jZXNbYnJvd3Nlck5hbWVdXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChpbnN0YW5jZVtmbk5hbWVdLmFwcGx5KGluc3RhbmNlLCBjb21tYW5kQXJncykucHJvbWlzZSlcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogY3VzdG9tIGV2ZW50IGhhbmRsaW5nIHNpbmNlIG11bHRpYnJvd3NlciBpbnN0YW5jZVxuICAgICAgICAgICAgICAgICAqIGFjdHVhbGx5IG5ldmVyIGV4ZWN1dGVzIGFueSBjb21tYW5kXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgbGV0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGZuTmFtZTogZm5OYW1lXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBicm93c2VyTmFtZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZFticm93c2VyTmFtZXNbaV1dID0gcmVzdWx0W2ldXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGZuTmFtZS5tYXRjaCgvKGluaXR8ZW5kKS8pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdChmbk5hbWUsIHBheWxvYWQpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdyZXN1bHQnLCBwYXlsb2FkKVxuICAgICAgICAgICAgICAgIHRoaXMuZGVmZXIucmVzb2x2ZShyZXN1bHQpXG4gICAgICAgICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIGVycilcbiAgICAgICAgICAgICAgICB0aGlzLmRlZmVyLnJlamVjdChlcnIpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIHZhciBfdGhlbiA9IGNsaWVudC50aGVuXG4gICAgY2xpZW50LnRoZW4gPSBmdW5jdGlvbiAob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGN1cnJ5IGFyZ3VtZW50c1xuICAgICAgICAgKiBhcyBtdWx0aWJyb3dzZXIgY29tbWFuZHMgcmV0dXJuIHdpdGggYW4gYXJyYXkgb2YgcmVzdWx0cyBmb3IgZWFjaCBpbnN0YW5jZVxuICAgICAgICAgKiByZXNwZWN0aXZlbHkgKHNlZSBxLmFsbCkgd2UgbmVlZCB0byBjdXJyeSB0aGVtIChleHBhbmQgYXJndW1lbnRzKSB0byBoZWxwXG4gICAgICAgICAqIHVzZXJzIHRvIGJldHRlciB3b3JrIHdpdGggdGhlIHJlc3VsdHNcbiAgICAgICAgICpcbiAgICAgICAgICogdW5jdXJyaWVkIG9yaWdpbmFsIHZlcnNpb246XG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIG1hdHJpeC5nZXRUaXRsZSgpLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgKiAgICAgZXhwZWN0KHJlc3VsdFswXSkudG8uYmUuZXF1YWwoJ3RpdGxlIG9mIGJyb3dzZXIgQScpXG4gICAgICAgICAqICAgICBleHBlY3QocmVzdWx0WzFdKS50by5iZS5lcXVhbCgndGl0bGUgb2YgYnJvd3NlciBCJylcbiAgICAgICAgICogfSlcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqXG4gICAgICAgICAqIGN1cnJpZWQgdmVyc2lvbjpcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogbWF0cml4LmdldFRpdGxlKCkudGhlbihmdW5jdGlvbiAodGl0bGVCcm93c2VyQSwgdGl0bGVCcm93c2VyQikge1xuICAgICAgICAgKiAgICAgZXhwZWN0KHRpdGxlQnJvd3NlckEpLnRvLmJlLmVxdWFsKCd0aXRsZSBvZiBicm93c2VyIEEnKVxuICAgICAgICAgKiAgICAgZXhwZWN0KHRpdGxlQnJvd3NlckIpLnRvLmJlLmVxdWFsKCd0aXRsZSBvZiBicm93c2VyIEInKVxuICAgICAgICAgKiB9KVxuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIGxldCBjdXJyeUFyZ3VtZW50cyA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIHdoZW4gcmV0dXJuaW5nIHdpdGggYSBwcm9taXNlIHdpdGhpbiBhIG11bHRpYnJvd3NlciBwcm9taXNlIGxpa2VcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgICAgICogbWF0cml4LnVybCguLi4pLmdldFRpdGxlKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgKiAgICAgcmV0dXJuIG1hdHJpeC5nZXRTb3VyY2UoKVxuICAgICAgICAgICAgICogfSlcbiAgICAgICAgICAgICAqIGBgYFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIHdlIHdpbGwgaGF2ZSBwcm9ibGVtcyBhcyB3ZSBhcmUgcnVubmluZyB0aHJvdWdoIGN1cnJ5QXJndW1lbnRzIHR3aWNlLlxuICAgICAgICAgICAgICogVGhlcmVmb3IgY2hlY2sgaWYgdGhlIG9uRnVsRmlsbGVkIGhhbmRsZXIgaXMgZnJvbSB0aGUgUSBsaWJyYXJ5IGFuZFxuICAgICAgICAgICAgICogaGFuZGxlIHRoYXQgcHJvbWlzZSBhcyB1c3VhbCBoZXJlLlxuICAgICAgICAgICAgICogSXQncyBhbiB1Z2x5IGhhY2sgYnV0IHRoZSBvbmx5IHdheSB0byBnZXQgYXJvdW5kIHdpdGggdGhpcyBhbmQgaGF2aW5nXG4gICAgICAgICAgICAgKiBuaWNlIGN1cnJpZWQgYXJndW1lbnRzLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYgKG9uRnVsZmlsbGVkLnRvU3RyaW5nKCkgPT09IG11bHRpYnJvd3Nlci5xUmVzb2x2ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvbkZ1bGZpbGxlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSAmJiAhQXJyYXkuaXNBcnJheShhcmdzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvbkZ1bGZpbGxlZC5jYWxsKHRoaXMsIGFyZ3MpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvbkZ1bGZpbGxlZC5hcHBseSh0aGlzLCBhcmdzKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFvbkZ1bGZpbGxlZCAmJiAhb25SZWplY3RlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvbkZ1bGZpbGxlZCAmJiAhb25SZWplY3RlZCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGVuLmNhbGwodGhpcywgY3VycnlBcmd1bWVudHMpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAob25GdWxmaWxsZWQgJiYgb25SZWplY3RlZCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGVuLmNhbGwodGhpcywgY3VycnlBcmd1bWVudHMsIG9uUmVqZWN0ZWQpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gX3RoZW4uY2FsbCh0aGlzLCB1bmRlZmluZWQsIG9uUmVqZWN0ZWQpXG4gICAgfVxuXG4gICAgY2xpZW50LnNlbGVjdCA9IGZ1bmN0aW9uIChicm93c2VyTmFtZSkge1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSBtdWx0aWJyb3dzZXIuaW5zdGFuY2VzW2Jyb3dzZXJOYW1lXVxuXG4gICAgICAgIGlmICghaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgYnJvd3NlciBuYW1lIFwiJHticm93c2VyTmFtZX1cIiB3YXMgbm90IGRlZmluZWRgKVxuICAgICAgICB9XG5cbiAgICAgICAgaW5zdGFuY2UuaXNNdWx0aWJyb3dzZXIgPSBmYWxzZVxuICAgICAgICByZXR1cm4gaW5zdGFuY2VcbiAgICB9XG5cbiAgICBjbGllbnQuc3luYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGJ1Y2tldCA9IG11bHRpYnJvd3Nlci5mbHVzaFByb21pc2VCdWNrZXQoKVxuICAgICAgICByZXR1cm4gdGhpcy5jYWxsKCgpID0+IFByb21pc2UuYWxsKGJ1Y2tldCkpXG4gICAgfVxuXG4gICAgdmFyIF9hZGRDb21tYW5kID0gY2xpZW50LmFkZENvbW1hbmRcbiAgICBjbGllbnQuYWRkQ29tbWFuZCA9IGZ1bmN0aW9uIChmbk5hbWUsIGZuLCBmb3JjZU92ZXJ3cml0ZSkge1xuICAgICAgICBfYWRkQ29tbWFuZC5jYWxsKHRoaXMsIGZuTmFtZSwgZm4sIGZvcmNlT3ZlcndyaXRlKVxuICAgICAgICBPYmplY3Qua2V5cyhtdWx0aWJyb3dzZXIuaW5zdGFuY2VzKS5mb3JFYWNoKChicm93c2VyTmFtZSkgPT4ge1xuICAgICAgICAgICAgbGV0IGluc3RhbmNlID0gbXVsdGlicm93c2VyLmluc3RhbmNlc1ticm93c2VyTmFtZV1cbiAgICAgICAgICAgIGluc3RhbmNlLmFkZENvbW1hbmQoZm5OYW1lLCBmbiwgZm9yY2VPdmVyd3JpdGUpXG4gICAgICAgIH0pXG4gICAgICAgIHJldHVybiB0aGlzXG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaWVudFxufVxuXG5leHBvcnQgZGVmYXVsdCBNdWx0aWJyb3dzZXJcbiJdfQ==