Selenium: Finding and Interacting with Elements
Selenium: Finding and Interacting with Elements
In this post we will cover a few more advanced topics in regards to finding and interacting with page elements using Selenium web browser automation. If you are not already familiar with the Selenium basics you might want to read our introduction guide first.
Finding Elements
Before you can interact with any element on the webpage you need to help Selenium find the correct element. This is relatively easy if we are talking about static elements but can get complex rather fast with elements that change dynamically. Let us tackle the easy ones first and then move on to a more complex example.
Static Elements
Let us imagine that we have simple search engine page with just a text input and button as possible elements. The HTML for this could look something like this:
<form>
<input name="searchQuery" type="text" />
<input name="submitSearch" type="submit" />
</form>
As one would expect finding these static elements is a rather easy tasks using Selenium. You could simple search them by their unique name attribute.
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.testpage.com");
IWebElement searchQuery = driver.FindElement(By.Name("searchQuery"));
IWebElement submitSearch = driver.FindElement(By.Name("submitSearch"));
// ...
driver.Quit();
Of course the name attribute will not always be unique or the best option. Other search possibilities are:
- ClassName
- LinkText
- PartialLinkText
- TagName
Dynamic Elements
Unfortunately in many cases the elements will not have a static unique identifier you can use. For our next example we take a look at a category list in a web shop implementation. As categories are added or removed the links and their attributes will change so we cannot just target one of the visible ids.
<ul>
<li><a href="#software" id="14_category">Software</a></li>
<li><a href="#hardware" id="33_category">Hardware</a></li>
<li><a href="#printer" id="19_category">Printer</a></li>
</ul>
So how can we write test code that is able to identify the Hardware category regardless of id and position in the list? Firstly we will identify all category links by using a css selector. Then we can iterate all found links until we find the one which has ‘Hardware’ as a link text.
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.testpage.com");
List<IWebElement> links = driver.FindElements(By.CssSelector("a[id$='_category']"));
foreach (IWebElement link in links)
{
if (link.Text.Equals("Hardware"))
{
// ...
}
}
driver.Quit();
This way you can find elements which are dynamically placed on the page and do not have a unique page-wide identifier.
Interaction
Now that we can find and identify elements we might as well try to interact with them.
Simple Interactions
For the most basic interactions (clicking and text input) Selenium has pretty good standard methods. These come with quite a few logic backed into them so if possible you should use them over custom actions. The below example will fill out a search box and click the search button to submit a form.
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.browseemall.com/Blog");
IWebElement search = driver.FindElement(By.Id("search-field"));
search.SendKeys("Selenium");
IWebElement submit = driver.FindElement(By.Id("searchsubmit"));
submit.Click();
driver.Quit();
Quite easy right?
Complex Interactions
While the basic interactions will be sufficient for most testing tasks sooner or later you will encounter a situation when these are not enough. For this Selenium has the possibility to create custom actions which can do things like Drag & Drop, double click, mouse move, right click and execute longer key combinations. Lets look at 2 different examples.
The first example will show how you can create a custom action to press the hotkey CTRL + ENTER:
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.example.com");
IWebElement textarea = driver.FindElement(By.Id("search"));
// Create a custom action for CTRL+ENTER
Actions action = new Actions(driver);
action.KeyDown(Keys.Control).KeyDown(Keys.Enter).KeyUp(Keys.Enter).KeyUp(Keys.Control).Build().Perform();
driver.Quit();
In the next example we will use custom actions to activate a hover state menu. First we will use an action to move the mouse over the menu, then we will instruct Selenium to wait until the sub-menu appears and finally we will click the logout link hidden in the sub-menu.
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.browseemall.com");
IWebElement menu = driver.FindElement(By.Id("menu"));
IWebElement logout = driver.FindElement(By.Id("logout"));
// Move mouse over the menu
Actions action = new Actions(driver);
action.MoveToElement(menu).Build().Perform();
// Wait until logout button appears
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("logout")));
// Click logout
logout.Click();
driver.Quit();
Now you know enough to start creating more complex tests for dynamic web applications or complex input situations. Have fun!