UNPKG

appium-xcuitest-driver-conan

Version:

Appium driver for iOS using XCUITest for backend

698 lines (546 loc) 38.3 kB
'use strict'; 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