This article is a part of series on Cypress basics. You can check out some other articles on my blog where I provide step by step explanations of some Cypress basics + some extra tips on how you can take things one step further. So far, I wrote about:
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.
In Cypress, you select elements using this syntax:
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:
To select elements, it is of course vital to see into the page. Markup of our page looks like this:
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.
To select an element by class you need to use .
prefix and to select an element by its id, 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!
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:
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):
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?
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:
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.
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:
To select our element its containing text we can use .contains()
command. This is very similar to a jQuery method with the same name. This command can be used in various ways:
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.
Inside our list, we can select elements based on their position in the list, using .first()
, .last()
or .eq()
selector.
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:
And of course, you can go the other way around:
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.
To do the exact opposite, you can use .not()
command. With this command you will select all the colors except red green and blue.
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.
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
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:
which you can later use in your test like this:
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 😅
From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.