Search code examples
javascriptiosappiumwebdriver-ioperfecto

How to "tap" and/or "press" a button using Appium / webdriverio?


I am trying to, after my app launches, to perform a tap/press action on a button element using an XPath selector. This app is a Hybrid app (native + some webviews).

I am having issues as the docs for Appium seem to be misleading (potentially).

getDriver():

  const driver = await remote({
    capabilities: {
      platformName: 'IOS',
      browserName: 'mobileOS',
      deviceName: config.deviceName,
      securityToken: config.securityToken,
      app: 'PUBLIC:my-app.ipa'
    },
    hostname: config.hostname,
    path: config.path,
    port: config.port,
    logLevel: config.logLevel
  });

Here is how I get my driver up and running. This starts the device, and opens up the application that I install.

I try and perform a tap or press or click action:

const el = driver.$('//*[@name="MyButton"]');
driver.touchPerform([
      { action: 'press', options: { element: el } },
      { action: 'release'}
    ]);

The error I get is: Request failed due to java.util.LinkedHashMap cannot be cast to java.lang.String

or

const el = driver.$('//*[@name="MyButton"]');
driver.touchPerform(
      { action: 'tap', options: { element: el } }
);

The error I get is: Error getting WebDriver: Malformed type for "actions" parameter of command touchPerform Expected: object[] Actual: object

Now originally, I follow this doc: http://appium.io/docs/en/commands/interactions/touch/tap/ and/or http://appium.io/docs/en/commands/interactions/touch/touch-perform/

Now I may understand why the touchPerform( press ) may not work due to it specifying on other docs that it can only use x,y potentially.

But the tap is what is throwing me off. If I wrap the object I send in driver.touchPerform in an array like so:

const el = driver.$('//*[@name="MyButton"]');
driver.touchPerform([
      { action: 'tap', options: { element: el } }
]);

I get the same error as the previous: Request failed due to java.util.LinkedHashMap cannot be cast to java.lang.String

My question is, am I using the wrong selection or touch type event to click on a button on a mobile device?

I have also tried the http://appium.io/docs/en/commands/element/actions/click/ method, and when I try that it tells me driver.$(..).click() is not a function

Any help is greatly appreciated.


Solution

  • To anyone thats having issues like this, I finally found the answer to my question.

    Even though I am using webdriverio version where the first example on this: http://appium.io/docs/en/commands/element/find-element/

    should work, it does not. It's actually the third example that works for me to find the element.

    await driver.findElement('name', selector);
    

    The other issue I was having was my XPath in correlation to Perfecto was wrong. In javascript, my xpath would have worked, but perfecto defines its xpath very specifically. You need to go (on Perfecto) to the Automation tab in the old lab structure. Go to "Object Spy" and you will be able to click on elements similar to a Chrome Inspect tool.

    The XPath that I thought it would be was '//*[@name="MyButton"]' but in reality it was: //AppiumAUT/XCUIElementTypeApplication[1]/XCUIElementTypeWindow[3]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeNavigationBar[1]/XCUIElementTypeButton[2] What I really needed to be doing was using the locator strategy correctly.

    findElement(locator strategy, selector)
    

    where the locator strategy is here: http://appium.io/docs/en/commands/element/find-elements/index.html#selector-strategies

    Then for clicking:

    driver.elementClick(element.ELEMENT);
    

    This is no where in the appium docs, or on webdriverio docs. But some digging in git inside appium's sample code. This handy dandy sample code is there for basic interactions: https://github.com/appium/appium/blob/master/sample-code/javascript-webdriverio/test/basic/ios-basic-interactions.test.js