Selector strategies
Tags: qa, automation, selectors, sqa
Published: 2024-03-09 00:19:43

Selectors are crucial in Test Automation because they help identify and interact with elements within the user interface of an application or webpage.

There are mainly two types of selectors, Xpath and CSS selectors. Depending on the situation both of these techniques can be helpful. So in this thread, I will discuss the basics of both techniques. 

Before starting with the strategies we need to understand some basics of a DOM( Document Object Model) tree. In the DOM tree, elements are represented as nodes, and each node can have different types. The main types of nodes in the DOM tree include element nodes, attribute nodes, and text nodes.

## Tagname:

In the DOM tree, the tagname corresponds to the element node's name.
Element nodes represent the structure of an XML or HTML document, and they contain other nodes or elements.
For example, if you have ```<book>Harry Potter</book>```, "book" is the tagname of the element node.

## Attribute:

Attributes are associated with element nodes in the DOM tree.
They provide additional information about elements.In the DOM tree, attributes are represented as separate nodes attached to their respective element nodes.
For instance, in ```<book id="1">Harry Potter</book>```, the attribute "id" with the value "1" is attached to the "book" element node.

## Value:

The value is usually associated with an attribute in the DOM tree. For example, in ```<book id="1">Harry Potter</book>```, “1" is the value of the attribute ‘id’ associated with the "book" element node.

## Text :

Text nodes contain the actual text content within XML or HTML elements.
For example, in the XML ```<book>Harry Potter</book>```, "Harry Potter" is the text node associated with the <book> element node.
Text nodes can also represent whitespace characters such as spaces, tabs, and line breaks.

## Xpath
Xpath stands for XML path language. 
Most of the automation frameworks/tools utilize Xpath for finding 
locator/selector in HTML dom structure.

There are two types of XPath. Absolute Xpath and Relative Xpath. Our focus will mainly be relative Xpath since absolute XPath are subject to changes hence not that useful for automation. An absolute XPath starts with '/' whereas a relative Xpath starts with '//' 

The basic XPath format of relative Xpath is

```xpath
//tagname[@Attribute='value']
//tagname[@Attribute]
```

Now in many cases for any given element the value of attributes is dynamic, that is the values are subject to change. To tackle this issue we can use functions.

## 'starts-with' function: 

By utilizing this function we can target/select an element which have dynamic value but the starting text of the value is always the same.

Here is the syntax of the starts-with() function:

```xpath
//tagname[starts-with(@attribute, 'value')]
```
## 'contains' Function:

The contains() function in XPath is utilized to select elements that contain a specified substring within their attribute values or text content.

Here is the syntax of the contains() function:

```xpath
//tagname[contains(@attribute, 'value')]
//tagname[contains(text(), 'value')]
```
## 'text' Function:

The text function can be used to select an element that contains certain text.

Here is the syntax of the text() function:

```xpath
//tagname[text() = 'actualValue')]
```

## AND, OR operator in XPath 

In some cases, we might need to target an element that has different locators that are based on other available actions of the page the locator changes in that case we can utilize the OR operator.

Here is the syntax of the OR operator:

```xpath
//tagname[@Attribute1='value1' OR @Attribute2='value2']
```

Similarly, in some other cases, we might need to target an element that doesn't have a unique attribute-value pair but if we combine two attribute-value then we can target the element. In such case, we can use the AND operator.

Here is the syntax of the AND operator:

```xpath
//tagname[@Attribute1='value1' AND @Attribute2='value2']
```

## Xpath Axes Method:

We can utilize axes methods to traverse through the DOM tree. axes defines the relationship between elements.

Here is the syntax for axes:

```xpath
//tagname[@Attribute='value']//axes::tagname[@Attribute='value']
```
- Ancestor Axis (ancestor::): This axis selects all ancestors (parent, grandparent, etc.) of the current node.

- Ancestor-or-Self Axis (ancestor-or-self::): This axis selects the current node and all of its ancestors.

- Child Axis (child::): This axis selects all children of the current node.

- Descendant Axis (descendant::): Selects all descendants (children, grandchildren, etc.) of the current node.

- Descendant-or-Self Axis (descendant-or-self::): This axis selects the current node and all of its descendants.

- Following Axis (following::): Select all nodes that appear after the current node in document order.

- Following-Sibling Axis (following-sibling::): Selects all siblings that appear after the current node.

- Namespace Axis (namespace::): This axis selects the namespace nodes of the current node.

- Parent Axis (parent::): Selects the parent of the current node.

- Preceding Axis (preceding::): Selects all nodes that appear before the current node in document order.

- Preceding-Sibling Axis (preceding-sibling::): Selects all siblings that appear before the current node.

- Self Axis (self::): This axis selects the current node.

Finally, we can also try different combinations of these function operators and axes as well.

## CSS Selectors

CSS stands for cascading style sheet. CSS selectors are very efficient in locating elements. A lot of automation tools/framework supports CSS selectors. Cypress, Robot Framework, and Puppeteer to name a few. 

The basic syntax for CSS selectors is 

```xpath
tagname[attribute='value']
```
Additionally, we can also select any element based on its ID or class. 

Select By ID - 

```xpath
 #ID 
``` 
Select By Class -

```xpath 
.class 
```

## Sub-String Matching Technique

Similar to the starts-with and contains the functionality of Xpath we can also do pattern matching in CSS selector.

## Prefix - '^':

Utilizing this symbol we can target an element that has a dynamic 
value for a tagname but the value always starts with a specific sub-string.

Here is the syntax for the prefix -

```xpath
tagname[attribute^='value']
```
## Suffix - '$':

Similarly, if the value of the tagname ends with a specific pattern then we can match the end sub-string

Here is the syntax for the suffix -

```xpath
tagname[attribute$='value']
```
## Contains - '*':

Additionally, we can use the wildcard (*) symbol to just match the sub-string of the value at any given place.

Here is the syntax for the contains -

```xpath
tagname[attribute*='value']
```

## AND, OR operation

We can utilize the 'AND', and 'OR' operations in CSS selectors as well. 

Here is the syntax for the AND operation -

```xpath
tagname[attribute='value'] tagname[attribute='value']
```

Basically ' ' denotes the AND operation in the CSS selector technique.

Here is the syntax for the OR operation -

```xpath
tagname[attribute='value'],tagname[attribute='value']
```

',' denotes the OR operation.

## Traversing In CSS Selector:

The syntax for traversing is as follows:

```xpath
tagname[attribute='value'](traverse symbol here)tagname[attribute='value']
```

- Descendant selector ( ): This selects all elements that are descendants of a specified element. For example, `div p` selects all `<p>` elements that are descendants of `<div>` elements.

- Child selector (>): This selects all elements that are direct children of a specified element. For example, `div > p` selects all `<p>` elements that are immediate children of `<div>` elements.

- Adjacent sibling selector (+): This selects an element that is immediately preceded by a specified element. For example, `h2 + p` selects the <p> element that directly follows an `<h2>` element.

- General sibling selector (~): This selects all elements that are siblings of a specified element and are preceded by the specified element. For example, h2 `~ p` selects all `<p>` elements that are siblings of an `<h2>` element and comes after it.

Unfortunately in the CSS selector technique traversing to the parent is not possible.

## Pseudo-classes:

We can also utilize pseudo-classes to target our elements.

The format for pseudo-classes is as follows

```xpath
tagname[attribute='value']:pseudo-class()
```

- :hover: This pseudo-class is used to apply styles when the mouse pointer is over an element. 

- :active: Applied to an element while it is being activated by the user. For example, when a user clicks on a button, it becomes active.

- :focus: Applied to an element when it receives focus, usually through keyboard navigation or clicking. 

- :visited: Applies to links that have been visited by the user. This pseudo-class is used to distinguish visited links from unvisited ones.

- :nth-child() and :nth-of-type(): These pseudo-classes allow you to select elements based on their position within a parent element. For example, `:nth-child(odd)` selects every odd child element of its parent.

- :first-child and `:last-child:` Selects the first or last child element of its parent.

- :not(): This pseudo-class selects elements that do not match a specific selector. For example,` :not(.class)` selects all elements that do not have the specified class.

- :checked: Applied to input elements (such as checkboxes or radio buttons) that are checked.

- :enabled: This pseudo-class selects elements that are enabled, which are the opposite of disabled elements.

- :disabled: This pseudo-class selects elements that are disabled, typically form elements like buttons, input fields, checkboxes, and radio buttons.

Pseudo-classes can be very powerful for assertion as you might have already guessed. We can also use the combinations of these techniques to target a unique element.

Thank you for taking the time to read this. I hope you found it informative and enjoyable. If you have any questions, comments, or feedback, please don't hesitate to reach out.