Selenium: Waiting for an element do disappear
Asked Answered
C

9

6

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) {

        }
    }
Cortisol answered 2/7, 2014 at 15:54 Comment(3)
possible duplicate of Selenium - Wait until element is NOT visibleRid
Google will turn up many other solutions available.Rid
thank you for that but the referred solutions didn't do the trick. came up with my own "waiting method".Cortisol
B
3

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.

Bombycid answered 25/4, 2016 at 17:52 Comment(0)
A
2

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);
 }
});
Antipodal answered 8/7, 2014 at 9:54 Comment(2)
The IDE (Eclipse) wants me to change the return type of the Webelement foo to boolean - Why ? It tell me to change "public WebElement apply(WebDriver driver) {..." to "public boolean apply(WebDriver driver) {..." Hint from the IDE: "cannot convert from boolean to WebElement"Cortisol
@christoph-zabinski If you change the suggestion (the second statement WebElement...) @nguyen-vu-hoang makes slightly it will work: WebElement foo = wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("lblOrderHeaderSaving")));Caloyer
C
1

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"));
Connieconniption answered 3/7, 2014 at 12:29 Comment(1)
Eventually this is KIND of what I did to come up with a solution. The key was using the CssValue and checking it's state in a loop. then proceed.Cortisol
S
0

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);
    }
}
Seafarer answered 2/6, 2015 at 21:48 Comment(0)
E
0

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;
        }
    }
Espresso answered 25/5, 2017 at 11:38 Comment(0)
P
0

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://mcmap.net/q/1778164/-wait-for-quot-loading-quot-icon-to-disappear-from-the-page

Phaih answered 9/10, 2017 at 8:4 Comment(0)
U
0

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')]")));
Usm answered 23/10, 2018 at 12:24 Comment(0)
D
0

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

Denby answered 27/1, 2021 at 6:54 Comment(0)
D
0

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;
    }
}
Dispend answered 20/1, 2023 at 7:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.