This page describes some useful Selenium tips on CSS rules and pseudo-classes that will help you understand how to convert your XPATH locators to CSS, a native approach on all browsers.
A CSS Selector is a combination of an element selector and a value which identifies the web element within a web page. They are string representations of HTML tags, attributes, Id and Class. As such they are patterns that match against elements in a tree and are one of several technologies that can be uses to select nodes in an XML document.
A direct child in XPATH is defined by the use of a “/“, while on CSS, it’s defined using “>”
CSS: div > a
Child or subchild
If an element could be inside another or one it’s childs, it’s defined in XPATH using “//” and in CSS just by a whitespace.
CSS: div a
An element’s id in XPATH is defined using:
“[@id='example']” and in CSS using:
“#” - ID's must be unique within the DOM.
XPath: //div[@id='example'] CSS: #example
For classes, things are pretty similar in XPATH:
“[@class='example']” while in CSS it’s just “.”
XPath: //div[@class='example'] CSS: .example
This is useful for navigating lists of elements, such as forms or ul items. The next sibling will tell selenium to find the next adjacent element on the page that’s inside the same parent. Let’s show an example using a form to select the field after username.
<form class = "form-signin" role = "form" action = "/index.php" method = "post"> <h4 class = "form-signin-heading"></h4> <input type = "text" class = "form-control" id = "username" name = "username" placeholder = "username" required autofocus></br> <input type = "password" class = "form-control" id = "password" name = "password" placeholder = "password" required> <p> <button class = "btn btn-lg btn-primary btn-block radius" type = "submit" name = "login">Login</button> </form>
Let’s write an XPath and css selector that will choose the input field after “username”. This will select the “alias” input, or will select a different element if the form is reordered.
CSS: .username + input
If you don’t care about the ordering of child elements, you can use an attribute selector in selenium to choose elements based on any attribute value. A good example would be choosing the ‘username’ element of the form above without adding a class.
We can easily select the username element without adding a class or an id to the element.
We can even chain filters to be more specific with our selectors.
Here Selenium will act on the input field with name="login" and type="submit"
Choosing a specific match
CSS selectors in Selenium allow us to navigate lists with more finess that the above methods. If we have a ul and we want to select its fourth li element without regard to any other elements, we should use nth-child or nth-of-type.
<ul id = "recordlist"> <li>Cat</li> <li>Dog</li> <li>Car</li> <li>Goat</li> </ul>
If we want to select the fourth li element (Goat) in this list, we can use the nth-of-type, which will find the fourth li in the list.
CSS: #recordlist li:nth-of-type(4)
On the other hand, if we want to get the fourth element only if it is a li element, we can use a filtered nth-child which will select (Car) in this case.
CSS: #recordlist li:nth-child(4)
Note, if you don’t specify a child type for nth-child it will allow you to select the fourth child without regard to type. This may be useful in testing css layout in selenium.
CSS: #recordlist *:nth-child(4)
CSS in Selenium has an interesting feature of allowing partial string matches using ^=, $=, or *=. I’ll define them, then show an example of each:
^= Match a prefix
A link with an “id” that starts with the text “id_prefix_”
$= Match a suffix
A link with an “id” that ends with the text “_id_sufix”
*= Match a substring
A link with an “id” that contains the text “id_pattern”
Matching by inner text
And last, one of the more useful pseudo-classes, :contains() will match elements with the desired text block:
CSS: a:contains('Log Out')
This will find the log out button on your page no matter where it’s located. This is by far my favorite CSS selector and I find it greatly simplifies a lot of my test code.
Sauce Labs - Selenium Testing on the Cloud