Christoph Zabinski
Christoph Zabinski

Reputation: 327

Selenium: Waiting for an element do disappear

I posed with a difficult task. I am fairly new to selenium and still working through the functionalities of waiting for elements and alike.

I have to manipulate some data on a website and then proceed to another. Problem: the manipulation invokes a script that makes a little "Saving..." label appear while the manipulated data is being processed in the background. I have to wait until I can proceed to the next website.

So here it is: How do i wait for and element to DISAPPEAR? Thing is: It is always present in the DOM but only made visible by some script (I suppose, see image below). The palish code contains the said element

This is what I tried but it just doesn't work - there is no waiting, selenium just proceeds to the next step (and gets stuck with an alert asking me if I want to leave or stay on the page because of the "saving...").

private By savingLableLocator = By.id("lblOrderHeaderSaving");

    public boolean waitForSavingDone(By webelementLocator, Integer seconds){
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    Boolean element = wait.until(ExpectedConditions.invisibilityOfElementLocated(webelementLocator));
    return element;
}

UPDATE / SOLUTION:

I came up ith the following solution: I built my own method. Basically it checks in a loop for the CssValue to change.

the loops checks for a certain amount of time for the CSSVALUE "display" to go from "block" to another state.

public void waitForSavingOrderHeaderDone(Integer _seconds){
    WebElement savingLbl = driver.findElement(By.id("lblOrderHeaderSaving"));   
    for (int second = 0;; second++) {
        if (second >= _seconds)
            System.out.println("Waiting for changes to be saved...");
        try {
            if (!("block".equals(savingLbl.getCssValue("display"))))
                break;
        } catch (Exception e) {

        }
    }

Upvotes: 6

Views: 35016

Answers (9)

user21048033
user21048033

Reputation: 1

enter image description hereI created my own method for element disappearing from dom....

In Conditions class (In .m2\repository\org\seleniumhq\selenium\selenium-support\3.141.59\selenium-support-3.141.59.jar!\org\openqa\selenium\support\ui\ExpectedConditions.class)

we can see that 'isInvisible' method with 'isDisplayed' method,,, i wrote the same with 'isEnabled'

public static ExpectedCondition<Boolean> invisibilityOf(final WebElement element) {
    return new ExpectedCondition<Boolean>() {

        @Override
        public Boolean apply(WebDriver webDriver) {
            return isRemovedFromDom(element);
        }

        @Override
        public String toString() {
            return "invisibility of " + element;
        }
    };
}


private static boolean isRemovedFromDom(final WebElement element) {
    try {
        return !element.isEnabled();
    } catch (StaleElementReferenceException ignored) {
        return true;
    }
}

Upvotes: 0

Anh Nguyen
Anh Nguyen

Reputation: 1

Try using invisibilityOfElementLocated method. You can reference example here How to wait until an element no longer exists in Selenium?

Upvotes: 0

Hendrik
Hendrik

Reputation: 463

You could use XPath and WebDriverWait to check whether display: none is present in the style attribute of an element. Here is an example:

// Specify the time in seconds the driver should wait while searching for an element which is not present yet.
int WAITING_TIME = 10;

// Use the driver for the browser you want to use.
ChromeDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, WAITING_TIME);

// Replace ELEMENT_ID with the ID of the element which should disappear. 
// Waits unit style="display: none;" is present in the element, which means the element is not visible anymore.
driver.wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[@id='ELEMENT_ID'][contains(@style, 'display: block')]")));

Upvotes: 0

Santosh Pillai
Santosh Pillai

Reputation: 8653

You can also try waiting for the ajax calls to complete. I've used this to check when the page load is complete and all the elements are visible.

Here's the code - https://stackoverflow.com/a/46640938/4418897

Upvotes: 0

Abhinav Saxena
Abhinav Saxena

Reputation: 3904

I 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

TheFreddyKilo
TheFreddyKilo

Reputation: 417

You can wait for a WebElement to throw a StaleElementReferenceException like this:

public void waitForInvisibility(WebElement webElement, int maxSeconds) {
    Long startTime = System.currentTimeMillis();
    try {
        while (System.currentTimeMillis() - startTime < maxSeconds * 1000 && webElement.isDisplayed()) {}
    } catch (StaleElementReferenceException e) {
        return;
    }
}

So you would pass in the WebElement you want to wait for, and the max amount of seconds you want to wait.

Upvotes: 3

p3nGu1nZz
p3nGu1nZz

Reputation: 1715

This works with selenium 2.4.0. you have to use the invisibility mehtod to find it.

final public static boolean waitForElToBeRemove(WebDriver driver, final By by) {
    try {
        driver.manage().timeouts()
                .implicitlyWait(0, TimeUnit.SECONDS);

        WebDriverWait wait = new WebDriverWait(UITestBase.driver,
                DEFAULT_TIMEOUT);

        boolean present = wait
                .ignoring(StaleElementReferenceException.class)
                .ignoring(NoSuchElementException.class)
                .until(ExpectedConditions.invisibilityOfElementLocated(by));

        return present;
    } catch (Exception e) {
        return false;
    } finally {
        driver.manage().timeouts()
                .implicitlyWait(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
    }
}

Upvotes: 0

Nguyen Vu Hoang
Nguyen Vu Hoang

Reputation: 1570

Webdriver has built in waiting functionality you just need to build in the condition to wait for.

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
   .withTimeout(30, SECONDS)
   .pollingEvery(5, SECONDS)
   .ignoring(NoSuchElementException.class);

WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
 public WebElement apply(WebDriver driver) {
   return (driver.findElements(By.id("lblOrderHeaderSaving")).size() == 0);
 }
});

Upvotes: 2

Pierre-luc S.
Pierre-luc S.

Reputation: 98

I'm not sure, but you can try something like this :)

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //time in second
WebElement we = driver.findElement(By.id("lblOrderHeaderSaving"));   
assertEquals("none", we.getCssValue("display"));

Upvotes: 1

Related Questions