Photo by KOBU Agency on Unsplash
Let's discuss CssSelector, a lesser-known figure in the Selenium community.
As we know, to identify an element in the Application Under Test, the tool needs to identify the element and this is the place where the tool needs to be performant enough, in the case of selenium we have plenty of options like Id, xPath, CSS, etc
ID
These are simple and unique, so they operate quickly, but it is hard for a developer to utilize them for every other DOM element.
driver.findElement(By.id("unique_key"));
XPath
XPATH is a query language for XML-like documents, so they require an additional layer of translation to be processed by the browser, which can introduce performance overhead.
to fetch xpath for any Element in the website, follow the below steps
Open developer tools of the browser
Navigate to the element in the DOM
What we get is : /html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[1]
xpath is nothing but a path for Selenium to locate the element
string searchBtnXpath = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[4]/center/input[1]";
driver.findElement(By.xpath(googleSearchBtnXpath));
cssSelector
If you want your scripts to be effective even when there isn't an element's id, cSS Selector is the way to go.
CSS selectors have native browser support, making them faster in execution. Browsers are optimized to handle CSS selectors efficiently, as they are part of the fundamental web technologies.
Let's discuss how we could use CSS in place of xPath
- When we have id for an element
string searchBtnId = "UniqueBtn";
driver.findElement(By.xpath($"//div[@id='{searchBtnId}']"));
driver.findElement(By.cssSelector($"#{searchBtnId}")); // # is used for id
When we need to point to a class
string searchBtnClass = "className"; driver.findElement(By.xpath($"//div[@class='{searchBtnId}']")); driver.findElement(By.cssSelector($".{searchBtnId}")); // . is used for class
When we have a single type of element on a page
string imageTypeElement = "img";
driver.findElement(By.xpath($"//{imageTypeElement}"));
driver.findElement(By.cssSelector($"{imageTypeElement}"));
- When we need to point a direct child
driver.findElement(By.xpath("//div/a"));
driver.findElement(By.cssSelector("div > a"));
When we need to avoid any changes and point to a sub-child by skipping layers
xpath does it with two-forward slashes {//}
css does it with a whitespace
driver.findElement(By.xpath("//div//a"));
driver.findElement(By.cssSelector("div a"));
When we want to select an element whose identifier is not given but we know it's sibling's identifier
<form class = "form-signin" role = "form" action = "/index.php" method = "post">
<input type = "text" id = "username" name = "username" placeholder = "username" required autofocus></br>
<input type = "password" placeholder = "password" required>
<button type = "submit" name = "login">Login</button>
</form>
Now, suppose we want to enter details in the password text bow, how do we do this is
string xPathForPassword = "//input[@id='username']/following-sibling:input[1]";
string cssForPassword = "#username + input";
//To select button using usernane
string cssForButton = "#username + button[type="submit"]";
A scenario where we have only a class name and want to select a specific element type
<input class="control" type = "text"></br>
<label class="control">Name:</label>
css for label will be
cssOption1: label.control
cssOption2: label[class='control'] #it will select the element which has only one class 'control'
xpath : //label[@class='control']
To have multiple conditions for an element
string xPath = "//input[@name='login'and @type='submit']";
string css = "input[name='login'][type='submit']";
To select items from a list, to select 3rd item from list
<ul id = "cars">
<li>Car1</li>
<li>Car2</li>
<li>Car3</li>
<li>Car4</li>
</ul>
cssOption1: #cars li::nth-of-type(3)
cssOption2: #cars li::nth-child(3)
cssOption3: #cars *::nth-child(3)
xpath : //ul[@id='cars']/li[3]
The special case when we need to work with partial string matching
TO LOCATE A div WHOSE ID STARTS WITH 'Prefix_' toMatchPrefix: div[id^='Prefix_'] TO LOCATE A div WHOSE ID ENDS WITH '_Suffix' toMatchSuffix: div[id$='_Suffix'] TO LOCATE A div WHOSE ID CONTAINS 'subString' toMatchSuffix: div[id*='subString']