Reputation: 20595
I am testing a UI in which the user clicks a delete button and a table entry disappears. As such, I want to be able to check that the table entry no longer exists.
I have tried using ExpectedConditions.not()
to invert ExpectedConditions.presenceOfElementLocated()
, hoping that it would mean "expect that there is not a presence of the specified element". My code is like so:
browser.navigate().to("http://stackoverflow.com");
new WebDriverWait(browser, 1).until(
ExpectedConditions.not(
ExpectedConditions.presenceOfElementLocated(By.id("foo"))));
However, I found that even doing this, I get a TimeoutExpcetion
caused by a NoSuchElementException
saying that the element "foo" does not exist. Of course, having no such element is what I want, but I don't want an exception to be thrown.
So how can I wait until an element no longer exists? I would prefer an example that does not rely on catching an exception if at all possible (as I understand it, exceptions should be thrown for exceptional behavior).
Upvotes: 57
Views: 113750
Reputation: 29
You can use the following logic:
C# code sinppet:
//wait is the instance of WebDriverWait
wait.Until(driver => driver.FindElements(By.Xpath("your element expath")).Count == 0);
Notice how I use FindElements
that does NOT throw NoSuchElementException
which is swallowed by Until()
function. So when element is gone collection size is zero.
Upvotes: 0
Reputation: 4116
It looks like elementIsNotVisible
has been added to until
after the previous answers were given. I'm using selenium webdriver 4.0.0-beta.3
Check it out:
const timeout = 60 * 1000; // 60 seconds
const element = await driver.findElement(By.id(elementId));
// this is the important line
await driver.wait(until.elementIsNotVisible(element), timeout);
Upvotes: 1
Reputation: 3649
You can also use -
new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(locator));
If you go through the source of it you can see that both NoSuchElementException
and staleElementReferenceException
are handled.
/**
* An expectation for checking that an element is either invisible or not
* present on the DOM.
*
* @param locator used to find the element
*/
public static ExpectedCondition<Boolean> invisibilityOfElementLocated(
final By locator) {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
try {
return !(findElement(locator, driver).isDisplayed());
} catch (NoSuchElementException e) {
// Returns true because the element is not present in DOM. The
// try block checks if the element is present but is invisible.
return true;
} catch (StaleElementReferenceException e) {
// Returns true because stale element reference implies that element
// is no longer visible.
return true;
}
}
Upvotes: 77
Reputation: 617
I don't know why but ExpectedConditions.invisibilityOf(element)
is the only work for me while ExpectedConditions.invisibilityOfElementLocated(By)
, !ExpectedConditions.presenceOfElementLocated(By)
... not. Try it!
Hope this help!
Upvotes: 2
Reputation: 3924
I found a workaround to fix this for me in efficient way, used following C# code to handle this, you may convert it to Java
public bool WaitForElementDisapper(By element)
{
try
{
while (true)
{
try
{
if (driver.FindElement(element).Displayed)
Thread.Sleep(2000);
}
catch (NoSuchElementException)
{
break;
}
}
return true;
}
catch (Exception e)
{
logger.Error(e.Message);
return false;
}
}
Upvotes: 0
Reputation: 21
// pseudo code
public Fun<driver,webelement> ElemtDisappear(locator)
{
webelement element=null;
iList<webelement> elemt =null;
return driver=>
{
try
{
elemt = driver.findelements(By.locator);
if(elemt.count!=0)
{
element=driver.findelement(By.locator);
}
}
catch(Exception e)
{
}
return(elemnt==0)?element:null;
};
// call function
public void waitforelemDiappear(driver,locator)
{
webdriverwaiter wait = new webdriverwaiter(driver,time);
try
{
wait.until(ElemtDisappear(locator));
}
catch(Exception e)
{
}
}
As findelement throws exception on element unaviability.so i implemented using findelements. please feel free to correct and use it as per your need.
Upvotes: 0
Reputation: 474161
The solution would still rely on exception-handling. And this is pretty much ok, even standard Expected Conditions rely on exceptions being thrown by findElement()
.
The idea is to create a custom Expected Condition:
public static ExpectedCondition<Boolean> absenceOfElementLocated(
final By locator) {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
try {
driver.findElement(locator);
return false;
} catch (NoSuchElementException e) {
return true;
} catch (StaleElementReferenceException e) {
return true;
}
}
@Override
public String toString() {
return "element to not being present: " + locator;
}
};
}
Upvotes: 5
Reputation: 16201
Why don't you simply find the size of elements
. We know the the collection of elements' size would be 0 if element does not exist.
if(driver.findElements(By.id("foo").size() > 0 ){
//It should fail
}else{
//pass
}
Upvotes: 3