appium-xcuitest-driver-conan
Version:
Appium driver for iOS using XCUITest for backend
698 lines (546 loc) • 38.3 kB
JavaScript
;
var _Object$assign = require('babel-runtime/core-js/object/assign')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _appiumBaseDriver = require('appium-base-driver');
var _appiumIosDriver = require('appium-ios-driver');
var _appiumSupport = require('appium-support');
var _asyncbox = require('asyncbox');
var _logger = require('../logger');
var _logger2 = _interopRequireDefault(_logger);
var commands = {},
extensions = {};
_Object$assign(extensions, _appiumIosDriver.iosCommands.element);
commands.getAttribute = function callee$0$0(attribute, el) {
var atomsElement;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = _appiumSupport.util.unwrapElement(el);
if (this.isWebContext()) {
context$1$0.next = 5;
break;
}
context$1$0.next = 4;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/attribute/' + attribute, 'GET'));
case 4:
return context$1$0.abrupt('return', context$1$0.sent);
case 5:
atomsElement = this.getAtomsElement(el);
if (!_lodash2['default'].isNull(atomsElement)) {
context$1$0.next = 10;
break;
}
throw new _appiumBaseDriver.errors.UnknownError('Error converting element ID for using in WD atoms: \'' + el);
case 10:
context$1$0.next = 12;
return _regeneratorRuntime.awrap(this.executeAtom('get_attribute_value', [atomsElement, attribute]));
case 12:
return context$1$0.abrupt('return', context$1$0.sent);
case 13:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.getText = function callee$0$0(el) {
var atomsElement;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = _appiumSupport.util.unwrapElement(el);
if (this.isWebContext()) {
context$1$0.next = 5;
break;
}
context$1$0.next = 4;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/text', 'GET'));
case 4:
return context$1$0.abrupt('return', context$1$0.sent);
case 5:
atomsElement = this.useAtomsElement(el);
context$1$0.next = 8;
return _regeneratorRuntime.awrap(this.executeAtom('get_text', [atomsElement]));
case 8:
return context$1$0.abrupt('return', context$1$0.sent);
case 9:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.getRect = function callee$0$0(el) {
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = _appiumSupport.util.unwrapElement(el);
if (!this.isWebContext()) {
context$1$0.next = 5;
break;
}
throw new _appiumBaseDriver.errors.NotYetImplementedError('Support for getRect for webcontext is not yet implemented. Please contact an Appium dev');
case 5:
context$1$0.next = 7;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/rect', 'GET'));
case 7:
return context$1$0.abrupt('return', context$1$0.sent);
case 8:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.getLocation = function callee$0$0(el) {
var atomsElement, rect;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = el.ELEMENT ? el.ELEMENT : el;
if (!this.isWebContext()) {
context$1$0.next = 10;
break;
}
context$1$0.next = 4;
return _regeneratorRuntime.awrap(this.useAtomsElement(el));
case 4:
atomsElement = context$1$0.sent;
context$1$0.next = 7;
return _regeneratorRuntime.awrap(this.executeAtom('get_top_left_coordinates', [atomsElement]));
case 7:
return context$1$0.abrupt('return', context$1$0.sent);
case 10:
context$1$0.next = 12;
return _regeneratorRuntime.awrap(this.getRect(el));
case 12:
rect = context$1$0.sent;
return context$1$0.abrupt('return', { x: rect.x, y: rect.y });
case 14:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.getLocationInView = function callee$0$0(el) {
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(this.getLocation(el));
case 2:
return context$1$0.abrupt('return', context$1$0.sent);
case 3:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.getSize = function callee$0$0(el) {
var atomsElement, rect;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = el.ELEMENT ? el.ELEMENT : el;
if (!this.isWebContext()) {
context$1$0.next = 12;
break;
}
atomsElement = this.getAtomsElement(el);
if (!(atomsElement === null)) {
context$1$0.next = 7;
break;
}
throw new _appiumBaseDriver.errors.UnknownError('Error converting element ID for using in WD atoms: \'' + el + '\'');
case 7:
context$1$0.next = 9;
return _regeneratorRuntime.awrap(this.executeAtom('get_size', [atomsElement]));
case 9:
return context$1$0.abrupt('return', context$1$0.sent);
case 10:
context$1$0.next = 16;
break;
case 12:
context$1$0.next = 14;
return _regeneratorRuntime.awrap(this.getRect(el));
case 14:
rect = context$1$0.sent;
return context$1$0.abrupt('return', { width: rect.width, height: rect.height });
case 16:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
function hasSpecialKeys(keys) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _getIterator(keys), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var char = _step.value;
if (isSpecialKey(char)) {
return true;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return false;
}
function isSpecialKey(k) {
if (k === '' || k === '') {
// BACKSPACE or DELETE
return true;
} else if (k === '' || k === '') {
// RETURN or ENTER
return true;
}
return false;
}
function translateKey(k) {
if (k === '' || k === '') {
// RETURN or ENTER
return '\n';
} else if (k === '' || k === '') {
// BACKSPACE or DELETE
return '\b';
}
return k;
}
extensions.bringUpKeyboard = function callee$0$0(element) {
var implicitWaitMs;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
var _this = this;
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
implicitWaitMs = this.implicitWaitMs;
context$1$0.next = 3;
return _regeneratorRuntime.awrap(this.setImplicitWait(0));
case 3:
context$1$0.prev = 3;
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _asyncbox.retryInterval)(10, 10, function callee$1$0() {
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.prev = 0;
context$2$0.next = 3;
return _regeneratorRuntime.awrap(this.findNativeElementOrElements('class name', 'XCUIElementTypeKeyboard', false));
case 3:
_logger2['default'].debug('Keyboard found. Continuing with text input.');
context$2$0.next = 13;
break;
case 6:
context$2$0.prev = 6;
context$2$0.t0 = context$2$0['catch'](0);
// no keyboard found
_logger2['default'].debug('No keyboard found. Clicking element to open it.');
context$2$0.next = 11;
return _regeneratorRuntime.awrap(this.nativeClick(element));
case 11:
context$2$0.next = 13;
return _regeneratorRuntime.awrap(this.findNativeElementOrElements('class name', 'XCUIElementTypeKeyboard', false));
case 13:
case 'end':
return context$2$0.stop();
}
}, null, _this, [[0, 6]]);
}));
case 6:
context$1$0.prev = 6;
context$1$0.next = 9;
return _regeneratorRuntime.awrap(this.setImplicitWait(implicitWaitMs));
case 9:
return context$1$0.finish(6);
case 10:
case 'end':
return context$1$0.stop();
}
}, null, this, [[3,, 6, 10]]);
};
commands.setValueImmediate = function callee$0$0(value, el) {
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
// WDA does not provide no way to set the value directly
_logger2['default'].info('There is currently no way to bypass typing using XCUITest. Setting value through keyboard');
context$1$0.next = 3;
return _regeneratorRuntime.awrap(this.setValue(value, el));
case 3:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
commands.setValue = function callee$0$0(value, el) {
var atomsElement, setFormattedValue, buffer, isFirstChar, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, k, char;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
var _this2 = this;
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = _appiumSupport.util.unwrapElement(el);
if (!this.isWebContext()) {
context$1$0.next = 9;
break;
}
atomsElement = this.useAtomsElement(el);
context$1$0.next = 5;
return _regeneratorRuntime.awrap(this.executeAtom('click', [atomsElement]));
case 5:
context$1$0.next = 7;
return _regeneratorRuntime.awrap(this.executeAtom('type', [atomsElement, value]));
case 7:
context$1$0.next = 54;
break;
case 9:
setFormattedValue = function setFormattedValue(input, isKeyboardPresenceCheckEnabled) {
return _regeneratorRuntime.async(function setFormattedValue$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (typeof input !== 'string' && !(input instanceof Array)) {
input = input.toString().split('');
}
context$2$0.prev = 1;
context$2$0.next = 4;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/value', 'POST', { value: input }));
case 4:
context$2$0.next = 23;
break;
case 6:
context$2$0.prev = 6;
context$2$0.t0 = context$2$0['catch'](1);
context$2$0.t1 = isKeyboardPresenceCheckEnabled;
if (!context$2$0.t1) {
context$2$0.next = 14;
break;
}
context$2$0.next = 12;
return _regeneratorRuntime.awrap(this.getAttribute('type', el));
case 12:
context$2$0.t2 = context$2$0.sent;
context$2$0.t1 = context$2$0.t2 === 'XCUIElementTypeTextField';
case 14:
if (!context$2$0.t1) {
context$2$0.next = 22;
break;
}
_logger2['default'].info('Cannot type in the text field because of ' + context$2$0.t0 + '.\nTrying to apply a workaround...');
context$2$0.next = 18;
return _regeneratorRuntime.awrap(this.bringUpKeyboard(el));
case 18:
context$2$0.next = 20;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/value', 'POST', { value: input }));
case 20:
context$2$0.next = 23;
break;
case 22:
throw context$2$0.t0;
case 23:
case 'end':
return context$2$0.stop();
}
}, null, _this2, [[1, 6]]);
};
// possible values of `value`:
// ['some text']
// ['s', 'o', 'm', 'e', ' ', 't', 'e', 'x', 't']
// 'some text'
if (typeof value === 'string') {
// plain string, so make it into an array of characters
value = value.toString().split('');
} else if (Array.isArray(value)) {
// make sure that all the strings inside are a single character long
value = _lodash2['default'].flatMap(value, function (v) {
return v.split('');
});
}
if (hasSpecialKeys(value)) {
context$1$0.next = 15;
break;
}
context$1$0.next = 14;
return _regeneratorRuntime.awrap(setFormattedValue(value, true));
case 14:
return context$1$0.abrupt('return');
case 15:
buffer = [];
isFirstChar = true;
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$1$0.prev = 20;
_iterator2 = _getIterator(value);
case 22:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$1$0.next = 37;
break;
}
k = _step2.value;
char = translateKey(k);
if (!(char === k)) {
context$1$0.next = 28;
break;
}
buffer.push(char);
return context$1$0.abrupt('continue', 34);
case 28:
context$1$0.next = 30;
return _regeneratorRuntime.awrap(setFormattedValue(buffer, isFirstChar));
case 30:
isFirstChar = false;
buffer = [];
// write the character
context$1$0.next = 34;
return _regeneratorRuntime.awrap(setFormattedValue([char], isFirstChar));
case 34:
_iteratorNormalCompletion2 = true;
context$1$0.next = 22;
break;
case 37:
context$1$0.next = 43;
break;
case 39:
context$1$0.prev = 39;
context$1$0.t0 = context$1$0['catch'](20);
_didIteratorError2 = true;
_iteratorError2 = context$1$0.t0;
case 43:
context$1$0.prev = 43;
context$1$0.prev = 44;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 46:
context$1$0.prev = 46;
if (!_didIteratorError2) {
context$1$0.next = 49;
break;
}
throw _iteratorError2;
case 49:
return context$1$0.finish(46);
case 50:
return context$1$0.finish(43);
case 51:
if (!buffer.length) {
context$1$0.next = 54;
break;
}
context$1$0.next = 54;
return _regeneratorRuntime.awrap(setFormattedValue(buffer, false));
case 54:
case 'end':
return context$1$0.stop();
}
}, null, this, [[20, 39, 43, 51], [44,, 46, 50]]);
};
commands.keys = function callee$0$0(value) {
var buffer, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, k, char;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (_lodash2['default'].isArray(value)) {
// concatenate any individual strings
value = value.join('');
}
if (_lodash2['default'].isString(value)) {
// split into component characters
value = value.split('');
}
buffer = [];
_iteratorNormalCompletion3 = true;
_didIteratorError3 = false;
_iteratorError3 = undefined;
context$1$0.prev = 6;
for (_iterator3 = _getIterator(value); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
k = _step3.value;
char = translateKey(k);
buffer.push(char);
}
context$1$0.next = 14;
break;
case 10:
context$1$0.prev = 10;
context$1$0.t0 = context$1$0['catch'](6);
_didIteratorError3 = true;
_iteratorError3 = context$1$0.t0;
case 14:
context$1$0.prev = 14;
context$1$0.prev = 15;
if (!_iteratorNormalCompletion3 && _iterator3['return']) {
_iterator3['return']();
}
case 17:
context$1$0.prev = 17;
if (!_didIteratorError3) {
context$1$0.next = 20;
break;
}
throw _iteratorError3;
case 20:
return context$1$0.finish(17);
case 21:
return context$1$0.finish(14);
case 22:
context$1$0.next = 24;
return _regeneratorRuntime.awrap(this.proxyCommand('/wda/keys', 'POST', { value: buffer }));
case 24:
case 'end':
return context$1$0.stop();
}
}, null, this, [[6, 10, 14, 22], [15,, 17, 21]]);
};
commands.clear = function callee$0$0(el) {
var atomsElement;
return _regeneratorRuntime.async(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
el = _appiumSupport.util.unwrapElement(el);
if (!this.isWebContext()) {
context$1$0.next = 6;
break;
}
atomsElement = this.useAtomsElement(el);
context$1$0.next = 5;
return _regeneratorRuntime.awrap(this.executeAtom('clear', [atomsElement]));
case 5:
return context$1$0.abrupt('return');
case 6:
context$1$0.next = 8;
return _regeneratorRuntime.awrap(this.proxyCommand('/element/' + el + '/clear', 'POST'));
case 8:
case 'end':
return context$1$0.stop();
}
}, null, this);
};
_Object$assign(extensions, commands);
exports.commands = commands;
exports['default'] = extensions;
// sometimes input is attempted before we have a keyboard. Try to bring one up
// but we want to handle the retries on find
// no matter what we do, make sure we have the implicit wait set up correctly
// make sure there is a keyboard if this is a text field
// nothing special, so just send it in
// if there are special characters, go through the value until we get to one,
// and then print it individually
// currently only supporting return, enter, backspace, and delete
// write and clear the buffer
// finally, send anything that might be left
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9jb21tYW5kcy9lbGVtZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O3NCQUFjLFFBQVE7Ozs7Z0NBQ0Msb0JBQW9COzsrQkFDZixtQkFBbUI7OzZCQUMxQixnQkFBZ0I7O3dCQUNQLFVBQVU7O3NCQUN4QixXQUFXOzs7O0FBRzNCLElBQUksUUFBUSxHQUFHLEVBQUU7SUFBRSxVQUFVLEdBQUcsRUFBRSxDQUFDO0FBQ25DLGVBQWMsVUFBVSxFQUFFLDZCQUFZLE9BQU8sQ0FBQyxDQUFDOztBQUUvQyxRQUFRLENBQUMsWUFBWSxHQUFHLG9CQUFnQixTQUFTLEVBQUUsRUFBRTtNQUsvQyxZQUFZOzs7O0FBSmhCLFVBQUUsR0FBRyxvQkFBSyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7O1lBQ3ZCLElBQUksQ0FBQyxZQUFZLEVBQUU7Ozs7Ozt5Q0FDVCxJQUFJLENBQUMsWUFBWSxlQUFhLEVBQUUsbUJBQWMsU0FBUyxFQUFJLEtBQUssQ0FBQzs7Ozs7O0FBRTVFLG9CQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7O2FBQ3ZDLG9CQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUM7Ozs7O2NBQ2xCLElBQUkseUJBQU8sWUFBWSwyREFBd0QsRUFBRSxDQUFHOzs7O3lDQUU3RSxJQUFJLENBQUMsV0FBVyxDQUFDLHFCQUFxQixFQUFFLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDOzs7Ozs7Ozs7O0NBRWxGLENBQUM7O0FBRUYsUUFBUSxDQUFDLE9BQU8sR0FBRyxvQkFBZ0IsRUFBRTtNQUsvQixZQUFZOzs7O0FBSmhCLFVBQUUsR0FBRyxvQkFBSyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7O1lBQ3ZCLElBQUksQ0FBQyxZQUFZLEVBQUU7Ozs7Ozt5Q0FDVCxJQUFJLENBQUMsWUFBWSxlQUFhLEVBQUUsWUFBUyxLQUFLLENBQUM7Ozs7OztBQUUxRCxvQkFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLENB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ckIsZUFBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDekI7O0FBRUcsY0FBTSxHQUFHLEVBQUU7Ozs7OztBQUNmLHVDQUFjLEtBQUsseUdBQUU7QUFBWixXQUFDO0FBQ0osY0FBSSxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUM7O0FBRTFCLGdCQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ25COzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7eUNBQ0ssSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDOzs7Ozs7O0NBQzlELENBQUM7O0FBRUYsUUFBUSxDQUFDLEtBQUssR0FBRyxvQkFBZ0IsRUFBRTtNQUczQixZQUFZOzs7O0FBRmxCLFVBQUUsR0FBRyxvQkFBSyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7O2FBQ3hCLElBQUksQ0FBQyxZQUFZLEVBQUU7Ozs7O0FBQ2pCLG9CQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7O3lDQUNyQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDOzs7Ozs7O3lDQUczQyxJQUFJLENBQUMsWUFBWSxlQUFhLEVBQUUsYUFBVSxNQUFNLENBQUM7Ozs7Ozs7Q0FDeEQsQ0FBQzs7QUFHRixlQUFjLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMzQixRQUFRLEdBQVIsUUFBUTtxQkFDRixVQUFVIiwiZmlsZSI6ImxpYi9jb21tYW5kcy9lbGVtZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IGVycm9ycyB9IGZyb20gJ2FwcGl1bS1iYXNlLWRyaXZlcic7XG5pbXBvcnQgeyBpb3NDb21tYW5kcyB9IGZyb20gJ2FwcGl1bS1pb3MtZHJpdmVyJztcbmltcG9ydCB7IHV0aWwgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgeyByZXRyeUludGVydmFsIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXInO1xuXG5cbmxldCBjb21tYW5kcyA9IHt9LCBleHRlbnNpb25zID0ge307XG5PYmplY3QuYXNzaWduKGV4dGVuc2lvbnMsIGlvc0NvbW1hbmRzLmVsZW1lbnQpO1xuXG5jb21tYW5kcy5nZXRBdHRyaWJ1dGUgPSBhc3luYyBmdW5jdGlvbiAoYXR0cmlidXRlLCBlbCkge1xuICBlbCA9IHV0aWwudW53cmFwRWxlbWVudChlbCk7XG4gIGlmICghdGhpcy5pc1dlYkNvbnRleHQoKSkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL2VsZW1lbnQvJHtlbH0vYXR0cmlidXRlLyR7YXR0cmlidXRlfWAsICdHRVQnKTtcbiAgfVxuICBsZXQgYXRvbXNFbGVtZW50ID0gdGhpcy5nZXRBdG9tc0VsZW1lbnQoZWwpO1xuICBpZiAoXy5pc051bGwoYXRvbXNFbGVtZW50KSkge1xuICAgIHRocm93IG5ldyBlcnJvcnMuVW5rbm93bkVycm9yKGBFcnJvciBjb252ZXJ0aW5nIGVsZW1lbnQgSUQgZm9yIHVzaW5nIGluIFdEIGF0b21zOiAnJHtlbH1gKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlQXRvbSgnZ2V0X2F0dHJpYnV0ZV92YWx1ZScsIFthdG9tc0VsZW1lbnQsIGF0dHJpYnV0ZV0pO1xuICB9XG59O1xuXG5jb21tYW5kcy5nZXRUZXh0ID0gYXN5bmMgZnVuY3Rpb24gKGVsKSB7XG4gIGVsID0gdXRpbC51bndyYXBFbGVtZW50KGVsKTtcbiAgaWYgKCF0aGlzLmlzV2ViQ29udGV4dCgpKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvZWxlbWVudC8ke2VsfS90ZXh0YCwgJ0dFVCcpO1xuICB9XG4gIGxldCBhdG9tc0VsZW1lbnQgPSB0aGlzLnVzZUF0b21zRWxlbWVudChlbCk7XG4gIHJldHVybiBhd2FpdCB0aGlzLmV4ZWN1dGVBdG9tKCdnZXRfdGV4dCcsIFthdG9tc0VsZW1lbnRdKTtcbn07XG5cbmNvbW1hbmRzLmdldFJlY3QgPSBhc3luYyBmdW5jdGlvbiAoZWwpIHtcbiAgZWwgPSB1dGlsLnVud3JhcEVsZW1lbnQoZWwpO1xuICBpZiAodGhpcy5pc1dlYkNvbnRleHQoKSkge1xuICAgIHRocm93IG5ldyBlcnJvcnMuTm90WWV0SW1wbGVtZW50ZWRFcnJvcignU3VwcG9ydCBmb3IgZ2V0UmVjdCBmb3Igd2ViY29udGV4dCBpcyBub3QgeWV0IGltcGxlbWVudGVkLiBQbGVhc2UgY29udGFjdCBhbiBBcHBpdW0gZGV2Jyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvZWxlbWVudC8ke2VsfS9yZWN0YCwgJ0dFVCcpO1xuICB9XG59O1xuXG5jb21tYW5kcy5nZXRMb2NhdGlvbiA9IGFzeW5jIGZ1bmN0aW9uIChlbCkge1xuICBlbCA9IGVsLkVMRU1FTlQgPyBlbC5FTEVNRU5UIDogZWw7XG4gIGlmICh0aGlzLmlzV2ViQ29udGV4dCgpKSB7XG4gICAgbGV0IGF0b21zRWxlbWVudCA9IGF3YWl0IHRoaXMudXNlQXRvbXNFbGVtZW50KGVsKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlQXRvbSgnZ2V0X3RvcF9sZWZ0X2Nvb3JkaW5hdGVzJywgW2F0b21zRWxlbWVudF0pO1xuICB9IGVsc2Uge1xuICAgIGxldCByZWN0ID0gYXdhaXQgdGhpcy5nZXRSZWN0KGVsKTtcbiAgICByZXR1cm4ge3g6IHJlY3QueCwgeTogcmVjdC55fTtcbiAgfVxufTtcblxuY29tbWFuZHMuZ2V0TG9jYXRpb25JblZpZXcgPSBhc3luYyBmdW5jdGlvbiAoZWwpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0TG9jYXRpb24oZWwpO1xufTtcblxuY29tbWFuZHMuZ2V0U2l6ZSA9IGFzeW5jIGZ1bmN0aW9uIChlbCkge1xuICBlbCA9IGVsLkVMRU1FTlQgPyBlbC5FTEVNRU5UIDogZWw7XG4gIGlmICh0aGlzLmlzV2ViQ29udGV4dCgpKSB7XG4gICAgbGV0IGF0b21zRWxlbWVudCA9IHRoaXMuZ2V0QXRvbXNFbGVtZW50KGVsKTtcbiAgICBpZiAoYXRvbXNFbGVtZW50ID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlVua25vd25FcnJvcihgRXJyb3IgY29udmVydGluZyBlbGVtZW50IElEIGZvciB1c2luZyBpbiBXRCBhdG9tczogJyR7ZWx9J2ApO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlQXRvbSgnZ2V0X3NpemUnLCBbYXRvbXNFbGVtZW50XSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGxldCByZWN0ID0gYXdhaXQgdGhpcy5nZXRSZWN0KGVsKTtcbiAgICByZXR1cm4ge3dpZHRoOiByZWN0LndpZHRoLCBoZWlnaHQ6IHJlY3QuaGVpZ2h0fTtcbiAgfVxufTtcblxuZnVuY3Rpb24gaGFzU3BlY2lhbEtleXMgKGtleXMpIHtcbiAgZm9yIChsZXQgY2hhciBvZiBrZXlzKSB7XG4gICAgaWYgKGlzU3BlY2lhbEtleShjaGFyKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNTcGVjaWFsS2V5IChrKSB7XG4gIGlmIChrID09PSAnXFx1RTAwMycgfHwgayA9PT0gJ1xcdWUwMTcnKSB7IC8vIEJBQ0tTUEFDRSBvciBERUxFVEVcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChrID09PSAnXFx1RTAwNicgfHwgayA9PT0gJ1xcdUUwMDcnKSB7IC8vIFJFVFVSTiBvciBFTlRFUlxuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlS2V5IChrKSB7XG4gIGlmIChrID09PSAnXFx1RTAwNicgfHwgayA9PT0gJ1xcdUUwMDcnKSB7IC8vIFJFVFVSTiBvciBFTlRFUlxuICAgIHJldHVybiAnXFxuJztcbiAgfSBlbHNlIGlmIChrID09PSAnXFx1RTAwMycgfHwgayA9PT0gJ1xcdWUwMTcnKSB7IC8vIEJBQ0tTUEFDRSBvciBERUxFVEVcbiAgICByZXR1cm4gJ1xcYic7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5cbmV4dGVuc2lvbnMuYnJpbmdVcEtleWJvYXJkID0gYXN5bmMgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgLy8gc29tZXRpbWVzIGlucHV0IGlzIGF0dGVtcHRlZCBiZWZvcmUgd2UgaGF2ZSBhIGtleWJvYXJkLiBUcnkgdG8gYnJpbmcgb25lIHVwXG4gIC8vIGJ1dCB3ZSB3YW50IHRvIGhhbmRsZSB0aGUgcmV0cmllcyBvbiBmaW5kXG4gIGxldCBpbXBsaWNpdFdhaXRNcyA9IHRoaXMuaW1wbGljaXRXYWl0TXM7XG4gIGF3YWl0IHRoaXMuc2V0SW1wbGljaXRXYWl0KDApO1xuICB0cnkge1xuICAgIGF3YWl0IHJldHJ5SW50ZXJ2YWwoMTAsIDEwLCBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cygnY2xhc3MgbmFtZScsICdYQ1VJRWxlbWVudFR5cGVLZXlib2FyZCcsIGZhbHNlKTtcbiAgICAgICAgbG9nLmRlYnVnKCdLZXlib2FyZCBmb3VuZC4gQ29udGludWluZyB3aXRoIHRleHQgaW5wdXQuJyk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgLy8gbm8ga2V5Ym9hcmQgZm91bmRcbiAgICAgICAgbG9nLmRlYnVnKCdObyBrZXlib2FyZCBmb3VuZC4gQ2xpY2tpbmcgZWxlbWVudCB0byBvcGVuIGl0LicpO1xuICAgICAgICBhd2FpdCB0aGlzLm5hdGl2ZUNsaWNrKGVsZW1lbnQpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZmluZE5hdGl2ZUVsZW1lbnRPckVsZW1lbnRzKCdjbGFzcyBuYW1lJywgJ1hDVUlFbGVtZW50VHlwZUtleWJvYXJkJywgZmFsc2UpO1xuICAgICAgfVxuICAgIH0pO1xuICB9IGZpbmFsbHkge1xuICAgIC8vIG5vIG1hdHRlciB3aGF0IHdlIGRvLCBtYWtlIHN1cmUgd2UgaGF2ZSB0aGUgaW1wbGljaXQgd2FpdCBzZXQgdXAgY29ycmVjdGx5XG4gICAgYXdhaXQgdGhpcy5zZXRJbXBsaWNpdFdhaXQoaW1wbGljaXRXYWl0TXMpO1xuICB9XG59O1xuXG5jb21tYW5kcy5zZXRWYWx1ZUltbWVkaWF0ZSA9IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSwgZWwpIHtcbiAgLy8gV0RBIGRvZXMgbm90IHByb3ZpZGUgbm8gd2F5IHRvIHNldCB0aGUgdmFsdWUgZGlyZWN0bHlcbiAgbG9nLmluZm8oJ1RoZXJlIGlzIGN1cnJlbnRseSBubyB3YXkgdG8gYnlwYXNzIHR5cGluZyB1c2luZyBYQ1VJVGVzdC4gU2V0dGluZyB2YWx1ZSB0aHJvdWdoIGtleWJvYXJkJyk7XG4gIGF3YWl0IHRoaXMuc2V0VmFsdWUodmFsdWUsIGVsKTtcbn07XG5cbmNvbW1hbmRzLnNldFZhbHVlID0gYXN5bmMgZnVuY3Rpb24gKHZhbHVlLCBlbCkge1xuICBlbCA9IHV0aWwudW53cmFwRWxlbWVudChlbCk7XG4gIGlmICh0aGlzLmlzV2ViQ29udGV4dCgpKSB7XG4gICAgbGV0IGF0b21zRWxlbWVudCA9IHRoaXMudXNlQXRvbXNFbGVtZW50KGVsKTtcbiAgICBhd2FpdCB0aGlzLmV4ZWN1dGVBdG9tKCdjbGljaycsIFthdG9tc0VsZW1lbnRdKTtcbiAgICBhd2FpdCB0aGlzLmV4ZWN1dGVBdG9tKCd0eXBlJywgW2F0b21zRWxlbWVudCwgdmFsdWVdKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBzZXRGb3JtYXR0ZWRWYWx1ZSA9IGFzeW5jIChpbnB1dCwgaXNLZXlib2FyZFByZXNlbmNlQ2hlY2tFbmFibGVkKSA9PiB7XG4gICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJyAmJiAhKGlucHV0IGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIGlucHV0ID0gaW5wdXQudG9TdHJpbmcoKS5zcGxpdCgnJyk7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL2VsZW1lbnQvJHtlbH0vdmFsdWVgLCAnUE9TVCcsIHt2YWx1ZTogaW5wdXR9KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBtYWtlIHN1cmUgdGhlcmUgaXMgYSBrZXlib2FyZCBpZiB0aGlzIGlzIGEgdGV4dCBmaWVsZFxuICAgICAgICBpZiAoaXNLZXlib2FyZFByZXNlbmNlQ2hlY2tFbmFibGVkICYmIGF3YWl0IHRoaXMuZ2V0QXR0cmlidXRlKCd0eXBlJywgZWwpID09PSAnWENVSUVsZW1lbnRUeXBlVGV4dEZpZWxkJykge1xuICAgICAgICAgIGxvZy5pbmZvKGBDYW5ub3QgdHlwZSBpbiB0aGUgdGV4dCBmaWVsZCBiZWNhdXNlIG9mICR7ZXJyfS5cXG5UcnlpbmcgdG8gYXBwbHkgYSB3b3JrYXJvdW5kLi4uYCk7XG4gICAgICAgICAgYXdhaXQgdGhpcy5icmluZ1VwS2V5Ym9hcmQoZWwpO1xuICAgICAgICAgIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvZWxlbWVudC8ke2VsfS92YWx1ZWAsICdQT1NUJywge3ZhbHVlOiBpbnB1dH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBwb3NzaWJsZSB2YWx1ZXMgb2YgYHZhbHVlYDpcbiAgICAvLyAgIFsnc29tZSB0ZXh0J11cbiAgICAvLyAgIFsncycsICdvJywgJ20nLCAnZScsICcgJywgJ3QnLCAnZScsICd4JywgJ3QnXVxuICAgIC8vICAgJ3NvbWUgdGV4dCdcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgLy8gcGxhaW4gc3RyaW5nLCBzbyBtYWtlIGl0IGludG8gYW4gYXJyYXkgb2YgY2hhcmFjdGVyc1xuICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpLnNwbGl0KCcnKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAvLyBtYWtlIHN1cmUgdGhhdCBhbGwgdGhlIHN0cmluZ3MgaW5zaWRlIGFyZSBhIHNpbmdsZSBjaGFyYWN0ZXIgbG9uZ1xuICAgICAgdmFsdWUgPSBfLmZsYXRNYXAodmFsdWUsICh2KSA9PiB2LnNwbGl0KCcnKSk7XG4gICAgfVxuXG4gICAgaWYgKCFoYXNTcGVjaWFsS2V5cyh2YWx1ZSkpIHtcbiAgICAgIC8vIG5vdGhpbmcgc3BlY2lhbCwgc28ganVzdCBzZW5kIGl0IGluXG4gICAgICBhd2FpdCBzZXRGb3JtYXR0ZWRWYWx1ZSh2YWx1ZSwgdHJ1ZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgYXJlIHNwZWNpYWwgY2hhcmFjdGVycywgZ28gdGhyb3VnaCB0aGUgdmFsdWUgdW50aWwgd2UgZ2V0IHRvIG9uZSxcbiAgICAvLyBhbmQgdGhlbiBwcmludCBpdCBpbmRpdmlkdWFsbHlcbiAgICAvLyBjdXJyZW50bHkgb25seSBzdXBwb3J0aW5nIHJldHVybiwgZW50ZXIsIGJhY2tzcGFjZSwgYW5kIGRlbGV0ZVxuICAgIGxldCBidWZmZXIgPSBbXTtcbiAgICBsZXQgaXNGaXJzdENoYXIgPSB0cnVlO1xuICAgIGZvciAobGV0IGsgb2YgdmFsdWUpIHtcbiAgICAgIGxldCBjaGFyID0gdHJhbnNsYXRlS2V5KGspO1xuXG4gICAgICBpZiAoY2hhciA9PT0gaykge1xuICAgICAgICBidWZmZXIucHVzaChjaGFyKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIHdyaXRlIGFuZCBjbGVhciB0aGUgYnVmZmVyXG4gICAgICBhd2FpdCBzZXRGb3JtYXR0ZWRWYWx1ZShidWZmZXIsIGlzRmlyc3RDaGFyKTtcbiAgICAgIGlzRmlyc3RDaGFyID0gZmFsc2U7XG4gICAgICBidWZmZXIgPSBbXTtcblxuICAgICAgLy8gd3JpdGUgdGhlIGNoYXJhY3RlclxuICAgICAgYXdhaXQgc2V0Rm9ybWF0dGVkVmFsdWUoW2NoYXJdLCBpc0ZpcnN0Q2hhcik7XG4gICAgfVxuICAgIC8vIGZpbmFsbHksIHNlbmQgYW55dGhpbmcgdGhhdCBtaWdodCBiZSBsZWZ0XG4gICAgaWYgKGJ1ZmZlci5sZW5ndGgpIHtcbiAgICAgIGF3YWl0IHNldEZvcm1hdHRlZFZhbHVlKGJ1ZmZlciwgZmFsc2UpO1xuICAgIH1cbiAgfVxufTtcblxuY29tbWFuZHMua2V5cyA9IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBpZiAoXy5pc0FycmF5KHZhbHVlKSkge1xuICAgIC8vIGNvbmNhdGVuYXRlIGFueSBpbmRpdmlkdWFsIHN0cmluZ3NcbiAgICB2YWx1ZSA9IHZhbHVlLmpvaW4oJycpO1xuICB9XG4gIGlmIChfLmlzU3RyaW5nKHZhbHVlKSkge1xuICAgIC8vIHNwbGl0IGludG8gY29tcG9uZW50IGNoYXJhY3RlcnNcbiAgICB2YWx1ZSA9IHZhbHVlLnNwbGl0KCcnKTtcbiAgfVxuXG4gIGxldCBidWZmZXIgPSBbXTtcbiAgZm9yIChsZXQgayBvZiB2YWx1ZSkge1xuICAgIGxldCBjaGFyID0gdHJhbnNsYXRlS2V5KGspO1xuXG4gICAgYnVmZmVyLnB1c2goY2hhcik7XG4gIH1cbiAgYXdhaXQgdGhpcy5wcm94eUNvbW1hbmQoJy93ZGEva2V5cycsICdQT1NUJywge3ZhbHVlOiBidWZmZXJ9KTtcbn07XG5cbmNvbW1hbmRzLmNsZWFyID0gYXN5bmMgZnVuY3Rpb24gKGVsKSB7XG4gIGVsID0gdXRpbC51bndyYXBFbGVtZW50KGVsKTtcbiAgaWYgKHRoaXMuaXNXZWJDb250ZXh0KCkpIHtcbiAgICBsZXQgYXRvbXNFbGVtZW50ID0gdGhpcy51c2VBdG9tc0VsZW1lbnQoZWwpO1xuICAgIGF3YWl0IHRoaXMuZXhlY3V0ZUF0b20oJ2NsZWFyJywgW2F0b21zRWxlbWVudF0pO1xuICAgIHJldHVybjtcbiAgfVxuICBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL2VsZW1lbnQvJHtlbH0vY2xlYXJgLCAnUE9TVCcpO1xufTtcblxuXG5PYmplY3QuYXNzaWduKGV4dGVuc2lvbnMsIGNvbW1hbmRzKTtcbmV4cG9ydCB7IGNvbW1hbmRzIH07XG5leHBvcnQgZGVmYXVsdCBleHRlbnNpb25zO1xuIl0sInNvdXJjZVJvb3QiOiIuLi8uLi8uLiJ9