By AyKarsi


2011-08-09 07:49:06 8 Comments

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 wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(By.Id("login"));

I'm mainly struggling how to setup up the anynomous function..

20 comments

@Angel D 2018-09-14 17:07:23

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

@user3607478 2017-06-13 07:56:59

You do not want to wait too long before the element changes. In this code the webdriver waits for up to 2 seconds before it continues.

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

@havan 2018-02-26 11:03:40

Used Rn222 and Aknuds1 to use an ISearchContext that returns either a single element, or a list. And a minimum number of elements can be specified:

public static class SearchContextExtensions
{
    /// <summary>
    ///     Method that finds an element based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeOutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns> The first element found that matches the condition specified</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeOutInSeconds)
    {
        if (timeOutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeOutInSeconds);
            return wait.Until<IWebElement>(ctx => ctx.FindElement(by));
        }
        return context.FindElement(by);
    }
    /// <summary>
    ///     Method that finds a list of elements based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds)
    {

        if (timeoutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
            return wait.Until<IReadOnlyCollection<IWebElement>>(ctx => ctx.FindElements(by));
        }
        return context.FindElements(by);
    }
    /// <summary>
    ///     Method that finds a list of elements with the minimum amount specified based on the search parameters within a specified timeout.<br/>
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <param name="minNumberOfElements">
    ///     The minimum number of elements that should meet the criteria before returning the list <para/>
    ///     If this number is not met, an exception will be thrown and no elements will be returned
    ///     even if some did meet the criteria
    /// </param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds, int minNumberOfElements)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        if (timeoutInSeconds > 0)
        {
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
        }

        // Wait until the current context found the minimum number of elements. If not found after timeout, an exception is thrown
        wait.Until<bool>(ctx => ctx.FindElements(by).Count >= minNumberOfElements);

        //If the elements were successfuly found, just return the list
        return context.FindElements(by);
    }

}

Example usage:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
// It can be now used to wait when using elements to search
var btn = main.FindElement(By.Id("button"),10);
btn.Click();
//This will wait up to 10 seconds until a button is found
var button = driver.FindElement(By.TagName("button"),10)
//This will wait up to 10 seconds until a button is found, and return all the buttons found
var buttonList = driver.FindElements(By.TagName("button"),10)
//This will wait for 10 seconds until we find at least 5 buttons
var buttonsMin= driver.FindElements(By.TagName("button"), 10, 5);
driver.Close();

@Ammar Ben Hadj Amor 2017-08-17 13:13:49

Try this code:

 New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)

@hering 2017-08-17 13:34:45

You should explain what you have done and why this solves the problem. And please format your code.

@Madhu 2015-04-27 12:02:47

public bool doesWebElementExist(string linkexist)
{
     try
     {
        driver.FindElement(By.XPath(linkexist));
        return true;
     }
     catch (NoSuchElementException e)
     {
        return false;
     }
}

@Batuhan Co┼čkun 2015-04-27 12:22:05

Please add some information about your answer.

@Madhu 2015-04-28 04:39:37

The above code is to check whether the a particular element is present or not.

@Brian121212 2011-12-08 14:28:38

//wait up to 5 seconds with no minimum for a UI element to be found
WebDriverWait wait = new WebDriverWait(_pagedriver, TimeSpan.FromSeconds(5));
IWebElement title = wait.Until<IWebElement>((d) =>
{
    return d.FindElement(By.ClassName("MainContentHeader"));
});

@Mike Kwan 2011-08-09 08:51:11

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.

@Reda 2013-06-07 15:16:14

thanks, the new syntax is : driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

@Diemo 2014-04-22 09:44:42

@RedaBalkouch, the syntax Mike used in his Answer is correct. It's C#

@mrfreester 2016-12-22 19:26:00

If you choose to use implicit waits, be careful not to use explicit waits. That can cause some unpredictable behavior leading to bad test results. Generally speaking, I would recommend using explicit waits over implicit waits.

@Samuel Rondeau-Millaire 2017-03-31 15:17:13

This method is now deprecated, you should instead use the property ImplicitWait : Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

@Jim Scott 2017-06-01 00:47:30

I used the approach provided and found the method was deprecated as pointed out by Samuel. Checking for the existence of an item now waits up to the specified time.

@Pete Kozak 2016-10-08 15:16:21

First answer is good, my problem was that unhandled exceptions didn't close web driver properly and it kept the same first value I had used which was 1 second.

If you get the same problem

restart you visual studio and ensure that all the exceptions are handled properly.

@Antti Haapala 2016-10-08 16:46:27

By now you should know that there is no ordering to answers in Stack Overflow, so there is no "first answer"

@david 2016-08-18 21:26:48

 new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
   Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));

@Pavan T 2016-02-17 10:42:50

Explicit Wait

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

Example:

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

@Loudenvier 2011-09-05 21:05:50

Using the solution provided by Mike Kwan may have an impact in overall testing performance, since the implicit wait will be used in all FindElement calls. Many times you'll want the FindElement to fail right away when an element is not present (you're testing for a malformed page, missing elements, etc.). With the implicit wait these operations would wait for the whole timeout to expire before throwing the exception. The default implicit wait is set to 0 seconds.

I've written a little extension method to to IWebDriver that adds a timeout (in seconds) parameter to the FindElement() method. It's quite self-explanatory:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }
}

I didn't cache the WebDriverWait object as its creation is very cheap, this extension may be used simultaneously for different WebDriver objects, and I only do optimizations when ultimately needed.

Usage is straight-forward:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost/mypage");
var btn = driver.FindElement(By.CssSelector("#login_button"));
btn.Click();
var employeeLabel = driver.FindElement(By.CssSelector("#VCC_VSL"), 10);
Assert.AreEqual("Employee", employeeLabel.Text);
driver.Close();

@Andy 2013-09-11 01:55:59

In case someone wonder, WebDriverWait are from the OpenQA.Selenium.Support.UI namespace and comes in a separate package called Selenium WebDriver Support Classes on NuGet

@Adween 2014-09-17 14:14:32

@Ved i could kiss you <3 been looking for it in a different dll :D

@Rick 2015-07-09 07:29:44

@Loudenvier Please make the first line bold so that it is more noticeable. Especially since it is not the accepted answer, although being a better and more precise approach.

@sujith s 2016-11-04 13:53:15

@Loudenvier In a case where the html element is not rendered into DOM it will throw NoSuchElementException , appreciate if you update the code which handle those scenario's too

@Loudenvier 2016-11-04 14:03:02

@sujiths this is the expected behavior. Selenium will throw an exception if the element is not found. If you want to change this behavior simply add a try..catch for NoSuchElementException in the FindElement extension method and return null when this exception is raised. Then you'll have to check for null whenever you try to find an element with this method. Sometimes it is easier to handle exceptions than to introduce null checks everywhere... It depends on how you write your code.

@Eric F. 2017-07-14 10:49:04

Selenium WebDriver Support Classes is now appeared on NuGet as "Selenium.Support", current version is 3.4.0

@prospector 2017-10-19 05:05:51

I still had a lot of errors until I used this line return wait.Until(ExpectedConditions.ElementToBeClickable(by)); and it works great now. Heads up in case anyone else gets random elements not found still.

@Aditi 2012-08-08 06:11:48

You can find out something like this in C# .

This is what i used in JUnit - Selenium

WebDriverWait wait = new WebDriverWait(driver, 100);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));

Do import related packages

@Jeff Mergler 2018-04-19 22:02:36

I attempted to use this today and VS.net is giving me warnings: the OpenQA.Selenium.Support.UI.ExpectedConditions class has been marked "deprecated" and was "migrated to DotNetSeleniumExtras" repo on github.com/DotNetSeleniumTools

@Md. Nazmul Haque Sarker 2014-04-16 06:33:56

Python:

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By

driver.find_element_by_id('someId').click()

WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, 'someAnotherId'))

from EC you can choose other conditions as well try this: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

@User 2016-06-24 16:27:15

This question is tagged C#, not Python. This answer is irrelevant.

@Humble Coder 2013-02-28 18:12:11

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

@Keavon 2014-03-05 22:33:19

This seems to work best.

@keithl8041 2014-04-02 11:44:49

Agreed, this is far more useful than a mere timeout (in cases where you're dynamically loading an object).

@Adam Garner 2018-05-04 11:03:16

Whilst this works. It is now marked as deprecated, so should be avoided.

@Dejan 2018-07-18 15:00:19

Here's the new approach (not deprecated): stackoverflow.com/a/49867605/331281

@Michal Stefanow 2013-02-15 09:39:50

Was searching how to wait in Selenium for condition, landed in this thread and here is what I use now:

    WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10));
    wait.Until(d => ReadCell(row, col) != "");

ReadCell(row, col) != "" can be any condition. Like this way because:

  • it's mine
  • allows inlining

@aknuds1 2012-11-08 14:33:13

Inspired by Loudenvier's solution, here's an extension method that works for all ISearchContext objects, not just IWebDriver, which is a specialization of the former. This method also supports waiting until the element is displayed.

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

Example usage:

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

@howcheng 2015-03-18 00:04:53

If you've set an implicit wait such as _webDriver.Manage().Timeouts().ImplicitlyWait(Timeout); that will still trump the timeout value you set here.

@newITguy 2012-08-07 22:41:17

I see multiple solutions already posted that work great! However, just in case anyone needs something else, I thought I would post two solutions that I personally used in selenium C# to test if an element is present! Hope it helps, cheers!

public static class IsPresent
{
    public static bool isPresent(this IWebDriver driver, By bylocator)
    {

        bool variable = false;
        try
        {
            IWebElement element = driver.FindElement(bylocator);
            variable = element != null;
        }
       catch (NoSuchElementException){

       }
        return variable; 
    }

}

Here is the second

    public static class IsPresent2
{
    public static bool isPresent2(this IWebDriver driver, By bylocator)
    {
        bool variable = true; 
        try
        {
            IWebElement element = driver.FindElement(bylocator);

        }
        catch (NoSuchElementException)
        {
            variable = false; 
        }
        return variable; 
    }

}

@Rn222 2012-04-04 18:20:05

Here's a variation of @Loudenvier's solution that also works for getting multiple elements:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }

    public static ReadOnlyCollection<IWebElement> FindElements(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => (drv.FindElements(by).Count > 0) ? drv.FindElements(by) : null);
        }
        return driver.FindElements(by);
    }
}

@Loudenvier 2012-11-09 18:01:04

Nice! I've just added this to my own library! That's the beauty of sharing code!!!

@Brantley Blanchard 2013-08-02 20:23:12

I'd suggest one addition to that. You could catch the NoSuchElement solution and return null in that instance. Then you could create an extension method called .exists that returns true unless the IWebElement is null.

@MacGyver 2012-01-17 20:29:41

The clickAndWait command doesn't get converted when you choose the Webdriver format in the Selenium IDE. Here is the workaround. Add the wait line below. Realistically, the problem was the click or event that happened before this one--line 1 in my C# code. But really, just make sure you have a WaitForElement before any action where you're referencing a "By" object.

HTML code:

<a href="http://www.google.com">xxxxx</a>

C#/NUnit code:

driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();

@AyKarsi 2011-08-09 07:59:04

I Confused anyomous function with predicate. Heres a little helper method:

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

Related Questions

Sponsored Content

51 Answered Questions

[SOLVED] Take a screenshot with Selenium WebDriver

1 Answered Questions

How to make selenium 3.4.0 wait for page load?

13 Answered Questions

4 Answered Questions

[SOLVED] WebDriver - wait for element using Java

2 Answered Questions

1 Answered Questions

[SOLVED] Selenium with WebDriver - wait

1 Answered Questions

[SOLVED] Selenium Webdriver C# How to test an element is not present?

1 Answered Questions

2 Answered Questions

[SOLVED] Webdriver implicit wait for a dynamic ID

2 Answered Questions

Wait not working in Firefox browser (Webdriver selenium 2.0 +Java)

Sponsored Content