【问题标题】:Why Ajax call is frozen during WebDriverWait (Selenium)为什么 Ajax 调用在 WebDriverWait (Selenium) 期间被冻结
【发布时间】:2014-08-11 14:22:12
【问题描述】:

我要测试当调用 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;
        }
    }

仍然无法让它工作。

【问题讨论】:

    标签: javascript ajax selenium


    【解决方案1】:

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

    一种方法是使用 FluentWait 和 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")));
            ..        
          }
    

    我在使用方式上对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;
    
        }
    

    希望对你有所帮助。

    【讨论】:

    • 感谢您的详细输入。但是我仍然难以理解您的行driver.switchTo().alert(); intellisense 告诉我switchTo() 指示驱动程序将未来的命令发送到不同的框架或窗口。但是我怎样才能检查那个新框架/窗口中的元素呢?你的.alert() 是怎么实现的?
    【解决方案2】:
    Alert alert = driver.switchTo().alert();
    

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

    取自official selenium documentation

    另一组动作——在窗口和框架之间移动——可以由

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 2021-07-31
      • 2021-08-26
      • 2014-03-02
      • 1970-01-01
      • 2016-01-08
      • 2018-08-02
      相关资源
      最近更新 更多