Mostly I use the following approach, which I also implemented in my latest project SeleniumSharper, which aims to simplify and enhance the Selenium experience.
What's cool about the approach is, that it will work with any instance of ISearchContext
, which means you can either call the Wait()
method with an IWebDriver
or IWebElement
.
First, you need to implement this extension method.
public static class SearchContextExtensions
{
public static Waiter<ISearchContext> Wait(this ISearchContext searchContext, int timeoutInSeconds = 0)
{
var wait = new DefaultWait<ISearchContext>(searchContext)
{
Timeout = TimeSpan.FromSeconds(timeoutInSeconds)
};
return new Waiter<ISearchContext>(wait);
}
}
where Waiter.cs
looks like this
public sealed class Waiter<T>
{
private readonly DefaultWait<T> _wait;
public Waiter(DefaultWait<T> wait)
{
_wait = wait;
}
public TResult Until<TResult>(Func<T, TResult> condition)
{
return _wait.Until(condition);
}
}
After that you need to create a specific condition to satisfy, for example:
public static class WaitConditions
{
public static Func<ISearchContext, IWebElement> ElementExists(By by)
{
return (searchContext) => searchContext.FindElement(by);
}
}
You can then wait for the condition by chaining up all the methods:
var webdriver = new ChromeDriver();
var locator = By.CssSelector(".myCssClass");
webdriver.Wait(30).Until(WaitConditions.ElementExists(locator));