April 19, 2015

How Selenium WebDriver uses CSS Selectors

This information is based upon Alan Richardson's class, Selenium 2 WebDriver with Java. If there is one thing that I can credit getting my current automation engineer position at Fitbit, it is this course. 

About CSS Selectors

A CSS Selector matches a set of elements. CSS stands for Cascading Style Sheets, what HTML uses to style the page layout of the web page. It is reused in Selenium to match the DOM (Document Object Model) elements.


Install Firepath

Once they are installed, you can right click on a web element, and "Inspect in Firepath". 
Firepath will be a tab located in Firebug, far to the right. 

Basic CSS Selectors


  • * : match any element
  • #id : match any id, such as #p4. 
  • .classname : match a class such as ".normal".
  • [attribute] : Match on an attribute name.

With Firepath, you can investigate the DOM (Document Object Model) by XPath, CSS Selector, or Sizzle. At Fitbit, when we cannot select "By.id", we use "By.cssSelector". 
A demo page was set up for the class on Alan Richardson's website, the "Find By Playground"  at http://www.compendiumdev.co.uk/selenium/find_by_playground.php
If you right click on the "This is a paragraph text" and choose "Inspect in Firepath", the Firebug window pops up with the Firepath tab displayed. You can then select "CSS (X)" from the dropdown next to the word "Highlight". 

You can see that the id, #p1 is shown. 
See what happens when you enter the following text in the CSS textbox when on this page:

CSS TextWhat happens in the Document Object Model (DOM) on the test page
*All web elements are selected.
[id]All elements with ids are selected.
#p4The p4 id tag is selected.
pAll web elements that are HTML paragraph tags (p) are selected
p#p4All paragraphs with an id of p4 are selected. Just #p4 may also work, but it makes it more readable.
p.normalAll paragraph web elements of class="normal" will be selected. .normal would also work, but with the explicit "p" tag there, it makes it more readable.
.hasOn this page, there is a class called "this has multiple values". By searching on the text ".has" it picks up on the word "has" in the class description.

More Advanced CSS Selectors

Examples

  • tag[attribute] : match tags with an attribute
  • tag[attribute=”value”] : match tags with a specific attribute value, in this case named "value"
  • tag[attr1='val1'][attr2='val2'] : match tag using multiple attribute values called "val1" and "val2"
  • tag[attribute*=”alu”] " Partial match anywhere on the attribute called "value"
  • tag[attribute^=”val”] : Partial match start of value. ^ is the wildcard for the beginning of the word.
  • tag[attribute$=”lue”]: Partial match end of value. $ is the wildcard for the end of a word. 
  • tag[attribute~=”value”] : Match on space separated values
  • tag[a='val'], tag[b='val'] : is an 'or' grouping, where it is looking for the tags a='val' or b='val'. If there is no comma, is is looking for tags a='val' and b='val'
Go back to the "Find By Playground page"  at http://www.compendiumdev.co.uk/selenium/find_by_playground.php and enter Firepath. 
See what happens when you enter the following text in the CSS textbox when on this page:
CSS TextWhat happens in the Document Object Model (DOM) on the test page
p.classAll web elements of type paragraph with a class attribute are selected.
p[class='normal']All paragraph web elements of an attribute of type class = normal are selected.
div[class='specialDiv']All DIV elements with a class called "specialDiv".
div[class*='Div']With the "*=" it is doing a partial match, matching any class with the word "Div" in it. .
div[class$='Div']With the "$=" it is matching where "Div" is on the end of the class.
div[class^='special']With the "^=" it is matching where "special" is on the beginning of the class.
div[class~='has']With the "~=" it found the separate word "has" in "this has multiple values"
div[class='nestedDiv']Matches all class attributes which equals the word "nestedDiv".
div[class='nestedDiv'][name='nestedDiv']Matches on the class AND the name is the word "nestedDiv".
div[class='nestedDiv'], div[name='nestedDiv']Matches where the class OR the name is the word "nestedDiv".


How to use CSS Selectors

We use the selector By.cssSelector(<the css selector string>).
@Test
public void findElementsUsingCSSTag(){
 List<WebElement> elements; // We set up a collection of WebElements we are calling "element" using a "List"
 elements = driver.findElements(By.cssSelector("p")); // Store the entire list in the variable called "element". 
}
CSS Selector Paths
CSS Selectors can be found in relation to one another. 
  • A > B : Match Selector B which is directly under Selector A ( such as: <A><B/></A> )
  • A B : descendant
  • selectors separated by space i.e. “this then that”
  • Any degree of separation
  • e.g. “div li” would match but “div > li” would not
  • A + B : B siblings of an A
  • B:first-child : every B which is first child of something
Go back to the "Find By Playground page"  at http://www.compendiumdev.co.uk/selenium/find_by_playground.php. You can see that there is a bullet pointed unordered list of links ("jump to para 0", jump to para 1", etc.)

If you right click on "Jump to para 0" and "Inspect Element", you will see the HTML Code:

It looks like:
<div >
 <ul>
  <li> (Bullet Point #1 ) 
  </li>
  <li> (Bullet Point #2 ) 
  </li>
  ...   ...     ...
 </ul>
<div>

Let's say you wanted to select all the bullet points (the "li" tag in HTML) in an unordered list (The "ul" HTML tag) under the DIV tag, the CSS Selector would be:  div > ul > li. 
To verify this, we can go into Firepath and check this code:

Note the text on the bottom pane of Firepath: "25 matching nodes". 
Now, let's say we wanted to find out the number of bullet points by using the ".size()" method and and place it in a variable called numberOfLinks: 

int numberOfBulletPoints;
 
numberOfBulletPoints = driver.findElements(By.cssSelector("div > ul > li)).size());

More examples

See what happens when you enter the following text in the CSS textbox when on this page:
CSS TextWhat happens in the Document Object Model (DOM) on the test page
li + liFind all list items with list items as sibling.
div liFind all <div> tags that have <li> list items as a descendant.
li: first-childFind the first child of the list <li>

Related articles

No comments: