Temporarily bypassing implicit waits with WebDriver
Asked Answered
M

7

24

When using implicit waits, as advised here, I still sometimes want to assert the immediate invisibility or non-existence of elements.

In other words, I know some elements should be hidden, and want my tests make that assertion fast, without spending several seconds because of the (otherwise useful) implicit wait.

One thing I tried was a helper method like this:

// NB: doesn't seem to do what I want
private boolean isElementHiddenNow(String id) {
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<Boolean> c = invisibilityOfElementLocated(By.id(id));
    try {
        zeroWait.until(c);
        return true;
    } catch (TimeoutException e) {
        return false;
    }
}

But in the above code, the call to until() only returns after the implicit wait time has passed, i.e., it doesn't do what I wanted.

This is the only way I've found so far that works:

@Test
public void checkThatSomethingIsNotVisible()  {
    turnOffImplicitWaits();
    // ... the actual test
    turnOnImplicitWaits();
}

... where e.g. turnOffImplicitWaits() is a helper in common Selenium superclass:

protected void turnOffImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}

But that is not very elegant, I think. Is there any cleaner way to bypass the implicit wait occasionally?

Merrilee answered 14/6, 2012 at 13:57 Comment(3)
I don't believe there is anything defined by the interface that does what you want. The only thing I can think of is to call findElements instead of findElement. But I'm not sure that bypasses the implicit wait either.Leatherwood
@MikeKwan No, findElements() also tries to wait and return after at least one element has been found.Carpogonium
Would be a good case for lambdas public void bypassImplicitWaits(Bypass bypass) { turnOffImplicitWaits(); bypass.do(); turnOnImplicitWaits(); }Nesmith
M
23

Given that Selenium doesn't seem to offer what I want directly (based on what Mike Kwan and Slanec said), this simple helper method is what I went with for now:

protected boolean isElementHiddenNow(String id) {
    turnOffImplicitWaits();
    boolean result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
    turnOnImplicitWaits();
    return result;
}

private void turnOffImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}

private void turnOnImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}

If the element is hidden or not present at all, the method returns true; if it is visible, returns false. Either way, the check is done instantly.

Using the above is at least much cleaner than littering the test cases themselves with calls to turnOffImplicitWaits() and turnOnImplicitWaits().

See also these answers for fined-tuned versions of the same approach:

Merrilee answered 15/6, 2012 at 9:0 Comment(5)
How do you turn on implicit waits?Mirthamirthful
@JeffMay: something like driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);. See e.g. this answer.Merrilee
Use By as an parameter in example so it would be easier and can be used for all :)Renatarenate
Anybody know how to replicate this line: driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS) in Python? I can't find it in the documentationIsometropia
Never mind, you can just set the implicit wait time the same way you initially set it.Isometropia
S
7

I would also suggest changing the parameter to a "By" locator for more flexibility when looking for the element.

protected boolean isElementHiddenNow(By locator) {
    turnOffImplicitWaits();
    boolean result = false;
    try {
       result = ExpectedConditions.invisibilityOfElementLocated(locator).apply(driver);
    }
    finally {
       turnOnImplicitWaits();
    }
    return result;
}

That way, you could search by css if needed rather than just id:

By PartLinkLocator = By.cssSelector("div.search-result div.row a");

'Course, your locator should probably be designed to return only one element (unlike the "By" example I quickly grabbed, which returns all part links in a css table of rows...) So, an "id" example would look like

By usernameLocator = By.id("inputEmail");
myResult = isElementHiddenNow(usernameLocator);
Sensible answered 28/7, 2014 at 18:32 Comment(1)
Definitely the try/finally is the way to go.Atonal
C
6

My implementation:

using (driver.NoImplicitWait())
{
    ....
}

With extension method:

public static NoImplicitWait NoImplicitWait(this IWebDriver driver)
{
    return new NoImplicitWait(driver);
}

And class:

public sealed class NoImplicitWait : IDisposable
{
    private readonly IWebDriver _driver;

    public NoImplicitWait(IWebDriver driver)
    {
        _driver = driver;
        _driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
    }

    public void Dispose()
    {
        _driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
    }
}
Crosscrosslet answered 10/3, 2016 at 11:3 Comment(0)
Z
3

@Jonic's answer helped me, however I would add a try { } finally { } and call turnOnImplicitWaits() in the finally block to make sure it always turns back on.

protected boolean isElementHiddenNow(String id) {
    turnOffImplicitWaits();
    boolean result = false;
    try {
       result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
    }
    finally {
       turnOnImplicitWaits();
    }
    return result;
}
Zugzwang answered 29/4, 2014 at 8:17 Comment(0)
I
1

My approach was to bypass Implicit wait entirely and reimplement it (with an addition of a visibility check etc.) in my own findElement() and findElements() methods which I now use by default. This way, when I want to check something instantly, I can call the original WebDriver method which does, of course, not wait.

Immobile answered 14/6, 2012 at 15:24 Comment(2)
How do you go about waiting without using the implicitWait option? Did you just implement a try/catch in some kind of loop and poll the element every few second until reaching some threshold?Geode
@Geode Yes, the usual (try-catch, try again or timeout) approach with some basic additional feats: visibility, disabled elements, highlighting found elements, workarounds for page not really loaded (starts again on StaleElementReference), temporarily also for this and this bug.Carpogonium
M
0

In an existing code relying a lot on implicit wait way of thinking, and without CSS to the rescue, I found a way out nfor that kind of things, complementing it with Jsoup, and going on with Jsoup:

# this is straightforward Scala... put the types and it is Java.
val innerHtml = seleniumWebElementFatherInstance.getAttribute("innerHTML")
val jsoupElements = Jsoup.parse(innerHtml).select("div.your.css.selector")
Microminiaturization answered 1/10, 2017 at 12:59 Comment(0)
E
0

To override or temporarily skip the implicit wait. Selenium doesn't provide any direct solution since these are static values.

To achieve that we need a workaround as mentioned in this article. How to skip the implicit wait for some element in Selenium in JAVA

Ergonomics answered 28/7, 2023 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.