Best JavaScript code snippet using appium-xcuitest-driver
ios-controller.js
Source:ios-controller.js  
...370        var tapUrl = this.args.robotUrl + "/tap";371        request.post({url:tapUrl, form: {x:tapPoint.x, y:tapPoint.y}}, cb);372      }.bind(this));373    } else {374      this.nativeTap(elementId, cb);375    }376  }377};378iOSController.nativeTap = function (elementId, cb) {379  var command = ["au.tapById('", elementId, "')"].join('');380  this.proxy(command, cb);381};382iOSController.nativeWebTap = function (elementId, cb) {383  this.useAtomsElement(elementId, cb, function (atomsElement) {384    this.executeAtom('get_top_left_coordinates', [atomsElement], function (err, res) {385      if (err || res.status !== 0) return cb(err, res);386      var x = res.value.x, y = res.value.y;387      this.executeAtom('get_size', [atomsElement], function (err, res) {388        if (err || res.status !== 0) return cb(err, res);389        var w = res.value.width, h = res.value.height;390        var clickX = x + (w / 2);391        var clickY = y + (h / 2);392        this.curWebCoords = {x: clickX, y: clickY};393        this.clickWebCoords(function (err, res) {394          // make sure real tap actually has time to register395          setTimeout(function () {396            cb(err, res);397          }, 500);398        });399      }.bind(this));400    }.bind(this));401  }.bind(this));402};403iOSController.pushFile = function (base64Data, remotePath, cb) {404  if (this.realDevice) {405    logger.debug("Unsupported: cannot write files to physical device");406    return cb(new NotYetImplementedError(), null);407  }408  logger.debug("Pushing " + remotePath + " to iOS simulator");409  var writeFile = function (err, fullPath) {410    if (err) return cb(err);411    logger.debug("Attempting to write " + fullPath + "...");412    async.series([413      function (cb) {414        try {415          if (fs.existsSync(fullPath)) {416            logger.debug(fullPath + " already exists, deleting...");417            fs.unlinkSync(fullPath);418          }419          mkdirp.sync(path.dirname(fullPath));420          var content = new Buffer(base64Data, 'base64');421          var fd = fs.openSync(fullPath, 'w');422          fs.writeSync(fd, content, 0, content.length, 0);423          fs.closeSync(fd);424          logger.debug("Wrote " + content.length + "bytes to " + fullPath);425          cb(null);426        } catch (e) {427          cb(e);428        }429      }.bind(this)430    ], function (err) {431      logger.debug("Returning response");432      if (err) return cb(err);433      cb(null, {434        status: status.codes.Success.code435      });436    });437  };438  this._getFullPath(remotePath, writeFile);439};440/*441 *  Get the full path to an iOS simulator file.442 *  Calls cb(err, fullFilePath)443 *  /Some/Path                           fetches a file relative to the root of the device's filesystem.444 *  /Applications/AppName.app/Some/Path  fetches a file relative to the root of that Application's .app directory, adding in the GUID.445 *  So it looks something like: /Applications/GUID-GUID-GUID-GUID/Some/Path446 */447iOSController._getFullPath = function (remotePath, cb) {448  var fullPath = "";449  var v = (this.args.platformVersion || this.iOSSDKVersion);450  var simRoots = this.sim.getDirs();451  if (simRoots.length < 1) {452    return cb(new Error("Could not find simulator root for SDK version " +453                        v + "; have you launched this sim before?"));454  } else if (simRoots.length > 1) {455    logger.warn("There were multiple simulator roots for version " + v + ". " +456                "We may be pulling the file from the one you're not using!");457  }458  if (simRoots.length > 1) {459    var filteredSimRoots = simRoots.filter(function (root) {460      return fs.existsSync(root + "/Applications") || // ios7461             fs.existsSync(root + "/Containers/Data/Application"); // ios8462    });463    if (filteredSimRoots.length > 0) {464      simRoots = filteredSimRoots;465    }466  }467  var basePath = simRoots[0];468  var appName = null;469  if (this.args.app) {470    var appNameRegex = new RegExp("\\" + path.sep + "(\\w+\\.app)");471    var appNameMatches = appNameRegex.exec(this.args.app);472    if (appNameMatches) {473      appName = appNameMatches[1];474    }475  }476  // de-absolutize the path477  if (isWindows()) {478    if (remotePath.indexof("://") === 1) {479      remotePath = remotePath.slice(4);480    }481  } else {482    if (remotePath.indexOf("/") === 0) {483      remotePath = remotePath.slice(1);484    }485  }486  if (remotePath.indexOf(appName) === 0) {487    logger.debug("We want an app-relative file");488    var findPath = basePath;489    if (this.args.platformVersion >= 8) {490      // the .app file appears in /Containers/Data and /Containers/Bundle both. We only want /Bundle491      findPath = path.resolve(basePath, "Containers", "Bundle");492    }493    findPath =  findPath.replace(/\s/g, '\\ ');494    var findCmd = 'find ' + findPath + ' -name "' + appName + '"';495    exec(findCmd, function (err, stdout) {496      if (err) return cb(err);497      var appRoot = stdout.replace(/\n$/, '');498      var subPath = remotePath.substring(appName.length + 1);499      fullPath = path.resolve(appRoot, subPath);500      cb(null, fullPath);501    }.bind(this));502  } else {503    logger.debug("We want a sim-relative file");504    fullPath = path.resolve(basePath, remotePath);505    cb(null, fullPath);506  }507};508iOSController.pullFile = function (remotePath, cb) {509  logger.debug("Pulling " + remotePath + " from sim");510  if (this.realDevice) {511    return cb(new NotYetImplementedError(), null);512  }513  var readAndReturnFile = function (err, fullPath) {514    if (err) return cb(err);515    logger.debug("Attempting to read " + fullPath);516    fs.readFile(fullPath, {encoding: 'base64'}, function (err, data) {517      if (err) return cb(err);518      cb(null, {status: status.codes.Success.code, value: data});519    });520  };521  this._getFullPath(remotePath, readAndReturnFile);522};523iOSController.pullFolder = function (remotePath, cb) {524  logger.debug("Pulling " + remotePath + " from sim");525  if (this.realDevice) {526    return cb(new NotYetImplementedError(), null);527  }528  var bufferOnSuccess = function (buffer) {529    logger.debug("Converting in-memory zip file to base64 encoded string");530    var data = buffer.toString('base64');531    logger.debug("Returning in-memory zip file as base54 encoded string");532    cb(null, {status: status.codes.Success.code, value: data});533  };534  var bufferOnFail = function (err) {535    cb(new Error(err));536  };537  var zipAndReturnFolder = function (err, fullPath) {538    if (err) return cb(err);539    logger.debug("Adding " + fullPath + " to an in-memory zip archive");540    var zip = new AdmZip();541    zip.addLocalFolder(fullPath);542    zip.toBuffer(bufferOnSuccess, bufferOnFail);543  };544  this._getFullPath(remotePath, zipAndReturnFolder);545};546iOSController.touchLongClick = function (elementId, cb) {547  cb(new NotYetImplementedError(), null);548};549iOSController.touchDown = function (elId, x, y, cb) {550  cb(new NotYetImplementedError(), null);551};552iOSController.touchUp = function (elementId, cb) {553  cb(new NotYetImplementedError(), null);554};555iOSController.touchMove = function (elId, startX, startY, cb) {556  cb(new NotYetImplementedError(), null);557};558iOSController.toggleData = function (cb) {559  cb(new NotYetImplementedError(), null);560};561iOSController.toggleFlightMode = function (cb) {562  cb(new NotYetImplementedError(), null);563};564iOSController.toggleWiFi = function (cb) {565  cb(new NotYetImplementedError(), null);566};567iOSController.toggleLocationServices = function (cb) {568  cb(new NotYetImplementedError(), null);569};570iOSController.getStrings = function (language, stringFile, cb) {571  this.parseLocalizableStrings(language, stringFile, function () {572    var strings = this.localizableStrings;573    if (strings && strings.length >= 1) strings = strings[0];574    cb(null, {575      status: status.codes.Success.code576    , value: strings577    });578  }.bind(this));579};580iOSController.executeAtom = function (atom, args, cb, alwaysDefaultFrame) {581  var counter = this.executedAtomsCounter++;582  var frames = alwaysDefaultFrame === true ? [] : this.curWebFrames;583  this.returnedFromExecuteAtom[counter] = false;584  this.processingRemoteCmd = true;585  this.remote.executeAtom(atom, args, frames, function (err, res) {586    this.processingRemoteCmd = false;587    if (!this.returnedFromExecuteAtom[counter]) {588      this.returnedFromExecuteAtom[counter] = true;589      res = this.parseExecuteResponse(res);590      cb(err, res);591    }592  }.bind(this));593  this.lookForAlert(cb, counter, 0, 5000);594};595iOSController.executeAtomAsync = function (atom, args, responseUrl, cb) {596  var counter = this.executedAtomsCounter++;597  this.returnedFromExecuteAtom[counter] = false;598  this.processingRemoteCmd = true;599  this.asyncResponseCb = cb;600  this.remote.executeAtomAsync(atom, args, this.curWebFrames, responseUrl, function (err, res) {601    this.processingRemoteCmd = false;602    if (!this.returnedFromExecuteAtom[counter]) {603      this.returnedFromExecuteAtom[counter] = true;604      res = this.parseExecuteResponse(res);605      cb(err, res);606    }607  }.bind(this));608  this.lookForAlert(cb, counter, 0, 5000);609};610iOSController.receiveAsyncResponse = function (asyncResponse) {611  var asyncCb = this.asyncResponseCb;612  //mark returned as true to stop looking for alerts; the js is done.613  this.returnedFromExecuteAtom = true;614  if (asyncCb !== null) {615    this.parseExecuteResponse(asyncResponse, asyncCb);616    asyncCb(null, asyncResponse);617    this.asyncResponseCb = null;618  } else {619    logger.warn("Received async response when we weren't expecting one! " +620                    "Response was: " + JSON.stringify(asyncResponse));621  }622};623iOSController.parseExecuteResponse = deviceCommon.parseExecuteResponse;624iOSController.parseElementResponse = deviceCommon.parseElementResponse;625iOSController.lookForAlert = function (cb, counter, looks, timeout) {626  setTimeout(function () {627    if (typeof looks === 'undefined') {628      looks = 0;629    }630    if (this.instruments !== null) {631      if (!this.returnedFromExecuteAtom[counter] && looks < 11 && !this.selectingNewPage) {632        logger.debug("atom did not return yet, checking to see if " +633          "we are blocked by an alert");634        // temporarily act like we're not processing a remote command635        // so we can proxy the alert detection functionality636        this.alertCounter++;637        this.proxy("au.alertIsPresent()", function (err, res) {638          if (res !== null) {639            if (res.value === true) {640              logger.debug("Found an alert, returning control to client");641              this.returnedFromExecuteAtom[counter] = true;642              cb(null, {643                status: status.codes.Success.code644              , value: ''645              });646            } else {647              // say we're processing remote cmd again648              looks++;649              setTimeout(this.lookForAlert(cb, counter, looks), 1000);650            }651          }652        }.bind(this));653      }654    }655  }.bind(this), timeout);656};657iOSController.clickCurrent = function (button, cb) {658  var noMoveToErr = {659    status: status.codes.UnknownError.code660  , value: "Cannot call click() before calling moveTo() to set coords"661  };662  if (this.isWebContext()) {663    if (this.curWebCoords === null) {664      return cb(null, noMoveToErr);665    }666    this.clickWebCoords(cb);667  } else {668    if (this.curCoords === null) {669      return cb(null, noMoveToErr);670    }671    this.clickCoords(this.curCoords, cb);672  }673};674iOSController.clickCoords = function (coords, cb) {675  if (this.useRobot) {676    var tapUrl = this.args.robotUrl + "/tap";677    request.post({url:tapUrl, form: {x:coords.x, y:coords.y}}, cb);678  } else {679    var opts = coords;680    opts.tapCount = 1;681    opts.duration = 0.3;682    opts.touchCount = 1;683    var command = ["au.complexTap(" + JSON.stringify(opts) + ")"].join('');684    this.proxy(command, cb);685  }686};687iOSController.translateWebCoords = function (coords, cb) {688  var wvCmd = "au.getElementsByType('webview')"689    , webviewIndex = this.webContextIndex();690  // add static offset for safari in landscape mode691  var yOffset = this.curOrientation === "LANDSCAPE" ?692     this.landscapeWebCoordsOffset :693     0;694  // absolutize web coords695  this.proxy(wvCmd, function (err, res) {696    if (err) return cb(err, res);697    if (res.value.length < 1) {698      return cb(null, {699        status: status.codes.UnknownError.code700      , value: "Could not find any webviews to click inside!"701      });702    }703    if (typeof res.value[webviewIndex] === "undefined") {704      logger.warn("Could not find webview at index " + webviewIndex + ", " +705                  "taking last available one for clicking purposes");706      webviewIndex = res.value.length - 1;707    }708    var realDims, wvDims, wvPos;709    var step1 = function () {710      var wvId = res.value[webviewIndex].ELEMENT;711      var locCmd = "au.getElement('" + wvId + "').rect()";712      this.proxy(locCmd, function (err, res) {713        if (err) return cb(err, res);714        var rect = res.value;715        wvPos = {x: rect.origin.x, y: rect.origin.y};716        realDims = {w: rect.size.width, h: rect.size.height};717        next();718      });719    }.bind(this);720    var step2 = function () {721      var cmd = "(function () { return {w: document.width, h: document.height}; })()";722      this.remote.execute(cmd, function (err, res) {723        wvDims = {w: res.result.value.w, h: res.result.value.h};724        next();725      });726    }.bind(this);727    var next = function () {728      if (wvDims && realDims && wvPos) {729        var xRatio = realDims.w / wvDims.w;730        var yRatio = realDims.h / wvDims.h;731        var serviceBarHeight = 20;732        if (parseFloat(this.args.platformVersion) >= 8) {733          // ios8 includes the service bar height in the app734          serviceBarHeight = 0;735        }736        var newCoords = {737          x: wvPos.x + Math.round(xRatio * coords.x)738        , y: wvPos.y + yOffset + Math.round(yRatio * coords.y) - serviceBarHeight739        };740        logger.debug("Converted web coords " + JSON.stringify(coords) +741                    "into real coords " + JSON.stringify(newCoords));742        cb(newCoords);743      }744    }.bind(this);745    step1();746    step2();747  }.bind(this));748};749iOSController.clickWebCoords = function (cb) {750  this.translateWebCoords(this.curWebCoords, function (coords) {751    this.clickCoords(coords, cb);752  }.bind(this));753};754iOSController.submit = function (elementId, cb) {755  if (this.isWebContext()) {756    this.useAtomsElement(elementId, cb, function (atomsElement) {757      this.executeAtom('submit', [atomsElement], cb);758    }.bind(this));759  } else {760    cb(new NotImplementedError(), null);761  }762};763iOSController.pressKeyCode = function (keycode, metastate, cb) {764  cb(new NotImplementedError(), null);765};766iOSController.longPressKeyCode = function (keycode, metastate, cb) {767  cb(new NotImplementedError(), null);768};769iOSController.keyevent = function (keycode, metastate, cb) {770  cb(new NotImplementedError(), null);771};772iOSController.complexTap = function (tapCount, touchCount, duration, x, y, elementId, cb) {773  var command;774  var  options = {775    tapCount: tapCount776  , touchCount: touchCount777  , duration: duration778  , x: x779  , y: y780  };781  var JSONOpts = JSON.stringify(options);782  if (elementId !== null) {783    command = ["au.getElement('", elementId, "').complexTap(", JSONOpts, ')'].join('');784  } else {785    command = ["au.complexTap(", JSONOpts, ")"].join('');786  }787  this.proxy(command, cb);788};789iOSController.clear = function (elementId, cb) {790  if (this.isWebContext()) {791    this.useAtomsElement(elementId, cb, function (atomsElement) {792      this.executeAtom('clear', [atomsElement], cb);793    }.bind(this));794  } else {795    var command = ["au.getElement('", elementId, "').setValue('')"].join('');796    this.proxy(command, cb);797  }798};799iOSController.getText = function (elementId, cb) {800  if (this.isWebContext()) {801    this.useAtomsElement(elementId, cb, function (atomsElement) {802      this.executeAtom('get_text', [atomsElement], cb);803    }.bind(this));804  } else {805    var command = ["au.getElement('", elementId, "').text()"].join('');806    this.proxy(command, function (err, res) {807      // in some cases instruments returns in integer. we only want a string808      res.value = res.value ? res.value.toString() : '';809      cb(err, res);810    });811  }812};813iOSController.getName = function (elementId, cb) {814  if (this.isWebContext()) {815    this.useAtomsElement(elementId, cb, function (atomsElement) {816      var script = "return arguments[0].tagName.toLowerCase()";817      this.executeAtom('execute_script', [script, [atomsElement]], cb);818    }.bind(this));819  } else {820    var command = ["au.getElement('", elementId, "').type()"].join('');821    this.proxy(command, cb);822  }823};824iOSController.getAttribute = function (elementId, attributeName, cb) {825  if (this.isWebContext()) {826    var atomsElement = this.getAtomsElement(elementId);827    if (atomsElement === null) {828      cb(null, {829        status: status.codes.UnknownError.code830      , value: "Error converting element ID for using in WD atoms: " + elementId831      });832    } else {833      this.executeAtom('get_attribute_value', [atomsElement, attributeName], cb);834    }835  } else {836    if (_.contains(['label', 'name', 'value', 'values', 'hint'], attributeName)) {837      var command = ["au.getElement('", elementId, "').", attributeName, "()"].join('');838      this.proxy(command, cb);839    } else {840      cb(null, {841        status: status.codes.UnknownCommand.code842      , value: "UIAElements don't have the attribute '" + attributeName + "'"843      });844    }845  }846};847iOSController.getLocation = function (elementId, cb) {848  if (this.isWebContext()) {849    this.useAtomsElement(elementId, cb, function (atomsElement) {850      this.executeAtom('get_top_left_coordinates', [atomsElement], cb);851    }.bind(this));852  } else {853    var command = ["au.getElement('", elementId,854      "').getElementLocation()"].join('');855    this.proxy(command, cb);856  }857};858iOSController.getSize = function (elementId, cb) {859  if (this.isWebContext()) {860    var atomsElement = this.getAtomsElement(elementId);861    if (atomsElement === null) {862      cb(null, {863        status: status.codes.UnknownError.code864      , value: "Error converting element ID for using in WD atoms: " + elementId865      });866    } else {867      this.executeAtom('get_size', [atomsElement], cb);868    }869  } else {870    var command = ["au.getElement('", elementId, "').getElementSize()"].join('');871    this.proxy(command, cb);872  }873};874iOSController.getWindowSize = function (windowHandle, cb) {875  if (windowHandle !== "current") {876    cb(null, {877      status: status.codes.NoSuchWindow.code878    , value: "Currently only getting current window size is supported."879    });880  }881  if (this.isWebContext()) {882    this.executeAtom('get_window_size', [], function (err, res) {883      cb(null, {884        status: status.codes.Success.code885      , value: res886      });887    });888  } else {889    this.proxy("au.getWindowSize()", cb);890  }891};892iOSController.mobileWebNav = function (navType, cb) {893  this.remote.willNavigateWithoutReload = true;894  this.executeAtom('execute_script', ['history.' + navType + '();', null], cb);895};896iOSController.back = function (cb) {897  if (this.isWebContext()) {898    this.mobileWebNav("back", cb);899  } else {900    var command = "au.back();";901    this.proxy(command, cb);902  }903};904iOSController.forward = function (cb) {905  if (this.isWebContext()) {906    this.mobileWebNav("forward", cb);907  } else {908    cb(new NotImplementedError(), null);909  }910};911iOSController.refresh = function (cb) {912  if (this.isWebContext()) {913    this.executeAtom('refresh', [], cb);914  } else {915    cb(new NotImplementedError(), null);916  }917};918iOSController.getPageIndex = function (elementId, cb) {919  if (this.isWebContext()) {920    cb(new NotImplementedError(), null);921  } else {922    var command = ["au.getElement('", elementId, "').pageIndex()"].join('');923    this.proxy(command, cb);924  }925};926iOSController.keys = function (keys, cb) {927  keys = escapeSpecialChars(keys, "'");928  if (this.isWebContext()) {929    this.active(function (err, res) {930      if (err || typeof res.value.ELEMENT === "undefined") {931        return cb(err, res);932      }933      this.setValue(res.value.ELEMENT, keys, cb);934    }.bind(this));935  } else {936    var command = ["au.sendKeysToActiveElement('", keys, "')"].join('');937    this.proxy(command, cb);938  }939};940iOSController.frame = function (frame, cb) {941  if (this.isWebContext()) {942    var atom;943    if (frame === null) {944      this.curWebFrames = [];945      logger.debug("Leaving web frame and going back to default content");946      cb(null, {947        status: status.codes.Success.code948      , value: ''949      });950    } else {951      if (typeof frame.ELEMENT !== "undefined") {952        this.useAtomsElement(frame.ELEMENT, cb, function (atomsElement) {953          this.executeAtom('get_frame_window', [atomsElement], function (err, res) {954            if (this.checkSuccess(err, res, cb)) {955              logger.debug("Entering new web frame: " + res.value.WINDOW);956              this.curWebFrames.unshift(res.value.WINDOW);957              cb(err, res);958            }959          }.bind(this));960        }.bind(this));961      } else {962        atom = "frame_by_id_or_name";963        if (typeof frame === "number") {964          atom = "frame_by_index";965        }966        this.executeAtom(atom, [frame], function (err, res) {967          if (this.checkSuccess(err, res, cb)) {968            if (res.value === null || typeof res.value.WINDOW === "undefined") {969              cb(null, {970                status: status.codes.NoSuchFrame.code971              , value: ''972              });973            } else {974              logger.debug("Entering new web frame: " + res.value.WINDOW);975              this.curWebFrames.unshift(res.value.WINDOW);976              cb(err, res);977            }978          }979        }.bind(this));980      }981    }982  } else {983    frame = frame ? frame : 'target.frontMostApp()';984    var command = ["wd_frame = ", frame].join('');985    this.proxy(command, cb);986  }987};988iOSController.implicitWait = function (ms, cb) {989  this.implicitWaitMs = parseInt(ms, 10);990  logger.debug("Set iOS implicit wait to " + ms + "ms");991  cb(null, {992    status: status.codes.Success.code993  , value: null994  });995};996iOSController.asyncScriptTimeout = function (ms, cb) {997  this.asyncWaitMs = parseInt(ms, 10);998  logger.debug("Set iOS async script timeout to " + ms + "ms");999  cb(null, {1000    status: status.codes.Success.code1001  , value: null1002  });1003};1004iOSController.pageLoadTimeout = function (ms, cb) {1005  this.pageLoadMs = parseInt(ms, 10);1006  if (this.remote) this.remote.pageLoadMs = this.pageLoadMs;1007  logger.debug("Set iOS page load timeout to " + ms + "ms");1008  cb(null, {1009    status: status.codes.Success.code1010  , value: null1011  });1012};1013iOSController.elementDisplayed = function (elementId, cb) {1014  if (this.isWebContext()) {1015    this.useAtomsElement(elementId, cb, function (atomsElement) {1016      this.executeAtom('is_displayed', [atomsElement], cb);1017    }.bind(this));1018  } else {1019    var command = ["au.getElement('", elementId, "').isDisplayed()"].join('');1020    this.proxy(command, cb);1021  }1022};1023iOSController.elementEnabled = function (elementId, cb) {1024  if (this.isWebContext()) {1025    this.useAtomsElement(elementId, cb, function (atomsElement) {1026      this.executeAtom('is_enabled', [atomsElement], cb);1027    }.bind(this));1028  } else {1029    var command = ["au.getElement('", elementId, "').isEnabled() === 1"].join('');1030    this.proxy(command, cb);1031  }1032};1033iOSController.elementSelected = function (elementId, cb) {1034  if (this.isWebContext()) {1035    this.useAtomsElement(elementId, cb, function (atomsElement) {1036      this.executeAtom('is_selected', [atomsElement], cb);1037    }.bind(this));1038  } else {1039    var command = ["au.getElement('", elementId, "').isSelected()"].join('');1040    this.proxy(command, cb);1041  }1042};1043iOSController.getCssProperty = function (elementId, propertyName, cb) {1044  if (this.isWebContext()) {1045    this.useAtomsElement(elementId, cb, function (atomsElement) {1046      this.executeAtom('get_value_of_css_property', [atomsElement,1047        propertyName], cb);1048    }.bind(this));1049  } else {1050    cb(new NotImplementedError(), null);1051  }1052};1053iOSController.getPageSource = function (cb) {1054  if (this.isWebContext()) {1055    this.processingRemoteCmd = true;1056    var cmd = 'document.getElementsByTagName("html")[0].outerHTML';1057    this.remote.execute(cmd, function (err, res) {1058      if (err) {1059        cb("Remote debugger error", {1060          status: status.codes.UnknownError.code1061        , value: res1062        });1063      } else {1064        cb(null, {1065          status: status.codes.Success.code1066        , value: res.result.value1067        });1068      }1069      this.processingRemoteCmd = false;1070    }.bind(this));1071  } else {1072    this.getSourceForElementForXML(null, function (err, res) {1073      var xmlSource;1074      if (err || res.status !== 0) return cb(err, res);1075      try {1076        xmlSource = _xmlSourceFromJson(res.value);1077      } catch (e) {1078        return cb(e);1079      }1080      return cb(null, {1081        status: status.codes.Success.code1082      , value: xmlSource1083      });1084    }.bind(this));1085  }1086};1087iOSController.getAlertText = function (cb) {1088  this.proxy("au.getAlertText()", cb);1089};1090iOSController.setAlertText = function (text, cb) {1091  text = escapeSpecialChars(text, "'");1092  this.proxy("au.setAlertText('" + text + "')", cb);1093};1094iOSController.postAcceptAlert = function (cb) {1095  this.proxy("au.acceptAlert()", cb);1096};1097iOSController.postDismissAlert = function (cb) {1098  this.proxy("au.dismissAlert()", cb);1099};1100iOSController.lock = function (secs, cb) {1101  this.proxy(["au.lock(", secs, ")"].join(''), cb);1102};1103iOSController.isLocked = function (cb) {1104  cb(new NotYetImplementedError(), null);1105};1106iOSController.background = function (secs, cb) {1107  this.proxy(["au.background(", secs, ")"].join(''), cb);1108};1109iOSController.getOrientation = function (cb) {1110  this.proxy("au.getScreenOrientation()", function (err, res) {1111    if (res && res.status === status.codes.Success.code) {1112      // keep track of orientation for our own purposes1113      logger.debug("Setting internal orientation to " + res.value);1114      this.curOrientation = res.value;1115    }1116    cb(err, res);1117  });1118};1119iOSController.setOrientation = function (orientation, cb) {1120  var command = ["au.setScreenOrientation('", orientation, "')"].join('');1121  this.proxy(command, function (err, res) {1122    if (res && res.status === 0) {1123      this.curOrientation = orientation;1124    }1125    cb(err, res);1126  }.bind(this));1127};1128iOSController.getScreenshot = function (cb) {1129  var guid = uuid.create();1130  var command = ["au.capture('screenshot", guid, "')"].join('');1131  var shotFolder = path.resolve(this.args.tmpDir,1132                                "appium-instruments/Run 1/");1133  if (!fs.existsSync(shotFolder)) {1134    mkdirp.sync(shotFolder);1135  }1136  var shotPath = path.resolve(shotFolder, 'screenshot' + guid + '.png');1137  // Retrying the whole screenshot process for three times.1138  async.retry(3,1139    function (cb) {1140      async.waterfall([1141        function (cb) { this.getOrientation(function () { cb(); }); }.bind(this),1142        function (cb) { this.proxy(command, cb); }.bind(this),1143        function (response, cb) {1144          var data;1145          var screenshotWaitTimeout = (this.args.screenshotWaitTimeout || 10) * 1000;1146          logger.debug('Waiting ' + screenshotWaitTimeout + ' ms for screenshot to ge generated.');1147          var startMs = Date.now();1148          var lastErr;1149          async.until(1150            function () { return data || Date.now() - startMs > screenshotWaitTimeout; },1151            function (cb) {1152              setTimeout(function () {1153                fs.readFile(shotPath, function (err, _data) {1154                  lastErr = err;1155                  if (!err) { data = _data; }1156                  cb();1157                });1158              }, 300);1159            },1160            function (err) {1161              if (!data) {1162                return cb(new Error("Timed out waiting for screenshot file. " + (lastErr || '').toString()));1163              }1164              cb(err, response, data);1165            }1166          );1167        }.bind(this),1168        function (response, data, cb) {1169          // rotate if necessary1170          if (this.curOrientation === "LANDSCAPE") {1171            // need to rotate 90 deg CC1172            logger.debug("Rotating landscape screenshot");1173            rotateImage(shotPath, -90, function (err) {1174              if (err) return cb(new Error("Could not rotate screenshot appropriately"), null);1175              fs.readFile(shotPath, function read(err, _data) {1176                if (err) return cb(new Error("Could not retrieve screenshot file following rotate. " + err.toString()));1177                cb(null, response, _data);1178              });1179            });1180          } else cb(null, response, data);1181        }.bind(this),1182        function (response, data, cb) {1183          var b64data = new Buffer(data).toString('base64');1184          response.value = b64data;1185          cb(null, response);1186        }1187      ], cb);1188    }.bind(this), cb);1189};1190iOSController.fakeFlick = function (xSpeed, ySpeed, swipe, cb) {1191  var command = "";1192  if (swipe) {1193    command = ["au.touchSwipeFromSpeed(", xSpeed, ",", ySpeed, ")"].join('');1194    this.proxy(command, cb);1195  } else {1196    command = ["au.touchFlickFromSpeed(", xSpeed, ",", ySpeed, ")"].join('');1197    this.proxyWithMinTime(command, FLICK_MS, cb);1198  }1199};1200iOSController.fakeFlickElement = function (elementId, xoffset, yoffset, speed, cb) {1201  var command = "";1202  if (this.isWebContext()) {1203    this.useAtomsElement(elementId, cb, function (atomsElement) {1204      this.executeAtom('get_top_left_coordinates', [atomsElement], function (err, res) {1205        if (err || res.status !== 0) return cb(err, res);1206        var x = res.value.x, y = res.value.y;1207        this.executeAtom('get_size', [atomsElement], function (err, res) {1208          if (err || res.status !== 0) return cb(err, res);1209          var w = res.value.width, h = res.value.height;1210          var clickX = x + (w / 2);1211          var clickY = y + (h / 2);1212          this.translateWebCoords({x: clickX, y: clickY}, function (from) {1213            this.translateWebCoords({x: clickX + xoffset, y: clickY + yoffset}, function (to) {1214              // speed is not used because underlying UIATarget.flickFromTo doesn't support it1215              command = ["au.flick(", JSON.stringify({from: from, to: to}), ")"].join('');1216              this.proxy(command, cb);1217            }.bind(this));1218          }.bind(this));1219        }.bind(this));1220      }.bind(this));1221    }.bind(this));1222  } else {1223    command = ["au.getElement('", elementId, "').touchFlick(", xoffset, ",",1224      yoffset, ",", speed, ")"].join('');1225    this.proxyWithMinTime(command, FLICK_MS, cb);1226  }1227};1228iOSController.drag = function (startX, startY, endX, endY, duration, touchCount, elId, destElId, cb) {1229  var command;1230  if (elId) {1231    if (this.isWebContext()) {1232      return cb(new NotYetImplementedError(), null);1233    }1234    command = ["au.getElement('", elId, "').drag(", startX, ',', startY, ',',1235      endX, ',', endY, ',', duration, ',', touchCount, ")"].join('');1236  } else {1237    command = ["au.dragApp(", startX, ',', startY, ',', endX, ',', endY, ',',1238      duration, ")"].join('');1239  }1240  // wait for device to complete swipe1241  this.proxy(command, function (err, res) {1242    setTimeout(function () {1243      cb(err, res);1244    }, duration * 1000);1245  });1246};1247iOSController.swipe = function (startX, startY, endX, endY, duration, touchCount, elId, cb) {1248  this.drag(startX, startY, endX, endY, duration, touchCount, elId, null, cb);1249};1250iOSController.rotate = function (x, y, radius, rotation, duration, touchCount, elId, cb) {1251  var command;1252  var location = {'x' : x, 'y' : y};1253  var options = {'duration' : duration, 'radius' : radius, 'rotation' : rotation, 'touchCount' : touchCount};1254  if (elId) {1255    if (this.isWebContext()) {1256      return cb(new NotYetImplementedError(), null);1257    }1258    command = "au.getElement('" + elId + "').rotateWithOptions(" + JSON.stringify(location) +1259              "," + JSON.stringify(options) + ")";1260    this.proxy(command, cb);1261  } else {1262    this.proxy("target.rotateWithOptions(" + JSON.stringify(location) + "," + JSON.stringify(options) + ")", cb);1263  }1264};1265iOSController.pinchClose = function (startX, startY, endX, endY, duration,1266    percent, steps, elId, cb) {1267  var command;1268  var fromPointObject = {'x' : startX, 'y' : startY};1269  var toPointObject = {'x' : endX, 'y' : endY};1270  if (elId) {1271    command = ["au.getElement('", elId, "').pinchCloseFromToForDuration(",1272      JSON.stringify(fromPointObject),  ",",  JSON.stringify(toPointObject),1273        ",", duration, ")"].join('');1274    this.proxy(command, cb);1275  } else {1276    this.proxy("target.pinchCloseFromToForDuration(" + JSON.stringify(fromPointObject) +1277      "," + JSON.stringify(toPointObject) + "," + duration + ")", cb);1278  }1279};1280iOSController.pinchOpen = function (startX, startY, endX, endY, duration,1281    percent, steps, elId, cb) {1282  var command;1283  var fromPointObject = {'x' : startX, 'y' : startY};1284  var toPointObject = {'x' : endX, 'y' : endY};1285  if (elId) {1286    if (this.isWebContext()) {1287      return cb(new NotYetImplementedError(), null);1288    }1289    command = ["au.getElement('", elId, "').pinchOpenFromToForDuration(",1290      JSON.stringify(fromPointObject), ",", JSON.stringify(toPointObject), ",",1291      duration + ")"].join('');1292    this.proxy(command, cb);1293  } else {1294    this.proxy("target.pinchOpenFromToForDuration(" + JSON.stringify(fromPointObject) +1295      "," + JSON.stringify(toPointObject) + "," + duration + ")", cb);1296  }1297};1298iOSController.flick = function (startX, startY, endX, endY, touchCount, elId,1299    cb) {1300  var command;1301  if (elId) {1302    if (this.isWebContext()) {1303      return cb(new NotYetImplementedError(), null);1304    }1305    command = ["au.getElement('", elId, "').flick(", startX, ',', startY, ',',1306      endX, ',', endY, ',', touchCount, ")"].join('');1307  } else {1308    command = ["au.flickApp(", startX, ',', startY, ',', endX, ',', endY,1309      ")"].join('');1310  }1311  this.proxyWithMinTime(command, FLICK_MS, cb);1312};1313iOSController.scrollTo = function (elementId, text, direction, cb) {1314  if (this.isWebContext()) {1315    return cb(new NotYetImplementedError(), null);1316  }1317  // we ignore text for iOS, as the element is the one being scrolled too1318  var command = ["au.getElement('", elementId, "').scrollToVisible()"].join('');1319  this.proxy(command, cb);1320};1321iOSController.scroll = function (elementId, direction, cb) {1322  direction = direction.charAt(0).toUpperCase() + direction.slice(1);1323  // By default, scroll the first scrollview.1324  var command = "au.scrollFirstView('" + direction + "')";1325  if (elementId) {1326    if (this.isWebContext()) {1327      return cb(new NotYetImplementedError(), null);1328    }1329    // if elementId is defined, call scrollLeft, scrollRight, scrollUp, and scrollDown on the element.1330    command = ["au.getElement('", elementId, "').scroll", direction, "()"].join('');1331  }1332  this.proxy(command, cb);1333};1334iOSController.shake = function (cb) {1335  this.proxy("au.shake()", cb);1336};1337iOSController.setLocation = function (latitude, longitude, altitude, horizontalAccuracy, verticalAccuracy, course, speed, cb) {1338  var coordinates = {'latitude' : latitude, 'longitude' : longitude};1339  var hasOptions = altitude !== null || horizontalAccuracy !== null || verticalAccuracy !== null || course !== null || speed !== null;1340  if (hasOptions) {1341    var options = {};1342    if (altitude !== null) {1343      options.altitude = altitude;1344    }1345    if (horizontalAccuracy !== null) {1346      options.horizontalAccuracy = horizontalAccuracy;1347    }1348    if (verticalAccuracy !== null) {1349      options.verticalAccuracy = verticalAccuracy;1350    }1351    if (course !== null) {1352      options.course = course;1353    }1354    if (speed !== null) {1355      options.speed = speed;1356    }1357    this.proxy("target.setLocationWithOptions(" + JSON.stringify(coordinates) + "," +1358      JSON.stringify(options) + ")", cb);1359  } else {1360    this.proxy("target.setLocation(" + JSON.stringify(coordinates) + ")", cb);1361  }1362};1363iOSController.hideKeyboard = function (strategy, key, cb) {1364  this.proxy("au.hideKeyboard(" +1365    "'" + strategy + "'" +1366    (key ? ",'" + key + "'" : "") +1367    ")",1368  cb);1369};1370iOSController.url = function (url, cb) {1371  if (this.isWebContext()) {1372    // make sure to clear out any leftover web frames1373    this.curWebFrames = [];1374    this.processingRemoteCmd = true;1375    this.remote.navToUrl(url, function () {1376      cb(null, {1377        status: status.codes.Success.code1378      , value: ''1379      });1380      this.processingRemoteCmd = false;1381    }.bind(this));1382  } else {1383    // in the future, detect whether we have a UIWebView that we can use to1384    // make sense of this command. For now, and otherwise, it's a no-op1385    cb(null, {status: status.codes.Success.code, value: ''});1386  }1387};1388iOSController.getUrl = function (cb) {1389  if (this.isWebContext()) {1390    this.processingRemoteCmd = true;1391    this.remote.execute('window.location.href', function (err, res) {1392      if (err) {1393        cb("Remote debugger error", {1394          status: status.codes.JavaScriptError.code1395        , value: res1396        });1397      } else {1398        cb(null, {1399          status: status.codes.Success.code1400        , value: res.result.value1401        });1402      }1403      this.processingRemoteCmd = false;1404    }.bind(this));1405  } else {1406    cb(new NotImplementedError(), null);1407  }1408};1409iOSController.active = function (cb) {1410  if (this.isWebContext()) {1411    this.executeAtom('active_element', [], function (err, res) {1412      cb(err, res);1413    });1414  } else {1415    this.proxy("au.getActiveElement()", cb);1416  }1417};1418iOSController.isWebContext = function () {1419  return this.curContext !== null && this.curContext !== NATIVE_WIN;1420};1421iOSController.webContextIndex = function () {1422  return this.curContext.replace(WEBVIEW_BASE, "") - 1;1423};1424iOSController.getCurrentContext = function (cb) {1425  var err = null, response = null;1426  if (this.curContext) {1427    response = {1428      status: status.codes.Success.code1429    , value: WEBVIEW_BASE + this.curContext1430    };1431  } else {1432    response = {1433      status: status.codes.Success.code1434    , value: 'NATIVE_APP'1435    };1436  }1437  cb(err, response);1438};1439iOSController.getContexts = function (cb) {1440  this.getContextsAndViews(function (err, richCtxs) {1441    if (err) return cb(err);1442    var ctxs = _(richCtxs).map(function (richCtx) {1443      return richCtx.id;1444    });1445    cb(null, {1446      status: status.codes.Success.code1447    , value: ctxs1448    });1449  });1450};1451iOSController.setContext = function (name, callback, skipReadyCheck) {1452  var cb = function (err, res) {1453    if (!err && res.status === status.codes.Success.code && this.perfLogEnabled) {1454      logger.debug('Starting performance log on ' + this.curContext);1455      this.logs.performance = new IOSPerfLog(this.remote);1456      this.logs.performance.startCapture(function () {1457        callback(err, res);1458      });1459    } else {1460      callback(err, res);1461    }1462  }.bind(this);1463  logger.debug("Attempting to set context to '" + name + "'");1464  if (name === this.curContext) {1465    cb(null, {1466      status: status.codes.Success.code1467    , value: ""1468    });1469  } else if (name === NATIVE_WIN || name === null) {1470    if (this.curContext === null || this.curContext === NATIVE_WIN) {1471      cb(null, {1472        status: status.codes.Success.code1473      , value: ""1474      });1475    } else {1476      this.curContext = null;1477      //TODO: this condition should be changed to check if the webkit protocol is being used.1478      if (this.args.udid) {1479        this.remote.disconnect();1480        this.remote = null;1481      }1482      cb(null, {1483        status: status.codes.Success.code1484      , value: ''1485      });1486    }1487  } else {1488    var idx = name.replace(WEBVIEW_BASE, '');1489    if (idx === WEBVIEW_WIN) {1490      // allow user to pass in "WEBVIEW" without an index1491      idx = '1';1492    }1493    var pickContext = function () {1494      if (_.contains(this.contexts, idx)) {1495        var pageIdKey = parseInt(idx, 10);1496        var next = function () {1497          this.processingRemoteCmd = true;1498          if (this.args.udid === null) {1499            this.remote.selectPage(pageIdKey, function () {1500              this.curContext = idx;1501              this.processingRemoteCmd = false;1502              cb(null, {1503                status: status.codes.Success.code1504              , value: ''1505              });1506            }.bind(this), skipReadyCheck);1507          } else {1508            if (name === this.curContext) {1509              logger.debug("Remote debugger is already connected to window [" + name + "]");1510              this.processingRemoteCmd = false;1511              cb(null, {1512                status: status.codes.Success.code1513              , value: name1514              });1515            } else {1516              this.remote.disconnect(function () {1517                this.curContext = idx;1518                this.remote.connect(idx, function () {1519                  this.processingRemoteCmd = false;1520                  cb(null, {1521                    status: status.codes.Success.code1522                  , value: name1523                  });1524                }.bind(this));1525              }.bind(this));1526            }1527          }1528        }.bind(this);1529        next();1530      } else {1531        cb(null, {1532          status: status.codes.NoSuchContext.code1533        , value: "Context '" + name + "' does not exist"1534        });1535      }1536    }.bind(this);1537    // only get contexts if they haven't already been gotten1538    if (typeof this.contexts === 'undefined') {1539      this.getContexts(function () {1540        pickContext();1541      }.bind(this));1542    } else {1543      pickContext();1544    }1545  }1546};1547iOSController.getWindowHandle = function (cb) {1548  if (this.isWebContext()) {1549    var windowHandle = this.curContext;1550    var response = {1551      status: status.codes.Success.code1552    , value: windowHandle1553    };1554    cb(null, response);1555  } else {1556    cb(new NotImplementedError(), null);1557  }1558};1559iOSController.massagePage = function (page) {1560  page.id = page.id.toString();1561  return page;1562};1563iOSController.getWindowHandles = function (cb) {1564  if (!this.isWebContext()) {1565    return cb(new NotImplementedError(), null);1566  }1567  this.listWebFrames(function (err, pageArray) {1568    if (err) {1569      return cb(err);1570    }1571    this.windowHandleCache = _.map(pageArray, this.massagePage);1572    var idArray = _.pluck(this.windowHandleCache, 'id');1573    // since we use this.contexts to manage selecting debugger pages, make1574    // sure it gets populated even if someone did not use the1575    // getContexts method1576    if (!this.contexts) {1577      this.contexts = idArray;1578    }1579    cb(null, {1580      status: status.codes.Success.code1581    , value: idArray1582    });1583  }.bind(this));1584};1585iOSController.setWindow = function (name, cb, skipReadyCheck) {1586  if (!this.isWebContext()) {1587    return cb(new NotImplementedError(), null);1588  }1589  if (_.contains(_.pluck(this.windowHandleCache, 'id'), name)) {1590    var pageIdKey = parseInt(name, 10);1591    var next = function () {1592      this.processingRemoteCmd = true;1593      if (this.args.udid === null) {1594        this.remote.selectPage(pageIdKey, function () {1595          this.curContext = pageIdKey.toString();1596          this.curWindowHandle = pageIdKey.toString();1597          cb(null, {1598            status: status.codes.Success.code1599          , value: ''1600          });1601          this.processingRemoteCmd = false;1602        }.bind(this), skipReadyCheck);1603      } else {1604        if (name === this.curWindowHandle) {1605          logger.debug("Remote debugger is already connected to window [" + name + "]");1606          cb(null, {1607            status: status.codes.Success.code1608          , value: name1609          });1610        } else if (_.contains(_.pluck(this.windowHandleCache, 'id'), name)) {1611          this.remote.disconnect(function () {1612            this.curContext = name;1613            this.curWindowHandle = name;1614            this.remote.connect(name, function () {1615              cb(null, {1616                status: status.codes.Success.code1617              , value: name1618              });1619            });1620          }.bind(this));1621        } else {1622          cb(null, {1623            status: status.codes.NoSuchWindow.code1624          , value: null1625          });1626        }1627      }1628    }.bind(this);1629    next();1630  } else {1631    cb(null, {1632      status: status.codes.NoSuchWindow.code1633    , value: null1634    });1635  }1636};1637iOSController.closeWindow = function (cb) {1638  if (this.isWebContext()) {1639    var script = "return window.open('','_self').close();";1640    this.executeAtom('execute_script', [script, []], function (err, res) {1641      setTimeout(function () {1642        cb(err, res);1643      }, 500);1644    }, true);1645  } else {1646    cb(new NotImplementedError(), null);1647  }1648};1649iOSController.setSafariWindow = function (windowId, cb) {1650  var checkPages = function (_cb) {1651    this.findElement('name', 'Pages', function (err, res) {1652      if (this.checkSuccess(err, res, _cb)) {1653        this.getAttribute(res.value.ELEMENT, 'value', function (err, res) {1654          if (this.checkSuccess(err, res, _cb)) {1655            if (res.value === "") {1656              _cb(err, res);1657            } else {1658              _cb();1659            }1660          }1661        }.bind(this));1662      }1663    }.bind(this));1664  }.bind(this);1665  var tapPages = function (_cb) {1666    this.findElement('name', 'Pages', function (err, res) {1667      if (this.checkSuccess(err, res, _cb)) {1668        this.nativeTap(res.value.ELEMENT, function (err, res) {1669          if (this.checkSuccess(err, res, _cb)) {1670            _cb();1671          }1672        }.bind(this));1673      }1674    }.bind(this));1675  }.bind(this);1676  var selectPage = function (_cb) {1677    this.findElement('class name', 'UIAPageIndicator', function (err, res) {1678      if (this.checkSuccess(err, res, _cb)) {1679        this.setValue(res.value.ELEMENT, windowId, function (err, res) {1680          if (this.checkSuccess(err, res, _cb)) {1681            _cb();1682          }1683        }.bind(this));1684      }1685    }.bind(this));1686  }.bind(this);1687  var doneWithPages = function (_cb) {1688    this.findElement('name', 'Done', function (err, res) {1689      if (this.checkSuccess(err, res, _cb)) {1690        this.nativeTap(res.value.ELEMENT, function (err, res) {1691          if (this.checkSuccess(err, res, _cb)) {1692            _cb();1693          }1694        }.bind(this));1695      }1696    }.bind(this));1697  }.bind(this);1698  async.series([checkPages, tapPages, selectPage, doneWithPages],1699      function (err) { cb(err); });1700};1701iOSController.checkSuccess = function (err, res, cb) {1702  if (typeof res === "undefined") {1703    cb(err, {1704      status: status.codes.UnknownError.code...ios.js
Source:ios.js  
...1507  async.waterfall([1508    this.findElement.bind(this, 'name', 'URL'),1509    function (res, cb) {1510      this.implicitWaitMs = oldImpWait;1511      this.nativeTap(res.value.ELEMENT, noArgsCb(cb));1512    }.bind(this),1513    this.findElements.bind(this, 'name', 'Address'),1514    function (res, cb) {1515      var addressEl = res.value[res.value.length -1].ELEMENT;1516      this.setValueImmediate(addressEl, initialUrl, noArgsCb(cb));1517    }.bind(this),1518    this.findElement.bind(this, 'name', 'Go'),1519    function (res, cb) {1520      this.nativeTap(res.value.ELEMENT, noArgsCb(cb));1521    }.bind(this)1522  ], function () {1523    this.navToViewWithTitle(/.*/i, function (err) {1524      if (err) return cb(err);1525      // Waits for page to finish loading.1526      this.remote.pageUnload(cb);1527    }.bind(this));1528  }.bind(this));1529};1530IOS.prototype.navToViewThroughFavorites = function (cb) {1531  logger.debug("We're on iOS7+ simulator: clicking apple button to get into " +1532              "a webview");1533  var oldImpWait = this.implicitWaitMs;1534  this.implicitWaitMs = 7000; // wait 7s for apple button to exist1535  this.findElement('xpath', '//UIAScrollView[1]/UIAButton[1]', function (err, res) {1536    this.implicitWaitMs = oldImpWait;1537    if (err || res.status !== status.codes.Success.code) {1538      var msg = "Could not find button to click to get into webview. " +1539                "Proceeding on the assumption we have a working one.";1540      logger.error(msg);1541      return this.navToViewWithTitle(/.*/i, cb);1542    }1543    this.nativeTap(res.value.ELEMENT, function (err, res) {1544      if (err || res.status !== status.codes.Success.code) {1545        var msg = "Could not click button to get into webview. " +1546                  "Proceeding on the assumption we have a working one.";1547        logger.error(msg);1548      }1549      this.navToViewWithTitle(/apple/i, cb);1550    }.bind(this));1551  }.bind(this));1552};1553IOS.prototype.navToViewWithTitle = function (titleRegex, cb) {1554  logger.debug("Navigating to most recently opened webview");1555  var start = Date.now();1556  var spinTime = 500;1557  var spinHandles = function () {1558    this.getLatestWebviewContextForTitle(titleRegex, function (err, res) {1559      if (err) {1560        cb(new Error("Could not navigate to webview! Err: " + err));1561      } else if (!res) {1562        if ((Date.now() - start) < 90000) {1563          logger.warn("Could not find any webviews yet, refreshing/retrying");1564          if (this.args.udid || !this.capabilities.safari) {1565            return setTimeout(spinHandles, spinTime);1566          }1567          this.findUIElementOrElements('accessibility id', 'ReloadButton',1568              '', false, function (err, res) {1569            if (err || !res || !res.value || !res.value.ELEMENT) {1570              logger.warn("Could not find reload button, continuing");1571              setTimeout(spinHandles, spinTime);1572            } else {1573              this.nativeTap(res.value.ELEMENT, function (err, res) {1574                if (err || !res) {1575                  logger.warn("Could not click reload button, continuing");1576                }1577                setTimeout(spinHandles, spinTime);1578              }.bind(this));1579            }1580          }.bind(this));1581        } else {1582          cb(new Error("Could not navigate to webview; there aren't any!"));1583        }1584      } else {1585        var latestWindow = res;1586        logger.debug("Picking webview " + latestWindow);1587        this.setContext(latestWindow, function (err) {...context.js
Source:context.js  
...282  this.implicitWaitMs = 7000;283  // find the url bar, and tap on it284  let el = await this.findElement('name', 'URL');285  this.implicitWaitMs = oldImpWait;286  await this.nativeTap(el.ELEMENT);287  // get the last address element and set the url288  let els = await this.findElements('name', 'Address');289  let addressEl = _.last(els).ELEMENT;290  await this.setValueImmediate(initialUrl, addressEl);291  // make it happen292  el = await this.findElement('name', 'Go');293  await this.nativeTap(el.ELEMENT);294  await this.navToViewWithTitle(/.*/i);295  // wait for page to finish loading.296  await this.remote.pageUnload();297};298extensions.navToViewThroughFavorites = async function () {299  logger.debug('We are on iOS7+ simulator: clicking apple button to get into a webview');300  let oldImpWait = this.implicitWaitMs;301  this.implicitWaitMs = 7000; // wait 7s for apple button to exist302  let el;303  try {304    el = await this.findElement('xpath', '//UIAScrollView[1]/UIAButton[1]');305  } catch (err) {306    let msg = 'Could not find button to click to get into webview. ' +307              'Proceeding on the assumption we have a working one.';308    logger.error(msg);309    this.implicitWaitMs = oldImpWait;310    return await this.navToViewWithTitle(/.*/i);311  }312  this.implicitWaitMs = oldImpWait;313  try {314    await this.nativeTap(el.ELEMENT);315  } catch (err) {316    let msg = 'Could not click button to get into webview. ' +317              'Proceeding on the assumption we have a working one.';318    logger.error(msg);319  }320  await this.navToViewWithTitle(/apple/i);321};322extensions.navToViewWithTitle = async function (titleRegex) {323  logger.debug('Navigating to most recently opened webview');324  let start = Date.now();325  let spinTime = 500;326  let spinHandles = async () => {327    let res;328    try {329      res = await this.getLatestWebviewContextForTitle(titleRegex);330    } catch (err) {331      throw new Error(`Could not navigate to webview! Err: ${err.message}`);332    }333    if (res) {334      let latestWindow = res;335      logger.debug(`Picking webview '${latestWindow}'`);336      await this.setContext(latestWindow);337      await this.remote.cancelPageLoad();338      return;339    }340    // no webview was found341    if ((Date.now() - start) >= 90000) {342      // too slow, get out343      throw new Error('Could not navigate to webview; there are none!');344    }345    logger.warn("Could not find any webviews yet, refreshing/retrying");346    if (this.isRealDevice() || !this.opts.safari) {347      // on a real device, when not using Safari, we just want to try again348      await B.delay(spinTime);349      return await spinHandles();350    }351    // find the reload button and tap it, if possible352    let element;353    try {354      element = await this.findUIElementOrElements('accessibility id', 'ReloadButton', '', false);355      await this.nativeTap(element.ELEMENT);356    } catch (err) {357      logger.warn(`Error finding and tapping reload button: ${err.message}`);358      logger.warn('Retrying.');359      await B.delay(spinTime);360      return await spinHandles();361    }362  };363  await spinHandles();364};365helpers.closeAlertBeforeTest = async function () {366  let present = await this.uiAutoClient.sendCommand('au.alertIsPresent()');367  if (!present) {368    return false;369  }...gesture.js
Source:gesture.js  
...22  } else {23    if (this.opts.useRobot) {24      /* TODO */throw new errors.NotYetImplementedError();25    } else {26      await this.nativeTap(el);27    }28  }29};30commands.clickCurrent = async function (/*button*/) {31  if (this.isWebContext()) {32    if (_.isNull(this.curWebCoords)) {33      throw new errors.UnknownError('Cannot call click() before calling moveTo() to set coords');34    }35    await this.clickWebCoords();36  } else {37    if (this.curCoords === null) {38      throw new errors.UnknownError("Cannot call click() before calling moveTo() to set coords");39    }40    await this.clickCoords(this.curCoords);...Using AI Code Generation
1const { nativeTap } = driver;2await nativeTap({ x: 100, y: 100 });3await driver.touch('tap', { x: 100, y: 100 });4await driver.touchPerform([{5  options: { x: 100, y: 100 }6}]);7await driver.performTouch({8  options: { x: 100, y: 100 }9});10await driver.performMultiAction({11  actions: [{12    options: { x: 100, y: 100 }13  }]14});15await driver.performActions({16  actions: [{17    parameters: { pointerType: 'touch' },18    actions: [{19    }, {20    }, {21    }, {22    }]23  }]24});25await driver.touchAction({26  options: { x: 100, y: 100 }27});28await driver.performTouchAction({29  options: { x: 100, y: 100 }30});31await driver.performTouchAction({32  options: { x: 100, y: 100 }33});34await driver.performTouchAction({35  options: { x: 100,Using AI Code Generation
1this.nativeTap(0, 0);2this.nativeTap(100, 100);3this.nativeTap(0, 0);4this.nativeTap(100, 100);5this.nativeTap(0, 0);6this.nativeTap(100, 100);7this.nativeTap(0, 0);8this.nativeTap(100, 100);9this.nativeTap(0, 0);10this.nativeTap(100, 100);11this.nativeTap(0, 0);12this.nativeTap(100, 100);13this.nativeTap(0, 0);14this.nativeTap(100, 100);15this.nativeTap(0, 0);16this.nativeTap(100, 100);17this.nativeTap(0, 0);18this.nativeTap(100, 100);19this.nativeTap(0, 0);20this.nativeTap(100, 100);21this.nativeTap(0, 0);22this.nativeTap(100, 100);23this.nativeTap(0, 0);24this.nativeTap(100, 100);25this.nativeTap(0,Using AI Code Generation
1var wd = require('wd');2var assert = require('assert');3var caps = {4};5var driver = wd.promiseChainRemote('localhost', 4723);6driver.init(caps)7  .then(function () {8    return driver.sleep(5000);9  })10  .then(function () {11    return driver.elementByAccessibilityId('My Native Button');12  })13  .then(function (el) {14    return driver.nativeTap(el);15  })16  .catch(function (err) {17    console.log(err);18  });19- (void)pressButton:(id)sender {20  NSLog(@"Button Pressed");21  XCUIApplication *app = [[XCUIApplication alloc] init];22  XCUIElement *myNativeButton = app.buttons[@"My Native Button"];23  [myNativeButton tap];24}Using AI Code Generation
1var wd = require('wd');2var assert = require('assert');3var chai = require('chai');4var chaiAsPromised = require('chai-as-promised');5var should = chai.should();6chai.use(chaiAsPromised);7var browser = wd.promiseChainRemote({8});9browser.on('status', function(info) {10  console.log(info);11});12browser.on('command', function(meth, path, data) {13  console.log(' > ' + meth, path, data || '');14});15  .init({16  })17  .then(function() {18      .elementById('myElement')19      .then(function(el) {20        return browser.nativeTap(el);21      })22      .sleep(5000)23      .quit();24  })25  .catch(function(err) {26    console.log(err);27  });28> POST /wd/hub/session/7c3d1a9c-9e22-4d0f-9d6e-3d7f0b3e2c7b/element/0.16894574961425033-1/tap {"element":"0.16894574961425033-1"}Using AI Code Generation
1describe('test', function() {2  it('test', async function() {3    await driver.nativeTap({ x: 100, y: 100 });4  });5});6commands.nativeTap = async function (opts = {}) {7  const {x, y} = opts;8  const action = new wd.TouchAction(this);9  action.press({x, y}).release();10  return await this.performTouchAction(action);11};12commands.performTouchAction = async function (action) {13  if (this.isWebContext()) {14    return await action.perform();15  }16  const actions = [action];17  return await this.proxyCommand('/wda/touch/perform', 'POST', {actions});18};19commands.performTouchAction = async function (action) {20  if (this.isWebContext()) {21    return await action.perform();22  }23  const actions = [action];24  return await this.proxyCommand('/wda/touch/perform', 'POST', {actions});25};26commands.proxyCommand = async function (url, method, body) {27  return await this.proxyCommandTo(url, method, body, this.opts.device.udid);28};Using AI Code Generation
1this.nativeTap(this.elementId);2this.nativeTap = function (elementId) {3    return this.requestHandler.create({4    });5};6commands.tap = async function (elementId) {7    return await this.nativeTap(elementId);8};9commands.nativeTap = async function (elementId) {10    return await this.nativeTap(elementId);11};12commands.nativeTap = function (elementId) {13    return this.requestHandler.create({14    });15};16commands.nativeTap = function (elementId) {17    return this.requestHandler.create({18        path: `/session/:sessionId/appium/element/${elementId}/tap`,19    });20};21commands.nativeTap = function (elementId) {22    return this.requestHandler.create({23        path: `/session/:sessionId/appium/element/${elementId}/tap`,24    });25};26commands.nativeTap = function (elementId) {27    return this.requestHandler.create({28        path: `/session/:sessionId/appium/element/${elementId}/tap`,29    });30};31commands.nativeTap = function (elementId) {32    return this.requestHandler.create({33        path: `/session/:sessionId/appium/element/${elementId}/tap`,34    });35};36commands.nativeTap = function (elementId) {37    return this.requestHandler.create({38        path: `/session/:sessionId/appium/element/${elementId}/tap`,39    });40};41commands.nativeTap = function (elementId) {42    return this.requestHandler.create({Using AI Code Generation
1describe('Test Native Tap', function() {2    it('should tap on the element', function() {3        var el = driver.elementByAccessibilityId('Test Native Tap');4        el.click();5        driver.waitForElementByAccessibilityId('Test Native Tap');6        driver.nativeTap(100, 100);7        driver.waitForElementByAccessibilityId('Test Native Tap');8    });9});10describe('Test Native Tap', function() {11    it('should tap on the element', function() {12        var el = driver.elementByAccessibilityId('Test Native Tap');13        el.click();14        driver.waitForElementByAccessibilityId('Test Native Tap');15        driver.nativeTap(100, 100);16        driver.waitForElementByAccessibilityId('Test Native Tap');17    });18});19describe('Test Native Tap', function() {20    it('should tap on the element', function() {21        var el = driver.elementByAccessibilityId('Test Native Tap');22        el.click();23        driver.waitForElementByAccessibilityId('Test Native Tap');24        driver.nativeTap(100, 100);25        driver.waitForElementByAccessibilityId('Test Native Tap');26    });27});28describe('Test Native Tap', function() {29    it('should tap on the element', function() {30        var el = driver.elementByAccessibilityId('Test Native Tap');31        el.click();32        driver.waitForElementByAccessibilityId('Test Native Tap');33        driver.nativeTap(100, 100);34        driver.waitForElementByAccessibilityId('Test Native Tap');35    });36});37describe('Test Native Tap', function() {38    it('should tap on the element', function() {39        var el = driver.elementByAccessibilityId('Test Native Tap');40        el.click();41        driver.waitForElementByAccessibilityId('Test Native Tap');Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
