Selenium:等待元素消失

6
我面临着一个复杂的任务。我对selenium仍然很陌生,并正在学习等待元素等功能。
我需要在一个网站上操作一些数据,然后再进入另一个网站。问题是:这个操作会调用一个脚本,在后台处理被操作的数据时会出现一个小的“保存...”标签。我必须等到它消失才能进入下一个网站。
所以问题来了: 如何等待某个元素消失?事实上:它始终存在于DOM中,但只有在某个脚本(我想是这样,请参见下面的图片)的控制下才会变得可见。 The palish code contains the said element 以下是我尝试过的方法,但它根本没有起到等待的作用。selenium只是继续执行下一步(并因为“保存...”而卡在弹出框上,询问我是否要离开或留在该页面)。
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;
}

更新/解决方案:

我想出了以下解决方案: 我建立了自己的方法。基本上,它在循环中检查CssValue是否发生变化。

循环检查特定时间段内CSSVALUE "display"是否从"block"状态变为其他状态。

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

        }
    }

1
可能是重复的问题:Selenium - 等待元素不可见 - SiKing
谷歌会提供许多其他可用的解决方案。 - SiKing
谢谢您的回复,但是提供的解决方案并没有起作用。我自己想出了一种“等待方法”。 - Christoph Zabinski
9个回答

3
您可以像这样等待WebElement抛出StaleElementReferenceException异常:
public void waitForInvisibility(WebElement webElement, int maxSeconds) {
    Long startTime = System.currentTimeMillis();
    try {
        while (System.currentTimeMillis() - startTime < maxSeconds * 1000 && webElement.isDisplayed()) {}
    } catch (StaleElementReferenceException e) {
        return;
    }
}

所以你需要传入你想要等待的WebElement和你想要等待的最大秒数。


2

Webdriver内置等待功能,您只需要构建等待条件即可。

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);
 }
});

1
集成开发环境(Eclipse)要求我将Webelement foo的返回类型更改为布尔型 - 为什么?它告诉我将“public WebElement apply(WebDriver driver){...”更改为“public boolean apply(WebDriver driver){...” IDE的提示:“无法从布尔型转换为WebElement”。 - Christoph Zabinski
如果您更改建议(第二个语句 WebElement...),@nguyen-vu-hoang稍微修改一下,它就会起作用:WebElement foo = wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("lblOrderHeaderSaving"))); - daniel.kahlenberg

1

我不确定,但您可以尝试类似这样的方法 :)

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

最终,这就是我为了得出解决方案所做的事情。关键在于使用CssValue并在循环中检查其状态,然后继续进行。 - Christoph Zabinski

0

这适用于selenium 2.4.0。你必须使用不可见性方法来查找它。

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);
    }
}

0
你可以使用XPath和WebDriverWait来检查一个元素的style属性中是否存在"display: none"。以下是一个示例:
// 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')]")));

0

在此输入图像描述我创建了自己的元素从DOM中消失的方法....

在Conditions类中(位于.m2\repository\org\seleniumhq\selenium\selenium-support\3.141.59\selenium-support-3.141.59.jar!\org\openqa\selenium\support\ui\ExpectedConditions.class中)

我们可以看到带有'isDisplayed'方法的'isInvisible'方法,我用'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;
    }
}

0

0

0
我使用了以下的C#代码来处理这个问题,你可以将它转换成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;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接