This site runs best with JavaScript enabled.

Cypress basics: Selecting elements

Filip Hric

October 05, 2020


Selectors can be painful. Especially when you are starting with test automation. During my recent Cypress workshop, I saw some people struggle with selectors and the reason was, that they were using a different approach for selecting elements on page. In this blog, I would like to showcase some basics on how to select elements on page using Cypress.

If you want to follow along this article, there’s a repo on my GitHub page where you’ll find all the examples.

Selecting a single element

In Cypress, you select elements using this syntax:

1cy.get('.selector')

For starters, let’s look into what goes into the .selector part. Cypress is selecting elements by querying DOM. You may be already familiar with such selectors if you have ever played with CSS or used jQuery or if you are familiar with document.querySelector command in JavaScript. Let’s see what does this mean. As an example we can look into a page that looks something like this:

Selecting different shapes with Cypress
To select elements, it is of course vital to see into the page. Markup of our page looks like this:

1<h1>Shapes:</h1>
2<div class="square"></div>
3<div id="circle"></div>
4<div shape="triangle"></div>

We can select an element using h1 tag. If we want to select one of our shapes, we can select a single element using either class, id or an attribute.

1cy
2 .get('h1') // select by tag
3 .get('.square') // select by class
4 .get('#circle') // select by id
5 .get('[shape="triangle"]'); // select by attribute

To select an element by class you need to use . prefix and to select an element by its it, you should prefix id with #. The most common attribute you might find on your page would be a placeholder for an input or even a test-id where your selector starts and ends with square brackets. If choose to we select an element that is found multiple times on our page, such as our div element, Cypress will select all three of them. Try it for yourself in the code!

Selecting child elements

When working with nested elements, these are often being referred to as child elements. The logic of nesting is simple. Child is nested by a parent. Each element can be both parent or child, depending on the relationship with some other element. In this next example, we have an html page where its structure looks something like this:

1<div class="square-big red">
2 <div class="circle green"></div>
3</div>
4
5<div class="square-big green">
6 <div class="circle red"></div>
7</div>
8
9<div class="square-big green">
10 <div class="square-small red">
11 <div class="circle green"></div>
12 </div>
13</div>

The structure is pretty simple and hopefully readable. All the green elements have a class .green on them, and all the circle elements have a class .circle on them. On the line 2, we have an element that has both of these classes. This will render a green circle. I made a screenshot of the actual page. Give yourself a moment and try to see how the html code corresponds with the rendered page (BTW, I left out the headings in the html code):

Selecting various elements on page

Let’s focus only the inner circles for now. Selecting our circle by class, using cy.get('.circle') would return all 3 elements. But we may want to narrow down our selection though. We can do that by specifying our selector. Which element(s) would you guess will be returned by this selector?

1cy
2 .get('.green .circle')

The correct answer is circles in square #2 and square #3. This selector will look for all .circle elements, that are inside any .green element. As we can see on our page, both of these are nested in a .green element, our big green square.

Now let’s say we want to select only the circle inside square #2. In other words, if the circle is inside a red square, we want to ignore it. In our case, we would do it like this:

1cy
2 .get('.green > .circle');

This selector will only select those .circle elements, where a .green element is one level above. Since in square #3, our .circle element is nested inside a .red element, it will not be selected.

There are tons of ways we can select elements, and .get() command works well with most of them. (I say most of them, since it is not possible to use pseudo selectors, such as :hover or :visited etc.) You can find a whole variety of selectors on W3 schools page. Mastering these will help you immensely with writing your tests and understanding DOM structure of your page.

Cypress commands for selecting elements

While mastering various CSS selectors is definitely useful, there are ton of ways you can select elements on page using Cypress commands. More importantly, these commands provide a better readability to for tests. In this example, we will be testing this lovely rainbow page:

Testing rainbow with Cypress commands

Select by text

To select our element its conaining textm we can use .contains() command. This is very simlar to a jQuery method with the same name. This command can be used in various ways:

1// select an element with the text "indigo"
2cy
3 .contains('indigo')
4
5// select an h1 element, that contains the text "Rainbow"
6cy
7 .contains('h1', 'Rainbow')

You can even chain your commands together and create what is in my opinion quite self-explanatory code. Following code will look for a li (list item) element inside our .list. It will find multiple elements and from these, we will find the one that has the text "purple" inside it.

1cy
2 .get('.list')
3 .find('li') // returns 7 li elements
4 .contains('violet') // returns a single element

Select by position in list

Inside our list, we can select elements based on their position in the list, using .first(), .last() or .eq() selector.

1cy
2 .get('li')
3 .first(); // select "red"
4
5cy
6 .get('li')
7 .last(); // select "violet"
8
9cy
10 .get('li')
11 .eq(2); // select "yellow"

You can also select an element relative to a selected element. For example, we can select a .blue element by using .next() command like this:

1cy
2 .get('.green')
3 .next(); // will select the element .blue

And of course, you can go the other way around:

1cy
2 .get('.green')
3 .prev(); // will select the element .yellow

Select elements by filtering

Once you select multiple elements (e.g. by .get('li') command, which returns 7 elements), you can filter within these based on another selector. Following code will only select the colors red, green and blue, since these are primary colors and have a class .primary on them.

1cy
2 .get('li')
3 .filter('.primary') // select all elements with the class .primary

To do the exact opposite, you can use .not() command. With this command you will select all the colors except red green and blue.

1cy
2 .get('li')
3 .not('.primary') // select all elements without the class .primary

Finding elements

You can specify your selector by first selecting an element you want to search within, and then look down the DOM structure to find a specific element you are looking for.

1cy
2 .get('.list')
3 .find('.violet') // finds an element with class .violet inside .list element

Instead of looking down the DOM structure and finding an element within another element, we can look up. In this example, we first select our list item, and then try to find an element with a .list class

1cy
2 .get('.violet')
3 .parent('.list') // finds an element with class .list that is above our .violet element

Going further

You can combine these commands any way you want to get to your element. However, you don’t want to overdo it. The cleanest way to select elements in Cypress is to make sure that your application actually contains the selectors you need. It is a good practice to add your own data-test attributes to those elements in your app, that you want to interact with. Moreover, if you then use theCypress Selector playground, you may find your selectors more easily. This is because Cypress favors these selectors over classes, ids or other attributes. But you can easily customize which selectors should the Selector Playground utility prefer.

If you are already using attributes to mark your elements, here’s a tip for you. You can create a custom command, that will select your element by e.g. data-cy attribute:

1Cypress.Commands.add('getById', (input) => {
2
3 cy
4 .get(`[data-cy=${input}]`)
5
6})

which you can later use in your test like this:

1cy
2 .getById('indigo')

Selecting your elements can definitely be a painful task when you are starting and don’t know what’s what. I hope this guide will help you navigate through your application DOM. If you are a PRO already, share the link with your friend. They might still be struggling 😅

Share article
Cypress test automation course
If you like my articles, you’re going to love my new course on Cypress.io. It’s called Cypress test automation for people in a hurry, and it is exactly what you’d expect. A compact, fast and straight-to-the-point course with lots of practical examples and challenges. Check it out!

More articles coming! Get them to your inbox ✉️



Filip Hric © 2020