我想确保在webdriver开始做事情之前,一个元素是存在的。

我正在尝试这样做:

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
wait.Until(By.Id("login"));

我主要是挣扎如何设置匿名功能…


当前回答

WebDriverWait将不生效。

var driver = new FirefoxDriver(
    new FirefoxOptions().PageLoadStrategy = PageLoadStrategy.Eager
);
driver.Navigate().GoToUrl("xxx");
new WebDriverWait(driver, TimeSpan.FromSeconds(60))
    .Until(d => d.FindElement(By.Id("xxx"))); // A tag that close to the end

一旦页面是“交互式的”,这将立即抛出异常。我不知道为什么,但是超时就好像它不存在一样。

也许SeleniumExtras。WaitHelpers很管用,但我没试过。这是官方的,但它被拆分为另一个NuGet包。你可以参考c# Selenium 'ExpectedConditions is obsolete'。

我使用FindElements并检查Count == 0。如果为真,则使用await Task.Delay。这真的不是很有效。

其他回答

受Loudenvier的解决方案的启发,这里有一个扩展方法,它适用于所有ISearchContext对象,而不仅仅是IWebDriver,后者是前者的专门化。此方法还支持等待,直到元素显示出来。

static class WebDriverExtensions
{
    /// <summary>
    /// Find an element, waiting until a timeout is reached if necessary.
    /// </summary>
    /// <param name="context">The search context.</param>
    /// <param name="by">Method to find elements.</param>
    /// <param name="timeout">How many seconds to wait.</param>
    /// <param name="displayed">Require the element to be displayed?</param>
    /// <returns>The found element.</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        wait.Timeout = TimeSpan.FromSeconds(timeout);
        wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
        return wait.Until(ctx => {
            var elem = ctx.FindElement(by);
            if (displayed && !elem.Displayed)
                return null;

            return elem;
        });
    }
}

使用示例:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
var btn = main.FindElement(By.Id("button"));
btn.Click();
var dialog = main.FindElement(By.Id("dialog"), 5, displayed: true);
Assert.AreEqual("My Dialog", dialog.Text);
driver.Close();

第一个答案是好的,但我的问题是,未处理的异常没有关闭web驱动程序正确,它保持相同的第一个值,我使用的是1秒。

如果遇到同样的问题,重新启动Visual Studio并确保所有异常都得到了正确处理。

我混淆了匿名函数和谓词。这里有一个小帮手方法:

   WebDriverWait wait;
    private void waitForById(string id)
    {
        if (wait == null)
            wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));

        //wait.Until(driver);
        wait.Until(d => d.FindElement(By.Id(id)));
    }

您不希望在元素更改之前等待太长时间。在这段代码中,webdriver在继续之前最多等待2秒。


WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));

显式等

public static  WebDriverWait wait = new WebDriverWait(driver, 60);

例子:

wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));