Selenium Web驱动程序等待元素单击

本文关键字:元素 单击 等待 驱动程序 Web Selenium | 更新日期: 2023-09-27 18:27:05

我一直在为此寻找解决方案,但没有成功。我有一个按钮正在点击,有时需要很长时间才能返回数据,而驱动程序正在超时,我想这只是扼杀了应用程序。

我正试图使用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,我不这么做。

有人知道这样做的方法吗?

Selenium Web驱动程序等待元素单击

试试这个:

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

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

您可以尝试使用SendKeys而不是Click。与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的原因。

除了prestomanifesto的解决方案之外,我还可以提供一个不太理想的解决方案来解决这个问题。事实证明,它正在抛出一个异常-没有响应等…-所以我只是在一次尝试捕获中包围了它,然后等待弹出窗口关闭,这似乎很好。

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

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

我使用这个脚本:

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

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

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

不要使用线程睡眠

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