XPath on iOS causing a crash?

I am trying to use Appium to automated some iOS testing. Everything was going fine until I try to interact with one specific object. The inspector says the xpath is

(//XCUIElementTypeStaticText[@name="Terms and Conditions"])[1]

but when I try to use that with

@iOSFindBy(xpath = "(//XCUIElementTypeStaticText[@name=\"Terms and Conditions\"])[1]")

My app quits out and appium sits there a really long time before returning a NoSuchElementException. Any ideas why this would be happening? I am copying the xpath directly from the inspector.

Unfortunately I do not have the ability to add an accessibility id to the app at the moment, so I need to figure out this xpath thing.

@nwelna try better way:

    @iOSXCUITFindBy(iOSNsPredicate = "type == 'XCUIElementTypeStaticText' AND name == 'Terms and Conditions' AND visible == 1")
    private List<IOSElement> element;

// in code you can
String text = element.get(3).getText(); // get text of 4th element

Is there a way to get that specific element using the predicates? I am trying to do the following:

@iOSFindBy(xpath = "(//XCUIElementTypeStaticText[@name=\"Terms and Conditions\"])[1]")
@AndroidFindBy(accessibility = "Terms and Conditions")
public MobileElement termsAndConditions;

Don’t know why android has an accessibility id and iOS doesn’t, but that’s the situation I am in. I’d rather not have to have two different test flows between the two OSes because the app functions the same on both.

@nwelna i gave you predicate for iOS try

@nwelna for iOS see:

public @interface iOSXCUITFindBy {

    /**
     * The Class Chain locator is similar to xpath, but it's faster and can only
     * search direct children elements. See the
     * <a href="https://github.com/facebook/WebDriverAgent/wiki/Queries">
     * documentation</a> for more details.
     */
    String iOSClassChain() default "";

    /**
     * The NSPredicate class is used to define logical conditions used to constrain
     * a search either for a fetch or for in-memory filtering.
     */
    String iOSNsPredicate() default "";

    /**
     * It an UI automation accessibility Id which is a convenient to iOS.
     * About iOS accessibility
     * See  <a href="https://goo.gl/a3AivX">UIAccessibilityIdentification</a>
     */
    String accessibility() default "";

    /**
     * It is an id of the target element.
     */
    String id() default "";

    /**
     * It is a name of a type/class of the target element.
     */
    String className() default "";

    /**
     * It is a desired element tag.
     */
    String tagName() default "";

    /**
     * It is a xpath to the target element.
     */
    String xpath() default "";

    /**
     * @return priority of the searching. Higher number means lower priority.
     */
    int priority() default 0;
}

That works! Thank you!

How did you find out that this is list of elements and not single element ?

@VikramVI i do not understand you…

    @iOSXCUITFindBy(iOSNsPredicate = "type == 'XCUIElementTypeStaticText' AND name == 'Terms and Conditions' AND visible == 1")
    private List<IOSElement> elList;

    System.out.println(elList.size()) // gives it size and you can check what you need it is ONE expected or multiple depending of test

Ok, after reading again original post. I saw that @nwelna mentioned about single object with xpath (//XCUIElementTypeStaticText[@name="Terms and Conditions"])[1]

I was confused why you did private List<IOSElement> element; instead of private IOSElement element ?

@VikramVI only just when we need NOT first :slight_smile:

I only needed the first (and only in my case) element that matched those conditions on my screen, however if there were multiple elements that matched that Predicate you would use a list, and pick the element you needed from that list. The annotation works both ways.

Try
@iOSFindBy(xpath = “(//XCUIElementTypeStaticText[@name=“Terms and Conditions”])”)

without [1], it will search through the whole structure and look for attribute @name in all XCUIElementTypeStaticText elements.
there is also a chance that element with false visibility, so you need to check IOSFindBy method and see what it returns, i have a lot of such cases
if visibility = false i use isPresent method (wait.until(presenceOfElementLocated(locator)):wink:
if visibility = true i use iVisible method (wait.until(visibilityOfElementLocated(locator)):wink:

I had tried that as well, didn’t work either. App would force close the instant Appium tried to look up the element. Either way, the solution @Aleksei provided works, and I believe is preferred over xpath anyway.

@nwelna What version of Appium are you using that was crashing? I am seeing something similar while trying the Appium 1.6.6-beta4 build.

1.6.5 with Java Client 5.0.0-BETA9