Selenium Webdriver等待元素点击?

问题描述:

我一直在寻找解决方案,但无济于事。我点击了一个按钮,有时需要很长时间才能返回数据,并且驱动程序正在超时,我只是想杀死应用程序。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,我不这样做。

有谁知道一种方法来做到这一点?

除了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

我使用这个脚本:

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

而不是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

试试这个:

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

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。所有的类型参数都允许你使用它作为你指定类型的扩展方法。

请注意扩展方法的灵活性,因为调用者可以确定集合以及比较器。