Selenium Webdriver等待元素点击?

时间:2012-03-08 14:07:01

标签: c# selenium timeout 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()方法仅用于等待加载元素,但这会在Click()上超时,因此它甚至无法查找元素。

SetScriptTimeout()方法只适用于执行javascript,我没有这样做。

有谁知道这样做的方法?

6 个答案:

答案 0 :(得分:11)

试试这个:

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

元素可以是您重定向到的下一页上的任何元素的ID。 一旦页面完全加载,它将开始执行您的代码。

答案 1 :(得分: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;
});

作为旁注,我非常确定UntilIWebBrowser作为输入,而非元素,这就是您无法点击elem的原因。< / p>

答案 2 :(得分:5)

除了prestomanifesto的解决方案,我可以提供一个不太理想的解决方案来解决这个问题。事实证明它抛出一个异常 - 没有响应等...... - 所以我只是在try catch中包围它然后等待弹出窗口关闭,这似乎工作正常。

你可以在你的循环中替换你想要的任何东西,只要确保放入一个计数器,这样它就不会永远循环。

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);
}

答案 3 :(得分: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);
    }
  }

答案 4 :(得分:0)

使用LINQ Lambda表达式的RepeatUntil扩展方法

将此代码复制到您的项目中:

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;
        }
    }

使用以下语法调用它:

 // 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);

注意:在上面的示例中,我们传入一个PageObjectType,但您可以将其更改为IWebDriver类型或事件IWebElement。所有类型参数都允许您将其用作指定类型的扩展方法。

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

答案 5 :(得分:0)

不要使用线程睡眠

public class(IWebDriver driver)
{           
this.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMinutes(1);
wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromMinutes(1));
 }

public void class1()
{  
wait.Until(ExpectedConditions.ElementToBeClickable(elem)).Click();
}