I am trying to wait on a set of elements using FluentWait
, however it’s not correctly waiting/polling for the specified element if I were to use Function<AppiumDriver, List<MobileElement>
I am able to correctly wait for the elements when using ExpectedConditions
with FluentWait
.
Is there something that I might be overlooking?
FluentWait Code
public static Wait<AppiumDriver<MobileElement>> fluentWait(
int timeoutTime,
int pollTime,
Class<? extends Throwable>... ignoredExceptions)
{
return new FluentWait<>(DriverSingleton.getDriver())
.withTimeout(Duration.ofSeconds(timeoutTime))
.pollingEvery(Duration.ofSeconds(pollTime))
.ignoreAll(Arrays.asList(ignoredExceptions));
}
public static Function<AppiumDriver<MobileElement>, List<MobileElement>> fluentWaitFunctionMany(By by)
{
return new AppiumFunction<AppiumDriver<MobileElement>, List<MobileElement>>()
{
@NullableDecl
@Override
public List<MobileElement> apply(@NullableDecl AppiumDriver<MobileElement> driver)
{
if (driver == null)
{
throw new IllegalStateException("Driver parameter is null");
}
return driver.findElements(by);
}
};
}
public static List<MobileElement> fluentlyWaitForMany(
By by,
int timeoutTime,
int pollTime,
Class<? extends Throwable>... ignoredExceptions)
{
logger.info("Fluently Waiting for many {} | Timeout: {} | Polling: {}", by.toString(), timeoutTime, pollTime);
return fluentWait(timeoutTime, pollTime, ignoredExceptions).until(fluentWaitFunctionMany(by));
}
public static List<MobileElement> fluentlyWaitForManyWithDefaultExceptions(By by, int timeoutTime, int pollTime)
{
return fluentlyWaitForMany(by, timeoutTime, pollTime, NoSuchElementException.class, StaleElementReferenceException.class);
}
The element that I’m waiting on:
private static final By contentItemsBy = By.xpath("//*[@class='android.widget.LinearLayout and count(android.widget.FrameLayout)=2]");
FluentWait
with Function<AppiumDriver, List<MobileElement>
:
public void deleteAllContentItems()
{
logger.info("=====Started Deleting Library Content====");
List<MobileElement> contentItems = WaitUtil.fluentlyWaitForManyWithDefaultExceptions(contentItemsBy, 10, 1);
logger.info("Initial Content Item Size: {}", contentItems.size());
while (contentItems.isEmpty())
{
contentItems = WaitUtil.fluentlyWaitForManyWithDefaultExceptions(contentItemsBy, 10, 1);
logger.info("Testing: {}", contentItems.size());
}
logger.info("=====Finished Deleting Library Content====");
}
Results:
| 2019-05-28 | 15:13:51:111 | [main] INFO PageObject - =====Started Deleting Library Content====
| 2019-05-28 | 15:13:51:111 | [main] INFO WaitUtil - Fluently Waiting for many By.xpath: //*[@class='android.widget.LinearLayout' and count(android.widget.FrameLayout)=2] | Timeout: 10 | Polling: 1
| 2019-05-28 | 15:13:51:561 | [main] INFO PageObject - Initial Content Item Size: 0
| 2019-05-28 | 15:13:51:562 | [main] INFO WaitUtil - Fluently Waiting for many By.xpath: //*[@class='android.widget.LinearLayout' and count(android.widget.FrameLayout)=2] | Timeout: 10 | Polling: 1
| 2019-05-28 | 15:13:52:411 | [main] INFO PageObject - Testing: 2
| 2019-05-28 | 15:13:52:411 | [main] INFO PageObject - =====Finished Deleting Library Content====
As you can see for the results above, it was supposed to wait for 10 seconds, but it does not seem to be doing so and has to go through the second while
loop.
FluentWait
with ExpectedConditions
:
public void deleteAllContentItems()
{
logger.info("=====Started Deleting Library Content====");
List<WebElement> contentItems = WaitUtil.fluentWait(10, 1, NoSuchElementException.class)
.until(ExpectedConditions.presenceOfAllElementsLocatedBy(contentItemsBy));
logger.info("Initial Content Item Size: {}", contentItems.size());
while (contentItems.isEmpty())
{
contentItems = WaitUtil.fluentWait(10, 1, NoSuchElementException.class)
.until(ExpectedConditions.presenceOfAllElementsLocatedBy(contentItemsBy));
logger.info("Testing: {}", contentItems.size());
}
logger.info("=====Finished Deleting Library Content====");
}
Results:
| 2019-05-28 | 14:44:33:472 | [main] INFO PageObject - =====Started Deleting Library Content====
| 2019-05-28 | 14:44:34:918 | [main] INFO PageObject - Initial Content Item Size: 1
| 2019-05-28 | 14:44:34:918 | [main] INFO PageObject - =====Finished Deleting Library Content====
The ExpectedConditions
is doing its job properly by waiting and does not need to go through the second while
loop.
Extra Details:
I’ve also added an implicit wait to each PageObject class, if that is somehow conflicting with FluentWait.
public BasePage(AppiumDriver<MobileElement> driver, Class c) {
this.driver = (AndroidDriver) driver;
logger = LoggerFactory.getLogger(c);
PageFactory.initElements(new AppiumFieldDecorator(this.driver, Duration.ofSeconds(10)), this);
}
Environment:
Appium Java Client - 7.0.0
Appium Server Desktop Client - Version 1.13.0 (1.13.0.20190502.1)
Mobile Platform: Samsung Galaxy Tablet S4