Java client - temporary find element timeout

I’m implementing my own scroll method, because none of the built-in ones seem to work.

After doing a swipe, I’d like to check if the targeted element is on-screen.

I’m using driver.manage.timeouts().implicitlyWait(25, TimeUnit.SECONDS);. I don’t want to change that since there seems to be no way to restore it.

Problem is, everything I do seems to respect the implictlyWait setting.

here’s the only thing which i think might work, but still uses the 25s timeout

WebDriverWait wait = new WebDriverWait(driver, 1);
wait.until(ExpectedConditions.elementToBeClickable(By.id("foobar"))) // still waits 25 seconds

TL;DR: How do I find an element with a temporary timeout for that one request, without modifying any global state?

Could you add why this doesn’t work? Seems pretty straightforward.

Maybe it would work with a FluentWait:
https://appium.github.io/java-client/io/appium/java_client/AppiumFluentWait.html

FluentWait might work better using the .ignoring parameter, so you ignore the elementNotFound exception until the timeout expires.

It uses the 25s timeout. no idea why. Edited the original post to clarify. Trying a FluentWait now.

Doesn’t seem to change anything. I believe it’s still internally calling driver.findElement, which still blocks for 25 seconds. Hypothesis: FluentWait and WebDriverWait are the same thing with different APIs, although FluentWait has more options.

FluentWait wait = new FluentWait(driver)
    .withTimeout(Duration.ofSeconds(5))
    .pollingEvery(Duration.ofSeconds(1))
    .ignoring(Exception.class);
// still blocks for 25 seconds
wait.until(ExpectedConditions.elementToBeClickable(By.id("foobar")))

Right. FluentWait polls for the element using .pollingEvery(seconds), and during that poll it can ignore an exception with .ignoring(exception). If you are getting a elementMissing exception, you can ignore it for the duration that you’d like to poll. Looks like you’ve set .withTimeout to 5 seconds, maybe give it more time? The nice thing about the FluentWait is that if the element is found before the .withTimeout time expires it will return the element. So setting that to a very large value (say 30 seconds) should simply return the element before that time is reached. This is a very good way to stabilize tests.

  1. just in case http://appium.io/docs/en/writing-running-appium/tutorial/swipe-tutorial/
  2. after scroll do not look for x sec better user simple findElement and try tap directly. and limit all with time you want:
// add set implicit wait to 1 sec
long startTime = System.currentTimeMillis();
do {
  if (tap(driver.findElement(MobileBy.id("element_id")))) // this is fast element search and tap
    break;
  do_scroll();
} while (System.currentTimeMillis() < startTime + 20 * 1000); // 20 sec MAX
// add restore implicit wait to 25 sec

// tap function is any way of tap you know (they are many. i like w3c way today) with return result true / false
  1. way with Appium annotation:
    @iOSXCUITFindBy(id = "iOS_ID")
    @AndroidFindBy(id = "Android_ID")
    private WebElement myElement;

    public boolean isMyElementLoaded(final int sec) {
        setLookTiming(sec);
        boolean bool = false;
        try {
            bool = !((RemoteWebElement) myElement).getId().isEmpty(); 
        } catch (Exception e) {
        }
        setDefaultTiming(); // restoring default timeout e.g. 15 sec
        return bool;
    }

    public boolean tapMyElement(final int sec) {
        setLookTiming(sec);
        boolean bool = tap(myElement);
        setDefaultTiming(); // restoring default timeout e.g. 15 sec
        return bool;
    }

    public void setLookTiming(int sec) {
         PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(sec)), this);
    }

  1. finally why your example does not work -> cause:
elementToBeClickable -> visibilityOfElementLocated(locator).apply(driver); 
// where
visibilityOfElementLocated -> return elementIfVisible(driver.findElement(locator));
// where
`driver.findElement` uses your Implicit time of 25 sec

FluentWait blocks for the full 25 seconds from driver.manage().timeouts().implicitlyWait(25) regardless of what I set FleuntWait’s options to. I don’t want to change the implicitlyWait setting because there seems to be no way to restore it.

that’s what i’m using to swipe; seems to work fine.

still blocks for 25 seconds.

for various reasons, the element ID i’m looking for is dynamic. I can’t hard-code it in an annotation. Is there another way to do this?

Cause you set it to 25

For annotation no dynamic way :upside_down_face:

I know. That timeout is used for the rest of the test code. I don’t want to change it, because there seems to be no way to restore it.

You may change temporarily in needed function and restore inside it.

There doesn’t seem to be a way to restore the timeout after changing it.

Up to you. All depends on your code.
E.g. i use Appium annotation and change page element init time dynamically.