2010-05-14 244 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"); 
     } 
    }); 
}