📜 ⬆️ ⬇️

CSS selectors and their use in test automation software

All good!

We have already disclosed this topic at the webinar, which was conducted by our teacher, but we decided to add a little text (and, as it turned out, it was more convenient for many). In general, we present an article on the topic “CSS Selectors” , which Pavel Popov worked through in the course of our course “Automation in Testing” .

Go.
')
Each course or article for automation beginners talks about a convenient and versatile means of finding elements of a Web page, like XPath. This type of element locator was created in 1999 to point to elements in XML files. With built-in functions, XPath has become a very popular tool for finding items on a Web page. If your application's HTML code looks something like this:

… <form class=“form_upload> <div> <div class=“row_element_3 row tile_fixed”> <div class=“button_cell wrapper_tile”> <button type=“submit” class=“button_submit wrapper_button”> </button> </div> </div> </div> </form> … 

and you can not find a decent XPath for the button “Click me”, you should not immediately run towards the developer asking for help. There is a great opportunity to use the CSS selector, it will look like this:

 .button_submit 

Welcome to the world of CSS .



It is considered that in CSS selectors everything is tied to classes. This is not quite true, but if the Web application uses the “optimizer” or “obfuscator” of the HTML code, it looks like this:

 <form class=“afhfsdh__”> <div> <div class=“hfgeyq fjjs qurlzn”> <div class=“fjdfmzn fjafjd”> <button type=“submit” class=“ajffalf wjf_fjaap”></button> </div> </div> </div> </form> … 

(all css class names are reduced using the optimizer)

, it will not be possible to get a short CSS selector - as a rule, after each new build of css classes change to new ones. But still, the CSS selector may be easier in this case: css: form button[type='submit'] , instead of XPath: //form//button[@type='submit']

Suppose that HTML optimizers are not installed and the developers do not plan to use it on the project (check this fact!).

As you might have guessed, a symbol. is used instead of the word class and will look for the occurrence of this class in any element, regardless of the number of classes for this element.

See:

 <form class=“form_upload> <div> <div class=“row_element_3 row tile_fixed”> <div class=“button_cell wrapper_tile”> <button type=“submit” class=“button_submit wrapper_button”></button> </div> </div> </div> </form> 


css for the button: .button_submit , while the .wrapper_button class is optional, but if it is needed to point to our class, we can add it immediately after the first css class is specified: css: .button_submit.wrapper_button . The order of classes does not matter, so you can swap them:

  .wrapper_button.button_submit . 

The next indispensable tool in the search for HTML elements are tags. It is very easy to write a css selector pointing to the button tag, especially since it has already been written in this sentence. CSS selector for button -

 css: button. 

And you don't need to specify anything else if your goal is to bind to a tag. Combining tags and classes we get ::

 button.button_submit 

and it is also a css selector to our element.

In addition to tags, attributes also help to uniquely identify an element on a page. Often, developers create additional attributes instead of adding new “IDs”, for example, can create additional data-id or auto-id attributes for each element with which further action is planned. For example, developers can add the data-id attribute to our button button. Then the attributes using the css selector can be accessed through curly brackets: [data-id='submit'] . Additionally, you can omit the attribute value after the character equal to [data-id] . Such a selector will find you all the elements that have a data-id attribute with any value inside. You can also specify the class attribute to search for our button: [class='button_submit'] , but in CSS, as you already know, you can be lazy and write like this: .button_submit . Putting it all together is also quite simple:

 button[type='submit'].button_submit    

But it is a great success if we manage to find an element using a selector with only one element, such as using the [data-id] attribute, which uniquely finds one element on the page. Very often we have to use the ancestors of an element to find a descendant. And this in CSS is also possible to do quite simply:

 <form class=“form_upload> <div> <div class=“row_element_3 row tile_fixed”> <div class=“button_cell wrapper_tile”> <button type=“submit” class=“button_submit wrapper_button”></button> </div> </div> </div> </form> 


 css:form > div > div > div > button.button_submit 

and the > sign allows you to find an element exclusively in the ancestor inside. But to write all the elements is unnecessary, since in CSS there is the ability to search in all descendants, this character is a space “ “ . Using this pointer we can quickly find the element inside the form:

It was: css: form > div > div > div > button.button_submit
It became: css: form button,button_submit

It is also convenient to find the next “relative” through the previous one. Let's add our example with one more span :

 <form class=“form_upload> <div> <div class=“row_element_3 row tile_fixed”> <div class=“button_cell wrapper_tile”> <div class=“content”></div> <span data-id=“link”></span> <!--    data-id --> <button type=“submit” class=“button_submit wrapper_button”> <!--   --></button> </div> </div> </div> </form> 

[data-id='link'] + button will find the button , which has a relative higher by one attribute with the data-id=”link” attribute. This pointer can be used when the previous element has an id or a unique attribute, and the element that is next to the one you need does not have such identifiers. So, using the + css symbol, the selector will find the next relative.

NOTE:

 div + span[data-id='link'] + button 

Additionally, you can build a “train” of the following elements using the + pointer, but I do not advise doing this because of a possible change in the location of the elements.

Do not miss the search option on the part of the attribute. This is done simply: button[class*='submit'] - from the long class name button_submit we take only the right side of submit and add to the sign = the symbol *. You can also find the word cell from the class value: div[class*='cell'] .

There is another feature of css selectors that will allow you to find all the links or file extensions, is ^= and $= , but this task is not as common as searching for the attribute value.

a[href^=“https:”] - will find all links that start with https,
a[href$=“.pdf”] - will find all links that end in .pdf.

A little bit about how to find descendants with the same tag from the ancestor. Let's start, as always, with an example:

 <div class=“tiles”> <div class=“tile”>…</div> <div class=“tile”>…</div> </div> 

How to find the second div class=“tile” in div class=“tiles” ? Option two:

 div > div:nth-of-type(2) div > div:nth-child(2) 

But what is the difference between these two selectors? Let's add an example:

 <div class=“tiles”> <a class=“link”>…</a> <!—1—> <div class=“tile”>…</div><!—2—> <div class=“tile”>…</div><!—3—> </div> 

css 1 option: div > div:nth-of-type(2)
css 2 option: div > div:nth-child(2)

Now these selectors lead to two different elements. Before going further, try to guess which selector leads to which element?

Solution:

the first selector will point to line number 2, while the second selector will point to line number 3. nth-child searches for the second div , which is a descendant of the parent. Second
  <div> 
at the element
  <div class = “tiles”> 
This is the third line. In turn, the nth-of-type searches for the second element in the parent.
  <div class = “tiles”> 
which must be a tag
  div 
This is line number two.

There is a rule that allows you to simplify working with selectors in a situation where you need to find a specific element: use nth-of-type wherever possible. If you figured out the example above, I recommend that you always pay attention to the number of identical elements in an ancestor, using nth-child , and then you will not care where they put the link
  <a> 
: upstairs between
  <div> 
or at the bottom of the block, always the selector div:nth-child(2) will still point to the desired element - the second div element inside the block.

Another item search function by id was omitted. You already know that the search for any of the attributes is carried out using the specification of square brackets [attribute=“value”] and for our case we can find the element like this [id=“value”] . And what if there is a faster way to search by id element?

 #value. “#” - ,     id. 

Using all acquired skills try writing a selector for a button.
  <button> 


  … <div> <div class=“tile_wrapper tile content”> <div class=“row row_content”> <div class=“outline description__on”></div> <div class=“outline description__off button_send hover_mouse”> <button class=“outline button_send”></button> </div> </div> </div> </div> 

We will be glad to see your comments and options in the comments here or discuss it at the next open lesson, which will be held on March 13th.

Thank!

Source: https://habr.com/ru/post/350368/


All Articles