为什么 Ajax 调用在 WebDriverWait (Selenium) 期间被冻结

Why Ajax call is frozen during WebDriverWait (Selenium)

本文关键字:冻结 Selenium Ajax 调用 WebDriverWait 为什么      更新时间:2023-09-26

我要测试何时调用 Ajax 会返回未找到,将显示警报。

警报的可见性由"ng-show"属性控制。所以FindElement(By.Id())应该已经找到了那个元素。我想等待警报可见。

    protected IWebElement WaitForElement(string elementId)
    {
        var wait = new WebDriverWait(Host.TestWebDriver, TimeSpan.FromMinutes(2));
        return wait.Until(driver =>
        {
            var el = driver.FindElement(By.Id(elementId));
            if (el==null || !el.Displayed)
            {
                return null; // continue to wait if the element is not visible.
            }
            return el;
        });
    }

我预计WebDriverWait将等待 2 分钟,直到显示警报消息。但似乎我的 Ajax 调用从未返回错误,因此显示警报消息的 JavaScript 代码从未到达。

我应该怎么做才能让我的 Ajax 在等待时完成?


更新:

稍微修改了上面的WaitForElement

    protected IWebElement WaitForElement(string elementId)
    {
        var wait = new WebDriverWait(Host.TestWebDriver, TimeSpan.FromMinutes(2));
        try
        {
            var el = wait.Until(ExpectedConditions.ElementIsVisible(By.Id(elementId)));
            return el;
        }
        catch (WebDriverTimeoutException ex)
        {
            // no element
            return null;
        }
    }

仍然无法使其工作。

Selenium 2 中的隐式等待可能不适用于 Ajax 元素。我们建议您使用以下任一解决方法来处理 Ajax 元素。

一种方法是使用FluentWait和Selenium2可用的谓词。这种方法的优点是元素轮询机制是可配置的。下面的代码示例等待 1 秒,每 100 毫秒轮询一次文本区域。

 FluentWait<By> fluentWait = new FluentWait<By>(By.tagName("TEXTAREA"));
        fluentWait.pollingEvery(100, TimeUnit.MILLISECONDS);
        fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS);
        fluentWait.until(new Predicate<By>() {
            public boolean apply(By by) {
                try {
                    return browser.findElement(by).isDisplayed();
                } catch (NoSuchElementException ex) {
                    return false;
                }
            }
        });
        browser.findElement(By.tagName("TEXTAREA")).sendKeys("text to enter");

另一种方法是使用 ExpectCondition 和 WebDriverWait 策略。下面的代码等待 20 秒或直到元素可用,以最早者为准。

 public ExpectedCondition<WebElement> visibilityOfElementLocated(final By by) {
        return new ExpectedCondition<WebElement>() {
          public WebElement apply(WebDriver driver) {
            WebElement element = driver.findElement(by);
            return element.isDisplayed() ? element : null;
          }
        };
      }
      public void performSomeAction() {
        ..
        ..
        Wait<WebDriver> wait = new WebDriverWait(driver, 20);
        WebElement element = wait.until(visibilityOfElementLocated(By.tagName("a")));
        ..        
      }

以我使用的方式对 fluentWait 进行的特殊调整是在代码中:

public WebElement fluentWait(final By locator, WebDriver driver) {
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
//                .pollingEvery(5, TimeUnit.SECONDS)
                .pollingEvery(1, TimeUnit.SECONDS)
//                .ignoring(NoSuchElementException.class);
                .ignoring(org.openqa.selenium.NoSuchElementException.class);
        WebElement foo = wait.until(
                new Function<WebDriver, WebElement>() {
                    public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                    }
                }
        );
        return foo;
    }

调用将如下所示:

WebElement abracadabra = fluentWait(By.cssSelector('.elemSelector'));

对于汉岭警报并了解它们是否显示,我建议像这样:

 public boolean isAlertPresent(WebDriver driver) {
        boolean presentFlag;
        try {
            // Check the presence of alert
            Alert alert = driver.switchTo().alert();
            // Alert present; set the flag
            presentFlag = true;
            // if present consume the alert
//            alert.accept();
        } catch (NoAlertPresentException ex) {
            // Alert not present
//            ex.printStackTrace();
            presentFlag = false;
        }
        return presentFlag;
    }

希望这对你有帮助。

Alert alert = driver.switchTo().alert();

从Selenium 2.0 beta 1开始,内置了对处理弹出对话框的支持。触发打开弹出窗口的操作后,可以使用上面的字符串代码访问警报。

摘自官方硒文献

另一组操作 - 在窗口和框架之间移动 - 可以通过以下方式执行

switchTo()

方法。

顺便说一句,这里有一点修改等待警报:

public void checkForAlert() {
    try {
        WebDriverWait wait = new WebDriverWait(driver, 2);
        wait.until(ExpectedConditions.alertIsPresent());
        Alert alert = driver.switchTo().alert();
        alert.accept();
    } catch (Exception e) {
        //exception handling
    }
}