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

时间:2014-08-11 14:22:13

标签: javascript ajax selenium

我要测试何时调用Ajax会返回Not Found,会显示一条警告。

警报的可见性由“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;
        }
    }

仍然无法使其发挥作用。

2 个答案:

答案 0 :(得分:0)

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

一种方法是使用FlenWait和Selenium2提供的Predicate。这种方法的优点是元素轮询机制是可配置的。下面的代码示例等待1秒,并且每100毫秒轮询一次textarea。

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

另一种方法是使用ExpectedCondition和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")));
        ..        
      }
我在我使用的方式中对fluentWa的特殊调整是在代码中:

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

对于hanling警报并了解它们是否被显示,我建议使用smth:

 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;

    }

希望这会对你有所帮助。

答案 1 :(得分:0)

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

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

取自official selenium documentation

另一组操作 - 在Windows和框架之间移动 - 可以通过

执行
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
    }
}