2010-05-14 243 views

回答

37

我会用

waitForElementPresent(locator) 

这将等到元素存在于DOM。

如果您需要检查的元素是可见的,你可以使用

waitForElementHeight(locator) 
+15

,如果有什么不AJAX重定向和硒不知道呢?如何使用它? – Eugene 2011-05-23 13:27:29

+29

如果ajax只刷新一个已经存在的值,该怎么办? – 2014-10-10 21:58:42

23

不是等待一个元素将等待所有连接到服务器关闭一个更普遍的解决方案更好。这将允许您等待所有ajax调用完成,即使它们没有任何回调,因此也不会影响页面。更多细节请参见here

使用C#和jQuery,我已经创建了下面的方法来等待所有的Ajax调用完成(如果有人有从C#访问JS变量的更直接的方式,请评论):

internal void WaitForAjax(int timeOut = 15) 
{ 
    var value = ""; 
    RepeatUntil(
     () => value = GetJavascriptValue("jQuery.active"), 
     () => value == "0", 
     "Ajax calls did not complete before timeout" 
    ); 
} 

internal void RepeatUntil(Action repeat, Func<bool> until, string errorMessage, int timeout = 15) 
{ 
    var end = DateTime.Now + TimeSpan.FromSeconds(timeout); 
    var complete = false; 

    while (DateTime.Now < end) 
    { 
     repeat(); 
     try 
     { 
      if (until()) 
      { 
       complete = true; 
       break; 
      } 
     } 
     catch (Exception) 
     { } 
     Thread.Sleep(500); 
    } 
    if (!complete) 
     throw new TimeoutException(errorMessage); 
} 

internal string GetJavascriptValue(string variableName) 
{ 
    var id = Guid.NewGuid().ToString(); 
    _selenium.RunScript(String.Format(@"window.$('body').append(""<input type='text' value='""+{0}+""' id='{1}'/>"");", variableName, id)); 
    return _selenium.GetValue(id); 
} 
+3

this.selenium.GetEval(“(window.jQuery || {active:0})active”)比输入框更直接一点。如果jQuery不在页面上,它也不会出错。 – jons911 2012-08-16 20:59:26

+0

变量__selenium的类型是什么?我无法在对象模型 – 2014-04-11 22:36:26

+0

Mauricio中找到它,因为我与Selenium一起工作已经有一段时间了,所以我不记得细节,但我的猜测是IWebDriver实例。 – 2014-04-13 13:27:15

-1

对于那些谁在使用primefaces,只是做:

selenium.waitForCondition("selenium.browserbot.getCurrentWindow().$.active==0", defaultWaitingPeriod); 
+2

什么是browserbot? – 2013-01-24 09:47:49

+0

waitForCondition void waitForCondition(java.lang.String script, java.lang.String timeout) 重复运行指定的JavaScript代码片段,直到它的计算结果为“true”。代码片段可能有多行,但只会考虑最后一行的结果。 请注意,默认情况下,片段将在跑步者的测试窗口中运行,而不是在应用程序的窗口中运行。要获得应用程序的窗口,您可以使用JavaScript代码片段selenium.browserbot.getCurrentWindow(),然后在其中运行您的JavaScript – 2013-03-20 09:16:46

+0

它仅适用于Selenium RC。 Selenium WebDriver不支持功能 – ajahongir 2013-10-24 07:11:04

1

我也有类似的情况,我想等Ajax请求,以使搬入板会消失,我之前已经检查了HTML和请求后,发现ajax加载面板上有一个div,dix在ajax请求期间显示,并在请求结束后隐藏。我创建了一个功能等待面板来显示,然后等待它被隐藏

public void WaitForModalPanel() { string element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and not(contains(@style,'display: none'))]"; WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 2, 0)); wait.Until(ExpectedConditions.ElementIsVisible(By.XPath(element_xpath))); element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and contains(@style,'DISPLAY: none')]"; wait.Until(ExpectedConditions.ElementExists(By.XPath(element_xpath))); }

检查this更多细节

5

有了webdriver的又名selenium2你可以使用隐式等待配置上 http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits作为mentionned

使用Java:

WebDriver driver = new FirefoxDriver(); 
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 
driver.get("http://somedomain/url_that_delays_loading"); 
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement")); 

或者使用python:

from selenium import webdriver 

ff = webdriver.Firefox() 
ff.implicitly_wait(10) # seconds 
ff.get("http://somedomain/url_that_delays_loading") 
myDynamicElement = ff.find_element_by_id("myDynamicElement") 
10

如果使用Python,则可以使用该功能,点击该按钮并等待DOM变化:

def click_n_wait(driver, button, timeout=5): 
    source = driver.page_source 
    button.click() 
    def compare_source(driver): 
     try: 
      return source != driver.page_source 
     except WebDriverException: 
      pass 
    WebDriverWait(driver, timeout).until(compare_source) 

(CREDIT:基于this stack overflow answer

+1

不幸的是,一些页面已经加载动画,这破坏了这个伎俩,因为page_source被更新,但是你还没有数据。 – ubershmekel 2015-07-12 17:30:30

1

如上你提到可以等待活动连接关闭:

private static void WaitForReady() { 
    WebDriverWait wait = new WebDriverWait(webDriver, waitForElement); 
    wait.Until(driver => (bool)((IJavaScriptExecutor)driver).ExecuteScript("return jQuery.active == 0")); 
} 

我的观察结果是这不是relia因为数据传输非常迅速。数据处理和页面上的呈现需要花费更多时间,甚至可能还没有在页面上显示jQuery.active == 0数据。

更明智的是使用一个explicit wait元素在页面上显示,看到一些与此相关的答案。

最好的情况是,如果您的web应用程序有一些自定义加载程序或指示正在处理数据。在这种情况下,您可以等待此指示隐藏。

1

我写了一个方法为我的解决方案(我没有任何负载指示灯):

public static void waitForAjax(WebDriver driver, String action) { 
     driver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS); 
     ((JavascriptExecutor) driver).executeAsyncScript(
       "var callback = arguments[arguments.length - 1];" + 
         "var xhr = new XMLHttpRequest();" + 
         "xhr.open('POST', '/" + action + "', true);" + 
         "xhr.onreadystatechange = function() {" + 
         " if (xhr.readyState == 4) {" + 
         " callback(xhr.responseText);" + 
         " }" + 
         "};" + 
         "xhr.send();"); 
} 

然后,我仅仅指刚称这种方法与实际的驱动程序。 更多描述在这post

+0

downvote。答案应该包含真正的答案......他们不是为了吸引流量进入您的个人博客。 – 2016-11-27 19:07:27

+0

@CoreyGoldberg我不关心流量,但是,我会在这里插入帖子的代码。这篇文章只是另一种选择,因为其他答案不会为我工作。 – Hrabosch 2016-11-28 16:58:56

+0

@CoreyGoldberg我希望现在对你来说可以;) – Hrabosch 2016-11-28 17:04:47

1

的代码(C#)波纹管确保了目标元素被显示:

 internal static bool ElementIsDisplayed() 
     { 
      IWebDriver driver = new ChromeDriver(); 
      driver.Url = "http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp"; 
      WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); 
      By locator = By.CssSelector("input[value='csharp']:first-child"); 
      IWebElement myDynamicElement = wait.Until<IWebElement>((d) => 
      { 
      return d.FindElement(locator); 
      }); 
      return myDynamicElement.Displayed; 
     } 

如果页面支持jQuery的可以使用的jQuery.active function,以确保目标元素被检索后,所有的AJAX调用是完成:

public static bool ElementIsDisplayed() 
    { 
     IWebDriver driver = new ChromeDriver(); 
     driver.Url = "http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp"; 
     WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); 
     By locator = By.CssSelector("input[value='csharp']:first-child"); 
     return wait.Until(d => ElementIsDisplayed(d, locator)); 
    } 

    public static bool ElementIsDisplayed(IWebDriver driver, By by) 
    { 
     try 
     { 
      if (driver.FindElement(by).Displayed) 
      { 
       //jQuery is supported. 
       if ((bool)((IJavaScriptExecutor)driver).ExecuteScript("return window.$ != undefined")) 
       { 
        return (bool)((IJavaScriptExecutor)driver).ExecuteScript("return $.active == 0"); 
       } 
       else 
       { 
        return true; 
       } 
      } 
      else 
      { 
       return false; 
      } 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 
0

这是一个基于Morten Christiansen的答案的常规版本。

void waitForAjaxCallsToComplete() { 
    repeatUntil(
      { return getJavaScriptFunction(driver, "return (window.jQuery || {active : false}).active") }, 
      "Ajax calls did not complete before timeout." 
    ) 
} 

static void repeatUntil(Closure runUntilTrue, String errorMessage, int pollFrequencyMS = 250, int timeOutSeconds = 10) { 
    def today = new Date() 
    def end = today.time + timeOutSeconds 
    def complete = false; 

    while (today.time < end) { 
     if (runUntilTrue()) { 
      complete = true; 
      break; 
     } 

     sleep(pollFrequencyMS); 
    } 
    if (!complete) 
     throw new TimeoutException(errorMessage); 
} 

static String getJavaScriptFunction(WebDriver driver, String jsFunction) { 
    def jsDriver = driver as JavascriptExecutor 
    jsDriver.executeScript(jsFunction) 
} 
0

如果你正在等待控制是一种“Ajax”的网络元素,下面的代码将等待它,或任何其他Ajax网页元素加载完成或执行任何需要做这样就可以了更安全地继续你的步骤。

public static void waitForAjaxToFinish() { 

    WebDriverWait wait = new WebDriverWait(driver, 10); 

    wait.until(new ExpectedCondition<Boolean>() { 
     public Boolean apply(WebDriver wdriver) { 
      return ((JavascriptExecutor) driver).executeScript(
        "return jQuery.active == 0").equals(true); 
     } 
    }); 

} 
+0

请尝试在代码中添加一些解释,说明你如何认为这段代码解决了OP的问题。 – techspider 2016-07-12 20:11:39

0

这个工作对我来说就像魅力:

public void waitForAjax() { 

    try { 
     WebDriverWait driverWait = new WebDriverWait(driver, 10); 

     ExpectedCondition<Boolean> expectation; 
     expectation = new ExpectedCondition<Boolean>() { 

      public Boolean apply(WebDriver driverjs) { 

       JavascriptExecutor js = (JavascriptExecutor) driverjs; 
       return js.executeScript("return((window.jQuery != null) && (jQuery.active === 0))").equals("true"); 
      } 
     }; 
     driverWait.until(expectation); 
    }  
    catch (TimeoutException exTimeout) { 

     // fail code 
    } 
    catch (WebDriverException exWebDriverException) { 

     // fail code 
    } 
    return this; 
} 
0

这项工作对我来说

public void waitForAjax(WebDriver driver) { 
    new WebDriverWait(driver, 180).until(new ExpectedCondition<Boolean>(){ 
     public Boolean apply(WebDriver driver) { 
      JavascriptExecutor js = (JavascriptExecutor) driver; 
      return (Boolean) js.executeScript("return jQuery.active == 0"); 
     } 
    }); 
}