UNPKG

appium-xcuitest-driver-conan

Version:

Appium driver for iOS using XCUITest for backend

1,210 lines (986 loc) 88.3 kB
'use strict'; var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default']; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _Object$assign = require('babel-runtime/core-js/object/assign')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _appiumBaseDriver = require('appium-base-driver'); var _appiumSupport = require('appium-support'); var _appiumIosDriver = require('appium-ios-driver'); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _logger = require('../logger'); var _logger2 = _interopRequireDefault(_logger); var helpers = {}, extensions = {}, commands = {}; commands.moveTo = _appiumIosDriver.iosCommands.gesture.moveTo; commands.click = 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: if (this.isWebContext()) { context$1$0.next = 4; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.nativeClick(el)); case 3: return context$1$0.abrupt('return', context$1$0.sent); case 4: el = _appiumSupport.util.unwrapElement(el); if (!(this.opts.nativeWebTap && !this.isRealDevice())) { context$1$0.next = 10; break; } context$1$0.next = 8; return _regeneratorRuntime.awrap(this.nativeWebTap(el)); case 8: context$1$0.next = 14; break; case 10: atomsElement = this.useAtomsElement(el); context$1$0.next = 13; return _regeneratorRuntime.awrap(this.executeAtom('click', [atomsElement])); case 13: return context$1$0.abrupt('return', context$1$0.sent); case 14: case 'end': return context$1$0.stop(); } }, null, this); }; function isSameGestures(gestures, candidates) { try { if (gestures.length !== candidates.length) { return false; } for (var i = 0; i < gestures.length; i++) { var gestureObj = gestures[i]; var candidateObj = candidates[i]; if (!_lodash2['default'].isPlainObject(gestureObj) || !_lodash2['default'].isPlainObject(candidateObj)) { return false; } if (_lodash2['default'].difference(_lodash2['default'].keys(candidateObj), _lodash2['default'].keys(gestureObj)).length) { return false; } if (gestureObj.action.toLowerCase() !== candidateObj.action.toLowerCase()) { return false; } if (candidateObj.options && gestureObj.options.count !== candidateObj.options.count) { return false; } } } catch (err) { _logger2['default'].debug('Error "' + err.message + '" while comparing gestures. Considering them as not equal'); return false; } return true; } function gesturesChainToString(gestures) { var keysToInclude = arguments.length <= 1 || arguments[1] === undefined ? ['options'] : arguments[1]; return gestures.map(function (item) { var otherKeys = _lodash2['default'].difference(_lodash2['default'].keys(item), ['action']); otherKeys = _lodash2['default'].isArray(keysToInclude) ? _lodash2['default'].intersection(otherKeys, keysToInclude) : otherKeys; if (otherKeys.length) { return '' + item.action + ('(' + _lodash2['default'].map(otherKeys, function (x) { return x + '=' + (_lodash2['default'].isPlainObject(item[x]) ? JSON.stringify(item[x]) : item[x]); }).join(', ') + ')'); } return item.action; }).join('-'); } commands.performTouch = function callee$0$0(gestures) { var supportedGesturesMapping, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step$value, cmd, info, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, candidateMatch, availableGestures, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _step2$value, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4; 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: _logger2['default'].debug('Received the following touch action: ' + gesturesChainToString(gestures)); supportedGesturesMapping = { doubleTap: { handler: function handler(x) { return _regeneratorRuntime.async(function handler$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.handleDoubleTap(x)); case 2: case 'end': return context$2$0.stop(); } }, null, _this); }, matches: [[{ action: 'doubletap' }], [{ action: 'tap', options: { count: 2 } }]] }, tap: { handler: function handler(x) { return _regeneratorRuntime.async(function handler$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.handleTap(x[0])); case 2: case 'end': return context$2$0.stop(); } }, null, _this); }, matches: [[{ action: 'tap' }], [{ action: 'tap' }, { action: 'release' }], [{ action: 'press' }, { action: 'release' }]] }, longPress: { handler: function handler(x) { return _regeneratorRuntime.async(function handler$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.handleLongPress(x)); case 2: case 'end': return context$2$0.stop(); } }, null, _this); }, matches: [[{ action: 'longpress' }], [{ action: 'press' }, { action: 'wait' }, { action: 'release' }]] }, drag: { handler: function handler(x) { return _regeneratorRuntime.async(function handler$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.handleDrag(x)); case 2: case 'end': return context$2$0.stop(); } }, null, _this); }, matches: [[{ action: 'press' }, { action: 'wait' }, { action: 'moveTo' }, { action: 'release' }]] }, scroll: { handler: function handler(x) { return _regeneratorRuntime.async(function handler$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.handleScroll(x)); case 2: case 'end': return context$2$0.stop(); } }, null, _this); }, matches: [[{ action: 'press' }, { action: 'moveTo' }, { action: 'release' }]] } }; _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; context$1$0.prev = 5; _iterator = _getIterator(_lodash2['default'].toPairs(supportedGesturesMapping)); case 7: if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { context$1$0.next = 43; break; } _step$value = _slicedToArray(_step.value, 2); cmd = _step$value[0]; info = _step$value[1]; _iteratorNormalCompletion3 = true; _didIteratorError3 = false; _iteratorError3 = undefined; context$1$0.prev = 14; _iterator3 = _getIterator(info.matches); case 16: if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) { context$1$0.next = 26; break; } candidateMatch = _step3.value; if (!isSameGestures(gestures, candidateMatch)) { context$1$0.next = 23; break; } _logger2['default'].debug('Found matching gesture: ' + cmd); context$1$0.next = 22; return _regeneratorRuntime.awrap(info.handler(gestures)); case 22: return context$1$0.abrupt('return', context$1$0.sent); case 23: _iteratorNormalCompletion3 = true; context$1$0.next = 16; break; case 26: context$1$0.next = 32; break; case 28: context$1$0.prev = 28; context$1$0.t0 = context$1$0['catch'](14); _didIteratorError3 = true; _iteratorError3 = context$1$0.t0; case 32: context$1$0.prev = 32; context$1$0.prev = 33; if (!_iteratorNormalCompletion3 && _iterator3['return']) { _iterator3['return'](); } case 35: context$1$0.prev = 35; if (!_didIteratorError3) { context$1$0.next = 38; break; } throw _iteratorError3; case 38: return context$1$0.finish(35); case 39: return context$1$0.finish(32); case 40: _iteratorNormalCompletion = true; context$1$0.next = 7; break; case 43: context$1$0.next = 49; break; case 45: context$1$0.prev = 45; context$1$0.t1 = context$1$0['catch'](5); _didIteratorError = true; _iteratorError = context$1$0.t1; case 49: context$1$0.prev = 49; context$1$0.prev = 50; if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } case 52: context$1$0.prev = 52; if (!_didIteratorError) { context$1$0.next = 55; break; } throw _iteratorError; case 55: return context$1$0.finish(52); case 56: return context$1$0.finish(49); case 57: availableGestures = ''; _iteratorNormalCompletion2 = true; _didIteratorError2 = false; _iteratorError2 = undefined; context$1$0.prev = 61; _iterator2 = _getIterator(_lodash2['default'].toPairs(supportedGesturesMapping)); case 63: if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) { context$1$0.next = 90; break; } _step2$value = _slicedToArray(_step2.value, 2); cmd = _step2$value[0]; info = _step2$value[1]; availableGestures += '\t' + cmd + ': '; _iteratorNormalCompletion4 = true; _didIteratorError4 = false; _iteratorError4 = undefined; context$1$0.prev = 71; for (_iterator4 = _getIterator(info.matches); !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { candidateMatch = _step4.value; availableGestures += '\t\t' + gesturesChainToString(candidateMatch) + '\n'; } context$1$0.next = 79; break; case 75: context$1$0.prev = 75; context$1$0.t2 = context$1$0['catch'](71); _didIteratorError4 = true; _iteratorError4 = context$1$0.t2; case 79: context$1$0.prev = 79; context$1$0.prev = 80; if (!_iteratorNormalCompletion4 && _iterator4['return']) { _iterator4['return'](); } case 82: context$1$0.prev = 82; if (!_didIteratorError4) { context$1$0.next = 85; break; } throw _iteratorError4; case 85: return context$1$0.finish(82); case 86: return context$1$0.finish(79); case 87: _iteratorNormalCompletion2 = true; context$1$0.next = 63; break; case 90: context$1$0.next = 96; break; case 92: context$1$0.prev = 92; context$1$0.t3 = context$1$0['catch'](61); _didIteratorError2 = true; _iteratorError2 = context$1$0.t3; case 96: context$1$0.prev = 96; context$1$0.prev = 97; if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } case 99: context$1$0.prev = 99; if (!_didIteratorError2) { context$1$0.next = 102; break; } throw _iteratorError2; case 102: return context$1$0.finish(99); case 103: return context$1$0.finish(96); case 104: throw new _appiumBaseDriver.errors.NotYetImplementedError('Support for ' + gesturesChainToString(gestures) + ' gesture is not implemented. ' + 'Try to use "mobile: *" interface to workaround the issue. ' + ('Only these gestures are supported:\n' + availableGestures)); case 105: case 'end': return context$1$0.stop(); } }, null, this, [[5, 45, 49, 57], [14, 28, 32, 40], [33,, 35, 39], [50,, 52, 56], [61, 92, 96, 104], [71, 75, 79, 87], [80,, 82, 86], [97,, 99, 103]]); }; commands.performMultiAction = function callee$0$0(actions) { var i; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _logger2['default'].debug('Received the following multi touch action:'); for (i in actions) { _logger2['default'].debug(' ' + (i + 1) + ': ' + _lodash2['default'].map(actions[i], 'action').join('-')); } if (!isPinchOrZoom(actions)) { context$1$0.next = 6; break; } context$1$0.next = 5; return _regeneratorRuntime.awrap(this.handlePinchOrZoom(actions)); case 5: return context$1$0.abrupt('return', context$1$0.sent); case 6: throw new _appiumBaseDriver.errors.NotYetImplementedError('Support for this multi-action is not implemented. Try to use "mobile: *" interface to workaround the issue.'); case 7: case 'end': return context$1$0.stop(); } }, null, this); }; commands.nativeClick = function callee$0$0(el) { var endpoint; 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); endpoint = '/element/' + el + '/click'; context$1$0.next = 4; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST', {})); case 4: return context$1$0.abrupt('return', context$1$0.sent); case 5: case 'end': return context$1$0.stop(); } }, null, this); }; function isScroll(gestures) { if (gestures.length === 3 && gestures[0].action === 'press' && gestures[1].action === 'moveTo' && gestures[2].action === 'release') { return true; } return false; } function isPinchOrZoom() { var actions = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; // symmetric two-finger action consisting of press-moveto-release if (actions.length === 2) { if (actions[0].length === 3 && actions[1].length === 3) { return _lodash2['default'].every(actions, function (gestures) { return isScroll(gestures); }); } } return false; } helpers.handleScroll = function callee$0$0(gestures) { var dragGestures; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (!gestures[1].options.element) { context$1$0.next = 4; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.mobileScroll({ element: gestures[1].options.element, toVisible: true })); case 3: return context$1$0.abrupt('return', context$1$0.sent); case 4: dragGestures = [gestures[0], { action: 'wait', options: { ms: 0 } }, gestures[1], gestures[2]]; context$1$0.next = 7; return _regeneratorRuntime.awrap(this.handleDrag(dragGestures)); case 7: return context$1$0.abrupt('return', context$1$0.sent); case 8: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.handleDrag = function callee$0$0(gestures) { var press, wait, moveTo, pressCoordinates, duration, moveToCoordinates, params, endpoint; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: press = gestures[0]; wait = gestures[1]; moveTo = gestures[2]; context$1$0.next = 5; return _regeneratorRuntime.awrap(this.getCoordinates(press)); case 5: pressCoordinates = context$1$0.sent; duration = parseInt(wait.options.ms, 10) / 1000; context$1$0.next = 9; return _regeneratorRuntime.awrap(this.getCoordinates(moveTo)); case 9: moveToCoordinates = context$1$0.sent; // update moveTo coordinates with offset moveToCoordinates = this.applyMoveToOffset(pressCoordinates, moveToCoordinates); // build drag command params = {}; params.fromX = pressCoordinates.x; params.fromY = pressCoordinates.y; params.toX = moveToCoordinates.x; params.toY = moveToCoordinates.y; params.duration = duration; endpoint = '/wda/dragfromtoforduration'; context$1$0.next = 20; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST', params)); case 20: return context$1$0.abrupt('return', context$1$0.sent); case 21: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.handleTap = function callee$0$0(gesture) { var options, params, el, endpoint; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: options = gesture.options || {}; params = {}; if (_appiumSupport.util.hasValue(options.x) && _appiumSupport.util.hasValue(options.y)) { params.x = options.x; params.y = options.y; } el = _appiumSupport.util.hasValue(options.element) ? options.element : '0'; endpoint = '/wda/tap/' + el; if (_appiumSupport.util.hasValue(this.opts.tapWithShortPressDuration)) { // in some cases `tap` is too slow, so allow configurable long press _logger2['default'].debug('Translating tap into long press with \'' + this.opts.tapWithShortPressDuration + '\' duration'); params.duration = parseFloat(this.opts.tapWithShortPressDuration); endpoint = '/wda/element/' + el + '/touchAndHold'; params.duration = parseFloat(this.opts.tapWithShortPressDuration); } context$1$0.next = 8; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST', params)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.handleDoubleTap = function callee$0$0(gestures) { var gesture, opts, el, endpoint; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: gesture = gestures[0]; opts = gesture.options || {}; if (!opts.element) { _logger2['default'].errorAndThrow('WDA double tap needs an element'); } el = _appiumSupport.util.unwrapElement(opts.element); endpoint = '/wda/element/' + el + '/doubleTap'; context$1$0.next = 7; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST')); case 7: return context$1$0.abrupt('return', context$1$0.sent); case 8: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.handleLongPress = function callee$0$0(gestures) { var pressOpts, el, duration, params, endpoint; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: pressOpts = gestures[0].options || {}; el = _appiumSupport.util.unwrapElement(pressOpts.element); duration = undefined; // In seconds (not milliseconds) if (gestures.length === 1 && _appiumSupport.util.hasValue(pressOpts.duration)) { duration = pressOpts.duration / 1000; } else if (gestures.length === 3) { // duration is the `wait` action // upstream system expects seconds not milliseconds duration = parseFloat(gestures[1].options.ms) / 1000; } else { // give a sane default duration duration = 0.8; } params = { duration: duration, x: pressOpts.x, y: pressOpts.y }; endpoint = undefined; if (el) { endpoint = '/wda/element/' + el + '/touchAndHold'; } else { params.x = pressOpts.x; params.y = pressOpts.y; endpoint = '/wda/touchAndHold'; } context$1$0.next = 9; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST', params)); case 9: return context$1$0.abrupt('return', context$1$0.sent); case 10: case 'end': return context$1$0.stop(); } }, null, this); }; function determinePinchScale(x, y, pinch) { var scale = x > y ? x - y : y - x; if (pinch) { // TODO: revisit this when pinching actually works, since it is impossible to // know what the scale factor does at this point (Xcode 8.1) scale = 1 / scale; if (scale < 0.02) { // this is the minimum that Apple will allow // but WDA will not throw an error if it is too low scale = 0.02; } } else { // for zoom, each 10px is one scale factor scale = scale / 10; } return scale; } helpers.handlePinchOrZoom = function callee$0$0(actions) { var el, scale, velocity, thumb, forefinger, params; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: // currently we can only do this action on an element if (!actions[0][0].options.element || actions[0][0].options.element !== actions[1][0].options.element) { _logger2['default'].errorAndThrow('Pinch/zoom actions must be done on a single element'); } el = actions[0][0].options.element; scale = undefined, velocity = undefined; if (actions[0][0].options.y === actions[0][1].options.y) { thumb = actions[0][0].options.x <= actions[1][0].options.x ? actions[0] : actions[1]; // now decipher pinch vs. zoom, // pinch: thumb moving from left to right // zoom: thumb moving from right to left scale = determinePinchScale(thumb[0].options.x, thumb[1].options.x, thumb[0].options.x <= thumb[1].options.x); } else { forefinger = actions[0][0].options.y <= actions[1][0].options.y ? actions[0] : actions[1]; // now decipher pinch vs. zoom // pinch: forefinger moving from top to bottom // zoom: forefinger moving from bottom to top scale = determinePinchScale(forefinger[0].options.y, forefinger[1].options.y, forefinger[0].options.y <= forefinger[1].options.y); } velocity = scale < 1 ? -1 : 1; _logger2['default'].debug('Decoded ' + (scale < 1 ? 'pinch' : 'zoom') + ' action with scale \'' + scale + '\' and velocity \'' + velocity + '\''); if (scale < 1) { _logger2['default'].warn('Pinch actions may not work, due to Apple issue.'); } params = { scale: scale, velocity: velocity }; context$1$0.next = 10; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/pinch', 'POST', params)); case 10: case 'end': return context$1$0.stop(); } }, null, this); }; /* * See https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m * to get the info about available WDA gestures API * * See https://developer.apple.com/reference/xctest/xcuielement and * https://developer.apple.com/reference/xctest/xcuicoordinate to get the detailed description of * all XCTest gestures */ helpers.mobileScroll = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var swipe = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var params, msg, element, endpoint; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (opts.element) { context$1$0.next = 4; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.findNativeElementOrElements('class name', 'XCUIElementTypeApplication', false)); case 3: opts.element = context$1$0.sent; case 4: params = {}; if (opts.name && !swipe) { params.name = opts.name; } else if (opts.direction) { if (['up', 'down', 'left', 'right'].indexOf(opts.direction.toLowerCase()) < 0) { msg = 'Direction must be up, down, left or right'; _logger2['default'].errorAndThrow(msg); } params.direction = opts.direction; } else if (opts.predicateString && !swipe) { params.predicateString = opts.predicateString; } else if (opts.toVisible && !swipe) { params.toVisible = opts.toVisible; } else { msg = swipe ? 'Mobile swipe requires direction' : 'Mobile scroll supports the following strategies: name, direction, predicateString, and toVisible. Specify one of these'; _logger2['default'].errorAndThrow(msg); } element = opts.element.ELEMENT || opts.element; endpoint = '/wda/element/' + element + '/' + (swipe ? 'swipe' : 'scroll'); context$1$0.next = 10; return _regeneratorRuntime.awrap(this.proxyCommand(endpoint, 'POST', params)); case 10: return context$1$0.abrupt('return', context$1$0.sent); case 11: case 'end': return context$1$0.stop(); } }, null, this); }; function parseFloatParameter(paramName, paramValue, methodName) { if (_lodash2['default'].isUndefined(paramValue)) { _logger2['default'].errorAndThrow('"' + paramName + '" parameter is mandatory for "' + methodName + '" call'); } var result = parseFloat(paramValue); if (isNaN(result)) { _logger2['default'].errorAndThrow('"' + paramName + '" parameter should be a valid number. "' + paramValue + '" is given instead'); } return result; } helpers.mobilePinch = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var params, el; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (opts.element) { context$1$0.next = 4; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.findNativeElementOrElements('class name', 'XCUIElementTypeApplication', false)); case 3: opts.element = context$1$0.sent; case 4: params = { scale: parseFloatParameter('scale', opts.scale, 'pinch'), velocity: parseFloatParameter('velocity', opts.velocity, 'pinch') }; el = opts.element.ELEMENT || opts.element; context$1$0.next = 8; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/pinch', 'POST', params)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileDoubleTap = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var el, params; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (!opts.element) { context$1$0.next = 5; break; } el = opts.element.ELEMENT || opts.element; context$1$0.next = 4; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/doubleTap', 'POST')); case 4: return context$1$0.abrupt('return', context$1$0.sent); case 5: params = { x: parseFloatParameter('x', opts.x, 'doubleTap'), y: parseFloatParameter('y', opts.y, 'doubleTap') }; context$1$0.next = 8; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/doubleTap', 'POST', params)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileTwoFingerTap = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var el; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (opts.element) { context$1$0.next = 4; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.findNativeElementOrElements('class name', 'XCUIElementTypeApplication', false)); case 3: opts.element = context$1$0.sent; case 4: el = opts.element.ELEMENT || opts.element; context$1$0.next = 7; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/twoFingerTap', 'POST')); case 7: return context$1$0.abrupt('return', context$1$0.sent); case 8: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileTouchAndHold = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var params, el; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: params = { duration: parseFloatParameter('duration', opts.duration, 'touchAndHold') }; if (!opts.element) { context$1$0.next = 6; break; } el = opts.element.ELEMENT || opts.element; context$1$0.next = 5; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/touchAndHold', 'POST', params)); case 5: return context$1$0.abrupt('return', context$1$0.sent); case 6: // Long tap coordinates params.x = parseFloatParameter('x', opts.x, 'touchAndHold'); params.y = parseFloatParameter('y', opts.y, 'touchAndHold'); context$1$0.next = 10; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/touchAndHold', 'POST', params)); case 10: return context$1$0.abrupt('return', context$1$0.sent); case 11: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileTap = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var params, el; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: params = { x: parseFloatParameter('x', opts.x, 'tap'), y: parseFloatParameter('y', opts.y, 'tap') }; el = opts.element ? opts.element.ELEMENT || opts.element : '0'; context$1$0.next = 4; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/tap/' + el, 'POST', params)); case 4: return context$1$0.abrupt('return', context$1$0.sent); case 5: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileDragFromToForDuration = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var params, el; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: params = { duration: parseFloatParameter('duration', opts.duration, 'dragFromToForDuration'), fromX: parseFloatParameter('fromX', opts.fromX, 'dragFromToForDuration'), fromY: parseFloatParameter('fromY', opts.fromY, 'dragFromToForDuration'), toX: parseFloatParameter('toX', opts.toX, 'dragFromToForDuration'), toY: parseFloatParameter('toY', opts.toY, 'dragFromToForDuration') }; if (!opts.element) { context$1$0.next = 6; break; } el = opts.element.ELEMENT || opts.element; context$1$0.next = 5; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/element/' + el + '/dragfromtoforduration', 'POST', params)); case 5: return context$1$0.abrupt('return', context$1$0.sent); case 6: context$1$0.next = 8; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/dragfromtoforduration', 'POST', params)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.mobileSelectPickerWheelValue = function callee$0$0() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var el, params; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (!opts.element) { _logger2['default'].errorAndThrow('Element id is expected to be set for selectPickerWheelValue method'); } if (!_lodash2['default'].isString(opts.order) || ['next', 'previous'].indexOf(opts.order.toLowerCase()) === -1) { _logger2['default'].errorAndThrow('The mandatory "order" parameter is expected to be equal either to \'next\' or \'previous\'. ' + ('\'' + opts.order + '\' is given instead')); } el = opts.element.ELEMENT || opts.element; params = { order: opts.order }; if (opts.offset) { params.offset = parseFloatParameter('offset', opts.offset, 'selectPickerWheelValue'); } context$1$0.next = 7; return _regeneratorRuntime.awrap(this.proxyCommand('/wda/pickerwheel/' + el + '/select', 'POST', params)); case 7: return context$1$0.abrupt('return', context$1$0.sent); case 8: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.getCoordinates = function callee$0$0(gesture) { var el, coordinates, optionX, optionY, rect, pos, size, offsetX, offsetY; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: el = gesture.options.element; coordinates = { x: 0, y: 0, areOffsets: false }; optionX = null; if (gesture.options.x) { optionX = parseFloatParameter('x', gesture.options.x, 'getCoordinates'); } optionY = null; if (gesture.options.y) { optionY = parseFloatParameter('y', gesture.options.y, 'getCoordinates'); } // figure out the element coordinates. if (!el) { context$1$0.next = 19; break; } context$1$0.next = 9; return _regeneratorRuntime.awrap(this.getRect(el)); case 9: rect = context$1$0.sent; pos = { x: rect.x, y: rect.y }; size = { w: rect.width, h: rect.height }; offsetX = 0; offsetY = 0; // get the real offsets if (optionX || optionY) { offsetX = optionX || 0; offsetY = optionY || 0; } else { offsetX = size.w / 2; offsetY = size.h / 2; } // apply the offsets coordinates.x = pos.x + offsetX; coordinates.y = pos.y + offsetY; context$1$0.next = 22; break; case 19: // moveTo coordinates are passed in as offsets coordinates.areOffsets = gesture.action === 'moveTo'; coordinates.x = optionX || 0; coordinates.y = optionY || 0; case 22: return context$1$0.abrupt('return', coordinates); case 23: case 'end': return context$1$0.stop(); } }, null, this); }; helpers.applyMoveToOffset = function (firstCoordinates, secondCoordinates) { if (secondCoordinates.areOffsets) { return { x: firstCoordinates.x + secondCoordinates.x, y: firstCoordinates.y + secondCoordinates.y }; } else { return secondCoordinates; } }; _Object$assign(extensions, helpers, commands); exports.extensions = extensions; exports.helpers = helpers; exports.commands = commands; exports.isSameGestures = isSameGestures; exports.gesturesChainToString = gesturesChainToString; exports['default'] = extensions; // there are multiple commands that map here, so manually proxy // atoms-based clicks don't always work in safari 7 // use the to-visible option of scrolling in WDA // otherwise, for now, just translate into a drag with short duration // get gestures // get drag data // assume that action is in a single plane (x or y, not horizontal at all) // terminology all assuming right handedness // horizontal, since y offset is the same in press and moveTo // vertical // WDA supports four scrolling strategies: predication based on name, direction, // predicateString, and toVisible, in that order. Swiping requires direction. // Double tap element // Double tap coordinates // Long tap element // Drag element // Drag coordinates // defaults // defaults //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9jb21tYW5kcy9nZXN0dXJlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Z0NBQXVCLG9CQUFvQjs7NkJBQ3RCLGdCQUFnQjs7K0JBQ1QsbUJBQW1COztzQkFDakMsUUFBUTs7OztzQkFDTixXQUFXOzs7O0FBRzNCLElBQUksT0FBTyxHQUFHLEVBQUU7SUFBRSxVQUFVLEdBQUcsRUFBRTtJQUFFLFFBQVEsR0FBRyxFQUFFLENBQUM7O0FBRWpELFFBQVEsQ0FBQyxNQUFNLEdBQUcsNkJBQVksT0FBTyxDQUFDLE1BQU0sQ0FBQzs7QUFFN0MsUUFBUSxDQUFDLEtBQUssR0FBRyxvQkFBZ0IsRUFBRTtNQVUzQixZQUFZOzs7O1lBVGIsSUFBSSxDQUFDLFlBQVksRUFBRTs7Ozs7O3lDQUVULElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDOzs7Ozs7QUFFbkMsVUFBRSxHQUFHLG9CQUFLLGFBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQzs7Y0FDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUE7Ozs7Ozt5Q0FFMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Ozs7Ozs7QUFFdkIsb0JBQVksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQzs7eUNBQzlCLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7Ozs7Ozs7Ozs7Q0FFekQsQ0FBQzs7QUFFRixTQUFTLGNBQWMsQ0FBRSxRQUFRLEVBQUUsVUFBVSxFQUFFO0FBQzdDLE1BQUk7QUFDRixRQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssVUFBVSxDQUFDLE1BQU0sRUFBRTtBQUN6QyxhQUFPLEtBQUssQ0FBQztLQUNkO0FBQ0QsU0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFF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