Reputation: 81802
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?
Upvotes: 24
Views: 14647
Reputation: 9
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
Upvotes: 0
Reputation: 7342
@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;
}
Upvotes: 3
Reputation: 860
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")
Upvotes: 0
Reputation: 1157
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));
}
}
Upvotes: 6
Reputation: 81802
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:
Upvotes: 23
Reputation: 71
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);
Upvotes: 7
Reputation: 38444
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.
Upvotes: 1