Let's now take a look into how to select elements on a page using Cypress.
There's this really nice tool called selector playground which can help us find the selector that we need.
This works really well if we have unique selectors on our page.
Whenever I click on an element, I will get a full view of the command that I have to use.
I can just copy that and paste it into my code.
As soon as I save my test and hover over the timeline, I can see that I'm selecting the correct element.
But let's back up a little.
Most of the time, we need to find our selectors manually.
In order to do that, we can choose different strategies.
The easiest one is going by the thing that the user can actually see.
So if I type cy.contains()
, I can select an element using the text it contains.
For example, if I want to select this new board element, I'm just going to type cy.contains('new board')
.
it('my first test', () => {
cy.visit('/')
cy.contains('new board')
})
As soon as I save my test, I see that we are selecting the new board.
If we inspect our element in the browser, we can see that this div element has different properties.
We have the class
of board
, id
of board-1
, and then also the data-cy
attribute board-item
.
In Cypress, we can choose any of these attributes by using the cy.get()
command.
If I want to select an element using the class
- for example, the board - I'll just type board
and prefix that with a dot.
it('my first test', () => {
cy.visit('/')
cy.contains('new board')
cy.get('.board')
})
If I want to use the id
, I'll go cy.get(#board-1)
.
Finally, if I want to use any of the html attributes - for example, the data-cy
attribute that I have over there - I'll go `[data-cy=board-item]' and put it all in square brackets.
it('my first test', () => {
cy.visit('/')
cy.contains('new board')
cy.get('.board')
cy.get('#board-1')
cy.get('[data-cy=board-item]')
})
I'll save my test now, and when I hover over my get
commands in the timeline, I can see that they are all selecting the same element.
They're just using different types of selectors.
All these options can help us be flexible.
Now you might have noticed that when I hover over this contains
command, it's just selecting a portion of the board item element.
When we'll take a look at this element using the Inspect tool, we'll see that the div
element actually has the h2
element inside it and that one holds our text.
So in fact, our contains
command is not selecting the whole blue tile that we have over here, but it's just selecting the h2
element within it.
But it doesn't mean we cannot select the parent element using our text because the contains
command can actually take two arguments, and in that case, the first argument would act exactly as our get
command.
it('my first test', () => {
cy.visit('/')
cy.contains('.board', 'new board')
cy.get('.board')
cy.get('#board-1')
cy.get('[data-cy=board-item]')
})
If I say select an element that has the class of 'board' and contains the text 'new board', as soon as I save my test and then hover over my get
command, you can now see that we are selecting the whole element.
A question I get often related to Cypress is whether we can use some other means of selecting.
You might notice querying language from CSS, and that's exactly what Cypress is using.
But can Cypress use xpaths?
Well it can if you install an additional plugin.
While installing a plugin is not a big deal, I generally don't recommend going for xpaths because you can use Cypress commands for everything xpaths can do, and even more.
Let me show you what I mean.
I'm going to create another board - let's just call it "hello board" and go back to my home page where I now have two.
If I now decide to use this selector, you'll notice that we are selecting both of our elements but we don't want to interact with both of them - just a single one.
So we can narrow down our search by chaining off another command to our get command.
For example, we'll go with first()
to select the first element.
it('my first test', () => {
cy.visit('/')
cy.get('[data-cy=board-item]')
.first()
})
So now we have two - when I hover over, you can see that now we have only selected the first one.
There's also a last()
command which is going to select the last element of those two that were selected in the previous command, or we can use eq()
and then pass a number.
This is going to select whichever element we want, numbering from number zero.
So eq(0)
will select the first element, eq(1)
will select the second element and so on.
These are only a couple of options that we have here.
In Cypress, we have commands like next
, previous
, parent
, children
, find
and many more.
These allow us to traverse across the DOM in any direction we need.
It's very similar to the capabilities of xpath, but it's much more readable.
You can easily figure out what the commands are actually doing.
To find all of the commands, you can go to docs.cypress io.
In the documentation, under the "Queries" tab, you will find all of the querying commands.
These will help you target the right element, no matter where it is on page.