Enroll in Selenium Training

To understand this chapter you have to learn the concepts discussed in the earlier WebDriver Waits chapter. In the earlier chapter, we discussed some of the implicit waits. In this chapter we will look at Explicit waits and fluentwaits selenium C#, we call them explicit waits because these are explicitly applied to wait for conditions. Also, each explicit wait is different from the other one in the core waiting logic.

Its always good to start off with some example which we will try to solve using the Explicit wait. On our Practice Page we have a button element near the bottom of the page. Locator of this element is id="colorVar" , this element changes the color of the text from white to red after a few seconds. Our problem to solve will be to wait for the element until the color of the element is White and click on the element as soon as the color becomes Red.

We will solve this problem using the following waits

  1. WebDriverWait
  2. DefaultWait

General logic of Explicit waits fluentwaits selenium C#

The above two waits, in general the explicit waits, are smart waits. They are called smart primarily because they don’t wait for the max time out. Instead it waits for the time till the condition specified in .until(YourCondition) method becomes true.

A flow diagram explaining the working of Fluent wait is explained in the below diagram.

mplicitWait

When the until method is called, following things happen in strictly this sequence

  • Step 1: In this step smart/explicit wait captures the wait start time.
  • Step 2: Smart/Explicit wait checks the condition that is mentioned in the .until() method
  • Step 3: If the condition is not met, a thread sleep is applied with time out of the value mentioned in the .pollingInterval property call. In the example above it is of 250 milliseconds.
  • Step 4: Once the thread sleep of step 3 expires, a check of start time is made with the current time. If the difference between wait start time, as captured in step 1, and the current time is less than time specified in. Timeout property then step 2 is repeated.

This process keeps on happening till the time either the time out expires or the condition comes out to be true. The important point here is that your wait condition is evaluated after end of  every polling time duration. So we don't actually have to necessarily wait for the complete timeout.

WebDriver Wait

WebDriverWait is present in the OpenQA.Selenium.Support.UI namespace. This wait is a specialized form of DefaultWait class. We will discuss DefaultWait in the next section. Below is the code which uses a WebDriverWait

        static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("https://toolsqa.com/automation-practice-switch-windows/");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));

            Func<IWebDriver, bool> waitForElement = new Func<IWebDriver, bool>((IWebDriver Web) =>
            {
                Console.WriteLine(Web.FindElement(By.Id("target")).GetAttribute("innerHTML"));
                return true;
            });
            wait.Until(waitForElement);
        }

Here the whole logic of wait is encapsulated inside the Func delegate, which is present in System namespace. We have to pass Func delegate to the WebDriverWait.until method.

FluentWait function delegate

You can define a Func delegate like this Func<Type1, Type2> where Type1 is the input parameter and Type2 is the output parameter. WebDriverWait is tied to WebDriver, hence Type1 will always be equal to WebDriver and Type2, which is the return type, can be anything you want. In this example we have choosen the return type to be bool. So the definition of Func will become like this

       static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("https://toolsqa.com/automation-practice-switch-windows/");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
            Func<IWebDriver, bool> waitForElement = new Func<IWebDriver, bool>((IWebDriver Web) =>
            {
                Console.WriteLine("Waiting for color to change");
                IWebElement element = Web.FindElement(By.Id("target"));
                if(element.GetAttribute("style").Contains("red"))
                {
                    return true;
                }
                return false;
            });

            wait.Until(waitForElement);
        }

Here you can clearly see that the Func delegate return the same type as specified in Type2.

A small change in this Func definition can make us return a WebElement. With a small change we can now wait till the element is not present in Dom and as soon as the element is present we can return it. The code for this is show below

     static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("https://toolsqa.com/automation-practice-switch-windows/");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
            Func<IWebDriver, IWebElement> waitForElement = new Func<IWebDriver, IWebElement>((IWebDriver Web) =>
            {
                Console.WriteLine("Waiting for color to change");
                IWebElement element = Web.FindElement(By.Id("target"));
                if(element.GetAttribute("style").Contains("red"))
                {
                    return element;
                }
                return null;
            });

            IWebElement targetElement = wait.Until(waitForElement);
            Console.WriteLine("Inner HTML of element is " + targetElement.GetAttribute("innerHTML"));
        }

DefaultWait

Default wait is more generic wait in the sense that it is not bound to WebDriver. This wait can be used to pass in any object to wait on. Lets try to solve the above problem via DefaultWait now. We will first try to wait on the WebElement, here is the code

        static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("https://toolsqa.com/automation-practice-switch-windows/");
            IWebElement element = driver.FindElement(By.Id("colorVar"));
            DefaultWait<IWebElement> wait = new DefaultWait<IWebElement>(element);
            wait.Timeout = TimeSpan.FromMinutes(2);
            wait.PollingInterval = TimeSpan.FromMilliseconds(250);

            Func<IWebElement, bool> waiter = new Func<IWebElement, bool>((IWebElement ele) =>
                {
                    String styleAttrib = element.GetAttribute("style");
                    if (styleAttrib.Contains("red"))
                    {
                        return true;
                    }
                    Console.WriteLine("Color is still " + styleAttrib);
                     return false;
                });
            wait.Until(waiter);
        }

You can see that here DefaultWait is not tied to WebDriver. You can wait on anything you like, let's do some exercise to understand the concept more.

Exercise 1

  1. Go to http://toolsqa.com/automation-practice-switch-windows/
  2. There is a clock on the page that counts down till 0 from 60 second.
  3. You have to wait for the clock to show text "Buzz Buzz"

Try to use both WebDriverWait and DefaultWait. Solution with WebDriverWait is show below

        static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("https://toolsqa.com/automation-practice-switch-windows/");
            IWebElement element = driver.FindElement(By.Id("clock"));
            DefaultWait<IWebElement> wait = new DefaultWait<IWebElement>(element);
            wait.Timeout = TimeSpan.FromMinutes(2);
            wait.PollingInterval = TimeSpan.FromMilliseconds(250);

            Func<IWebElement, bool> waiter = new Func<IWebElement, bool>((IWebElement ele) =>
                {
                    String styleAttrib = element.Text;
                    if (styleAttrib.Contains("Buzz"))
                    {
                        return true;
                    }
                    Console.WriteLine("Current time is " + styleAttrib);
                     return false;
                });
            wait.Until(waiter);
        }

I hope you understand the usage of waits in details.

Implicit Wait Commands in Selenium WebDriver C#
Implicit Wait Commands in Selenium WebDriver C#
Previous Article
Switch Command in Selenium C#
Switch Command in Selenium C#
Next Article
Virender Singh
I am Virender Singh, I have around 14 years of experience in the Technology domain.
Reviewers
Lakshay Sharma's Photo
Lakshay Sharma

Similar Articles

Feedback