Can I reuse WebDriverWait in multiple sequential waits?

1.1k views Asked by At

Given I need wait for one textbox appears, do something, and later I will need wait another Textbox. I want to know if this code is correct:

var waitForTextBox = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
waitForTextBox.Until(ExpectedConditions.ElementIsVisible(By.Id("txtFirstName"))).SendKeys("John");
waitForTextBox.Until(ExpectedConditions.ElementIsVisible(By.Id("txtLastName"))).SendKeys("Skeet");

or if instead of reusing waitForTextBox, I will need do like this:

var waitForFirstName = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
waitForFirstName.Until(ExpectedConditions.ElementIsVisible(By.Id("txtFirstName"))).SendKeys("John");

var waitForLastName = new WebDriverWait(driver, TimeSpan.FromSeconds(30));              
waitForLastName.Until(ExpectedConditions.ElementIsVisible(By.Id("txtLastName"))).SendKeys("Skeet");
2

There are 2 answers

2
Greg Burghardt On BEST ANSWER

Reusing the WebDriverWait objects for multiple "waits" is best. The only time you need a different WebDriverWait object is if you need two different timeout periods. Otherwise the only state that a WebDriverWait keeps is the driver, how long it waits, and a list of exception types that should be ignored.

0
Click Ok On

Ok, I found the source code for the WebDriverWait and Until method, and I find there is no problem reusing this object:

    public virtual TResult Until<TResult>(Func<T, TResult> condition, CancellationToken token)
    {
        if (condition == null)
        {
            throw new ArgumentNullException("condition", "condition cannot be null");
        }

        var resultType = typeof(TResult);
        if ((resultType.IsValueType && resultType != typeof(bool)) || !typeof(object).IsAssignableFrom(resultType))
        {
            throw new ArgumentException("Can only wait on an object or boolean response, tried to use type: " + resultType.ToString(), "condition");
        }

        Exception lastException = null;
        var endTime = this.clock.LaterBy(this.timeout);
        while (true)
        {
            token.ThrowIfCancellationRequested();

            try
            {
                var result = condition(this.input);
                if (resultType == typeof(bool))
                {
                    var boolResult = result as bool?;
                    if (boolResult.HasValue && boolResult.Value)
                    {
                        return result;
                    }
                }
                else
                {
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                if (!this.IsIgnoredException(ex))
                {
                    throw;
                }

                lastException = ex;
            }

            // Check the timeout after evaluating the function to ensure conditions
            // with a zero timeout can succeed.
            if (!this.clock.IsNowBefore(endTime))
            {
                string timeoutMessage = string.Format(CultureInfo.InvariantCulture, "Timed out after {0} seconds", this.timeout.TotalSeconds);
                if (!string.IsNullOrEmpty(this.message))
                {
                    timeoutMessage += ": " + this.message;
                }

                this.ThrowTimeoutException(timeoutMessage, lastException);
            }

            Thread.Sleep(this.sleepInterval);
        }
    }

I will mark the previous answer as correct, just putting here for a more detailed and added authoritative source also.