Appium: How to wait for a new item with the same name as visible to appear on the screen?

advertisements

We're using Appium with iOS Simulator and test functions written in Java.

We have an iOS App with screen 1 containing a UICollection view, and tell Appium to click on one of its elements.

This opens screen 2 (and the scrolling animation takes about 500 ms), which also contains an UICollection view. I want to find out the size of the UICollection view of the second screen with Appium.

The problem is that Appium is too fast and executes the findElements() method directly after the click, which causes it to find the UICollection view of the first screen.

clickOnElementOnFirstScreen();

webDriver.findElements( By.className( "UIACollectionCell" ) ).size();
// is supposed to find the UICollection view on the second screen,
// but actually finds the UICollection view on the first screen

Appium provides several waiting functions. However as far as I can see all of them are intended to be used in this fashion: "wait until element at location X / with name X becomes visible"

If I try to use these waiting functions, they don't wait at all because they immediately find the UICollection view of the first screen, which has the same location and name as the one on the second screen.

The only solution I have found is to use Thread.sleep:

Thread.sleep(1000);
webDriver.findElements( By.className( "UIACollectionCell" ) ).size();

But we don't want to use Thread.sleep in code that will run on the client's server on hundreds of tests.

We might be able to modify the App and enter metadata into the views so that Appium is able to distinguish them, but this situation occurs in several places and the App is being programmed by the client, so we want to avoid this too.

What is a simple and safe way to wait for the new screen to appear, without modifying the code of the iOS App?


I have found only dirty workaround for this issue.

static waitFor(Duration duration) {
        try {
            def WebDriverWait wait = new WebDriverWait(mobileDriver, duration.standardSeconds)
            wait.until(visibilityOfElementLocated(By.xpath("//Fail")))
            //Wait until false case is visible to ensure proper timeout
        } catch (Exception e) {
        }
    }