C# Selenium Webdriver 等待元素点击?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9618878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:11:41  来源:igfitidea点击:

Selenium Webdriver wait on element click?

c#seleniumtimeoutwebdriver

提问by hacket

I have been searching for a solution for this, but to no avail. I have a button I'm clicking, that is sometimes taking a long while to return data, and the driver is timing out and just killing the app I guess.

我一直在为此寻找解决方案,但无济于事。我有一个正在单击的按钮,有时需要很长时间才能返回数据,而且驱动程序超时,我猜只是杀死了应用程序。

I am trying to use the WebDriverWait class to accomplish this, but the Click() method is not available in the way I'm using it.

我正在尝试使用 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;
});

The ImplicitlyWait() method is only for waiting for elements to load, but this times out on Click(), so it can't even look for an element.

ImplicitlyWait() 方法仅用于等待元素加载,但这在 Click() 上超时,因此它甚至无法查找元素。

The SetScriptTimeout() method just works with executing javascript, which I'm not doing.

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

Does anyone know of a way to do this?

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

采纳答案by hacket

In addition to prestomanifesto's solution I can offer a less than ideal solution to that I implemented to solve this issue. It turns out it is throwing an exception - No Response etc... - so I just surrounded it in a try catch then waited for the popup to close, which seems to work fine.

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

You can substitute whatever you want in your loop, just make sure to put a counter in so it won't loop forever.

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

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

回答by dotoree

I use this script :

我使用这个脚本:

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

回答by prestomanifesto

Instead of Clickyou could try to use SendKeys. Unlike Click, SendKeysdoes not wait for the page to finish loading before resuming code execution. So you can do something like this:

而不是Click你可以尝试使用SendKeys. 与 不同ClickSendKeys在恢复代码执行之前不等待页面完成加载。所以你可以做这样的事情:

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

As a side note, I'm pretty sure Untiltakes in a IWebBrowseras an input, not an element, which is why you can't click on elem.

作为旁注,我很确定Until将 aIWebBrowser作为输入,而不是元素,这就是您无法单击 的原因elem

回答by Aditi

try this :

尝试这个 :

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

Element can be ID of any element present on the next page you are redirected to . Once Page loads fully then it will start executing your code .

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

回答by John Peters

RepeatUntil Extension Method using LINQ Lambda expressions

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

Copy this code to your project:

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

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

Call it using this syntax:

使用以下语法调用它:

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

Note: In the example above we are passing in a PageObjectType but you could change this to be of type IWebDriver or event IWebElement. All the type parameter does it allow you to use this as an extension method for the type you specify.

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

Note the flexibility of the extension method in that the caller can determine the collection as well as the comparator.

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

回答by Thilanka89

don't use thread sleep

不要使用线程睡眠

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