Explicit wait usage in Selenium C Sharp using lambda functions
We know that the implicit wait is the default wait time for which selenium waits to find an element on the webpage. Also, driver.findelement or driver.findelements internally call the implicit wait default timeout. After 20 seconds, selenium will throw an error if the element is not found.
Now sometimes, you might want to wait a little bit more for a certain element on a webpage. This is done using explicit wait.
Let us say we go to below website, enter ‘To’ and ‘From’ city & click search
Sometimes the above search results window might take a lot of time to load and display the results. You might see the previous window ‘Hold on, we're fetching flights for you’ for a longer time.
So basically, the wait time can be more or less (dynamically changes) for our search results to appear on a webpage. See below.
So the default implicit wait setup for 20 seconds might not work for the intermediate box ‘Hold on, we're fetching flights for you’. So we have to use explicit wait here.
Explicit wait is implemented by an inbuilt class ‘WebDriverWait’.
So we can tell selenium to explicitly wait for 30 seconds for the ‘VIEW PRICES’ button to become visible instead of 20 seconds implicit wait
So this is the overall concept. Let us practically see how explicit wait works.
The use case that we will look into is: we will launch https://www.way2automation.com/ and explicitly wait for 30 seconds for the link ‘Lifetime Membership’ to become visible on the webpage. Once the link is visible, we will click it
Line#33 declares the explicit wait of 30 sec. Line#35 will help us in ignoring few exceptions during runtime
Next see below figure. We created a lambda function expWaitForElement of type boolean that returns either true or false. We than create a variable wd of type IWebDriver (line 3) which we than use in line 39 to find an element (Since we are already using driver variable in line 31, we have created another variable wd). We than store this element reference in elem variable (line 39). Now, we create an ‘if’ condition. If the element is visible on the webpage, it would be clicked and we are also logging a text for this purpose (line 42).
If the method returns true, lambda function expWaitForElement (line 49) will be called using expwait object reference. So basically, we are asking selenium to explicitly wait until the method is called expwait.Until(expWaitForElement);
Save and execute (Test > Test Explorer)
Notice below that the link is found and gets clicked
The test is pass
Notice the console log below
Code for above execution:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebDriverManager.DriverConfigs.Impl;
namespace NunitTestProject
{
class FirstSelenTest
{
IWebDriver driver;
[SetUp]
public void InvokeBrowser()
{
new WebDriverManager.DriverManager().SetUpDriver(new ChromeConfig());
driver = new ChromeDriver();
driver.Manage().Window.Maximize();
}
[Test]
public void Test1()
{
driver.Url = "https://www.way2automation.com/";
WebDriverWait expwait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
expwait.IgnoreExceptionTypes(typeof(NoSuchElementException),typeof(ElementNotVisibleException));
Func<IWebDriver, bool> expWaitForElement = new Func<IWebDriver, bool>((IWebDriver wd) =>
{
IWebElement elem = wd.FindElement(By.LinkText("Lifetime Membership"));
if (elem.Displayed)
{
TestContext.Progress.WriteLine("LifeTime Membership link is loaded");
elem.Click();
return true;
}
return false;
}
);
expwait.Until(expWaitForElement);
}
}
}
Let us make a typo error in the link text (line 39)
Run the test, notice that the link does not get clicked
Selenium explicitly waits for 30 sec for this link and then throws the error as shown below
Code snippet for above execution:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebDriverManager.DriverConfigs.Impl;
namespace NunitTestProject
{
class FirstSelenTest
{
IWebDriver driver;
[SetUp]
public void InvokeBrowser()
{
new WebDriverManager.DriverManager().SetUpDriver(new ChromeConfig());
driver = new ChromeDriver();
driver.Manage().Window.Maximize();
}
[Test]
public void Test1()
{
driver.Url = "https://www.way2automation.com/";
WebDriverWait expwait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
expwait.IgnoreExceptionTypes(typeof(NoSuchElementException),typeof(ElementNotVisibleException));
Func<IWebDriver, bool> expWaitForElement = new Func<IWebDriver, bool>((IWebDriver wd) =>
{
IWebElement elem = wd.FindElement(By.LinkText("LifeTime Membership"));
if (elem.Displayed)
{
TestContext.Progress.WriteLine("LifeTime Membership link is loaded");
elem.Click();
return true;
}
return false;
}
);
expwait.Until(expWaitForElement);
}
}
}
In the above example, the return type was boolean. Let us now see another example where the return type is string.
The task is to fetch the string title of page
Let us comment the previous function
Let us write a new lambda function. The string will be stored in a variable ‘t’ and we are returning a string (line 39). We are then verifying if the title contains the string ‘Selenium’. If yes, than we are returning the title (line 42) and the function gets executed (line 46). We are printing the title (line 47)
Save and execute. Notice below that the page title gets printed in the ‘Output’ window
Code for above execution:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebDriverManager.DriverConfigs.Impl;
namespace NunitTestProject
{
class FirstSelenTest
{
IWebDriver driver;
[SetUp]
public void InvokeBrowser()
{
new WebDriverManager.DriverManager().SetUpDriver(new ChromeConfig());
driver = new ChromeDriver();
driver.Manage().Window.Maximize();
}
[Test]
public void Test1()
{
driver.Url = "https://www.way2automation.com/";
WebDriverWait expwait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
expwait.IgnoreExceptionTypes(typeof(NoSuchElementException),typeof(ElementNotVisibleException));
Func<IWebDriver, string> expWaitForPageTitle()
{
return ((t) =>
{
if (t.Title.Contains("Selenium"))
return t.Title;
return null;
});
}
expwait.Until(expWaitForPageTitle());
TestContext.Progress.WriteLine(expwait.Until(expWaitForPageTitle()));
/*
Func<IWebDriver, bool> expWaitForElement = new Func<IWebDriver, bool>((IWebDriver wd) =>
{
IWebElement elem = wd.FindElement(By.LinkText("Lifetime Membership"));
if (elem.Displayed)
{
TestContext.Progress.WriteLine("LifeTime Membership link is loaded");
elem.Click();
return true;
}
return false;
}
);
expwait.Until(expWaitForElement);
*/
}
}
}
We can now add line 48 as shown below. This will get executed only if the page title is returned (line 42)
Save and execute, notice below that ‘Lifetime Membership link gets clicked
Let us make a typo in the page title (line 41)
Save and execute. This time line 48 will not execute since selenium will not be able to search for the incorrect title “SeleJnium”
Code for above execution:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebDriverManager.DriverConfigs.Impl;
namespace NunitTestProject
{
class FirstSelenTest
{
IWebDriver driver;
[SetUp]
public void InvokeBrowser()
{
new WebDriverManager.DriverManager().SetUpDriver(new ChromeConfig());
driver = new ChromeDriver();
driver.Manage().Window.Maximize();
}
[Test]
public void Test1()
{
driver.Url = "https://www.way2automation.com/";
WebDriverWait expwait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
expwait.IgnoreExceptionTypes(typeof(NoSuchElementException),typeof(ElementNotVisibleException));
Func<IWebDriver, string> expWaitForPageTitle()
{
return ((t) =>
{
if (t.Title.Contains("SeleJnium"))
return t.Title;
return null;
});
}
expwait.Until(expWaitForPageTitle());
TestContext.Progress.WriteLine(expwait.Until(expWaitForPageTitle()));
driver.FindElement(By.LinkText("Lifetime Membership")).Click();
/*
Func<IWebDriver, bool> expWaitForElement = new Func<IWebDriver, bool>((IWebDriver wd) =>
{
IWebElement elem = wd.FindElement(By.LinkText("Lifetime Membership"));
if (elem.Displayed)
{
TestContext.Progress.WriteLine("LifeTime Membership link is loaded");
elem.Click();
return true;
}
return false;
}
);
expwait.Until(expWaitForElement);
*/
}
}
}
Thank you for reading!