2012-03-08 239 views
9

我一直在尋找解決方案,但無濟於事。我點擊了一個按鈕,有時需要很長時間才能返回數據,並且驅動程序正在超時,我只是想殺死應用程序。Selenium Webdriver等待元素點擊?

我想使用WebDriverWait類來完成此操作,但Click()方法在我使用它的方式中不可用。

WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(0, 5, 0)); 

bool clicked = wait.Until<bool>((elem) => 
{ 
    elem.Click(); //Doesn't Work 
    return true; 
}); 

的ImplicitlyWait()方法僅適用於等待元素加載,但出這個時間上點擊(),所以它甚至不能找一個元素。

SetScriptTimeout()方法只適用於執行JavaScript,我不這樣做。

有誰知道一種方法來做到這一點?

回答

5

除了prestomanifesto的解決方案,我可以提供一個不太理想的解決方案來解決這個問題。事實證明,它正在拋出一個異常 - 沒有響應等等 - - 所以我只是在try catch中包圍它,然後等待popup關閉,這似乎工作正常。

你可以在你的循環中替換你想要的任何東西,只要確保把一個計數器放入它就不會永久循環。

try 
{ 
    element.Click(); 
} 
catch 
{ 
    cnt++; 
    do 
    { 
     //wait for whatever 
     cnt++; 
     Thread.Sleep(1000); 
     // Wait for 30 seconds for popup to close 
    } while (!string.IsNullOrEmpty(browser.CurrentWindowHandle) && cnt < 30); 
} 
+0

我正在努力尋找更好的解決方案,我已經發布在這裏,如果你可以看看它http://stackoverflow.com/questions/12967008/webdriverwait-or-implicitlywait-or-explictlywait-nothing-works – 2012-10-19 22:09:07

0

我使用這個腳本:

private static void waitUntilScriptFoundAndExecute(String script) { 
    int tries = 0; 
    boolean found = false; 
    do { 
     tries++; 
     try { 
     driver.executeScript(script); 
     found = true; 
     } catch (NoSuchElementException nse) { 
     System.out.println("Wait for script NSE (" + tries + ")"); 
     } catch (WebDriverException wde) { 
     System.out.println("Wait for script WDE (" + tries + ")"); 
     } catch (Exception e) { 
     System.out.println("Wait for script E (" + tries + ")"); 
     } 

     // Waiting 
     if (!found) { 
     System.out.println("Wait for script Not found (" + tries + ")"); 
     waiting(SCRIPT_WAITING_INTERVAL); 
     } 
    } while (!found && tries < MAX_SCRIPT_WAIT_TRIES); 

    if (!found) { 
     System.out.println("Script aborted: " + script); 
    } 
    } 
+0

這對我正在做的事不起作用,而對於查找腳本非常有用。謝謝。我最終找到了一個解決方案,並會在發佈後發佈。新用戶無法立即回答自己的解決方案。 – hacket 2012-03-08 14:31:10

+0

我在同一塊板上,你是如何修復的?你能分享嗎?編輯你的問題和貼上你的解決方案。 – 2012-10-19 20:16:21

5

而不是Click你可以嘗試使用SendKeys。與Click不同,SendKeys在恢復代碼執行之前不會等待頁面完成加載。所以,你可以做這樣的事情:

WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(0, 5, 0)); 

elem.SendKeys(Keys.Enter);  
wait.Until<bool>((_driver) => 
{   
    //Check here if results have loaded yet 
    return true; 
}); 

作爲一個方面說明,我敢肯定Until發生在一個IWebBrowser作爲輸入,而不是元素,這就是爲什麼你不能在elem點擊。

+0

這是一個很好的解決方案,不幸的是,發送輸入到這個按鈕不起作用。不知道爲什麼... – hacket 2012-03-09 13:36:21

+0

我有時也會發生這種情況,特別是當點擊觸發jQuery事件時。在這種情況下,我使用'ExecuteScript'來執行點擊,類似於:'driver.ExecuteScript(「$(arguments [0])。click()」,elem);'很高興您現在找到了解決方法。 – prestomanifesto 2012-03-09 17:21:32

10

試試這個:

WebDriverWait wait = new WebDriverWait(driver , 1000) ; 
wait.until(ExcepctedConditions.elementToBeClickable(ById("element")); 

元素可以存在,你將被重定向到下一個頁面上的任何元素的ID。 一旦頁面加載完成,它就會開始執行你的代碼。

+0

該問題當處理element.click()時,它會暫停並等待大約30秒,以使.click()方法返回。如果沒有,則拋出異常。 – hacket 2012-08-30 15:12:50

0

RepeatUntil推廣使用LINQ LAMBDA方法表達式

拷貝代碼到你的項目:

// You can change PageObjectType to IWebDriver or IWebElement so that 
// cb is of any type. 
var element = cb.RepeatUntil<MyPageObjectType>(
    //This is the first function to provide the elements 
    p => p.FindElements(By.ClassName("TreeNode")), 
    //This is the comparator 
    ele => ele.Text == nodeText && ele.Location.Y>YLocation); 

注:

public static class SeleniumExtensionMethods 
    { 
     public static IWebElement RepeatUntil<T>(this T obj, 
      Func<T, IEnumerable<IWebElement>> func, 
       Func<IWebElement, bool> compare, 
        int MaxRetry = 20) 
     { 
      //call function to get elements 
      var eles = func(obj); 
      IWebElement element = null; 
      while (element == null && MaxRetry > 0) 
      { 
       MaxRetry-=1; 
       //call the iterator 
       element = IterateCollection(compare, eles); 
       if (element == null) 
       { 
        Thread.Sleep(500); 
        //get new collection of elements 
        eles = func(obj); 
       } 
      }; 

      return element; 
     } 

     private static IWebElement IterateCollection(
      Func<IWebElement, bool> compare, 
      IEnumerable<IWebElement> eles){ 
      IWebElement element = null; 
      eles.ToList().ForEach(
       ele => 
       { 
        //call the comparator 
        var found = compare(ele); 
        if (found) element = ele; 
       }); 
      return element; 
     } 
    } 

使用此語法調用它的上面的例子中,我們傳入一個PageObjectType,但可以將其更改爲b類型IWebDriver或事件IWebElement。所有的類型參數都允許你使用它作爲你指定類型的擴展方法。

請注意擴展方法的靈活性,因爲調用者可以確定集合以及比較器。

相關問題