Mike Collins
Mike Collins

Reputation: 4559

Appium: How to iterate over a listview of unknown length?

I have a list view with a hierarchy I theoretically have no knowledge of. I am attempting to accept a String array and create MobileElements for each string in it, but due to the way I've automated (PageFactory) defining my elements via annotations, they cannot use variables. I also don't know that it's valid or proper to define my annotations inside a method.

The code I've written, which obviously does not compile follows:

public void selectLocation(String[] location) {

    List<MobileElement> locationsList = new ArrayList<>();
    for(int i = 0; i < location.length; i++) {

        @iOSFindBy(accessibility = location[i])
        @AndroidFindBy(xpath = "//android.widget.TextView[@text='" + location[i] + "']")
        locationsList.add(i);
    }
    for (int i = 0; i < location.length; i++) {
        locationsList.get(i).click();
    }
}

I'm assuming the proper way to do this is wholly different from the way I've implemented.

My list hierarchy is similar to the following; my end point could vary depending on the branch I go down:

Upvotes: 1

Views: 2376

Answers (3)

Mike Collins
Mike Collins

Reputation: 4559

I now look for a matching element. If I don't find it, I swipe further into the list. If the element doesn't exist I obviously run into problems, but not really an issue in my case since that’d be a failing test.

while (!driver.findElementById(currentLocation).isDisplayed()) {
   driver.swipe(startX, startY, startX, endY, 100);
}
driver.findElementById(currentLocation).click();

Yes, I also realize .swipe() is deprecated, but it still works for me and I'd rather not rewrite all my code with TouchActions until necessary.

Upvotes: 2

James MacDonald
James MacDonald

Reputation: 11

You can just loop over the elements themselves.

....

for(MobileElement location: locationsList) {
    for(int p = 0; p < location.length; p++) {
        if (location.getText().equals(location[p])) {
            location.click();
        }
    }
}

Upvotes: 1

Mike Collins
Mike Collins

Reputation: 4559

I ended up using the "FindsBys" functions to create an array of all matching elements. I then loop through those elements looking for a match to one of my strings.

@AndroidFindBys({@AndroidFindBy(xpath = "//android.widget.TextView")})
@iOSFindBys({@iOSFindBy(xpath = "//XCUIElementTypeStaticText")})
private List<MobileElement> locationsList;

...

public void selectLocation(String[] location)
{
    for(int i = 0; i < locationsList.size(); i++)
        for(int p = 0; p < location.length; p++) {
            if (locationsList.get(i).getText().equals(location[p])) {
                locationsList.get(i).click();
            }
        }
}

It's not foolproof (if you have duplicate strings at different levels of your hierarchy you may run into issues), but it works for my use-case and should be able to guide anyone looking for a stronger solution.

Upvotes: 1

Related Questions