I want to make sure that an element is present before the webdriver starts doing stuff.
I\'m trying to get something like this to work:
WebDriverWait w
WebDriverWait
won't take effect.
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
This would immediately throw an exception once the page is "interactive". I don't know why but the timeout acts as if not exist.
Perhaps SeleniumExtras.WaitHelpers
works but I didn't try. It's official but was split out into another nuget package. You can refer to C# Selenium 'ExpectedConditions is obsolete'.
Myself is using FindElements
and check whether Count == 0
, if true, use await Task.Delay
. It's really not quite efficient.
Alternatively you can use implicit wait:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
We can achieve that like this:
public static IWebElement WaitForObject(IWebDriver DriverObj, By by, int TimeOut = 30)
{
try
{
WebDriverWait Wait1 = new WebDriverWait(DriverObj, TimeSpan.FromSeconds(TimeOut));
var WaitS = Wait1.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.PresenceOfAllElementsLocatedBy(by));
return WaitS[0];
}
catch (NoSuchElementException)
{
Reports.TestStep("Wait for Element(s) with xPath was failed in current context page.");
throw;
}
}
You can also use
ExpectedConditions.ElementExists
So you will search for an element availability like that
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));
Source
public bool doesWebElementExist(string linkexist)
{
try
{
driver.FindElement(By.XPath(linkexist));
return true;
}
catch (NoSuchElementException e)
{
return false;
}
}
Since I'm separating page elements definitions and page test scenarios using already found IWebElement for visibility could be done like this:
public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, IWebElement element, int timeout)
{
new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}
private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
return driver => {
try
{
return element.Displayed;
}
catch(Exception)
{
// If element is null, stale or if it cannot be located
return false;
}
};
}