In this test that we have been working with, we have a couple of assertions.
So, what we are doing here is that we are checking the text of our first task. And then we are checking the text of our second task.
We do that by selecting each task individually, and then make an assertion using the should
command.
There's another way we can approach this and I'm going to show it to you right now.
The first thing I'll do, I'll delete this piece of code. And when I save my test, you can see that our get
command, is actually matching 2 elements.
These 2 will be passed on to the next command.
For that, I'm going to use the then
command. And as an argument, I'm going to pass a function. If we want to see what's passed in this function, we can just console.log
it.
When I now save my test and look into the console, you'll see that we are getting properties of each of our elements.
We can test these properties inside our then
function.
Instead of console.log
, we can write an expect
function.
Since we have 2 elements, we are going to be selecting them by their index number. So, the first item will be, item 0. And the second one will be, item 1.
And to write our assertion, we're going to write it like this, to.contain.text
, the first one will be “bread” and the second one, we want to assert that the text is “milk”.
cy
.get('[data-cy=task]')
.then( item => {
expect(item[0]).to.contain.text('bread')
expect(item[1]).to.contain.text('milk')
})
When I now save this, you can see that we are essentially doing the same thing as we did in the beginning.
But instead of selecting each item individually, we are just using one get
command, and then we pass it on to the then
function and use the expect
function to make assertions about these elements.
There's one important thing you need to remember about this.
The then
function doesn't contain retry logic. That means that whatever the get
function will return, the then
command, is just going to use it.
Let me demonstrate.
If I reorder these elements and run my test again, you'll see that the test has failed really, really fast.
So, we don't have our 4-second period to retry.
To give ourselves the ability to retry these assertions, we can simply change this then
command to a should
command.
cy
.get('[data-cy=task]')
.should( item => {
expect(item[0]).to.contain.text('bread')
expect(item[1]).to.contain.text('milk')
})
That way, when I save my test and reorder my items during the test, my test will pass. And as you could see, the assertions were retried until the tasks were in the correct order.
The nice thing about passing elements to a function is that inside this function, we can write our own logic.
Let's say we don't want to test this unless the number of elements in our list is 3.
So, inside this function, I'm going to write a condition so that if the item length is not equal to 3, then we are going to throw an error (throw new Error
). That is going to say, “Not enough elements!”.
beforeEach(() => {
cy
.visit('/board/2305140181')
})
it('Multiple assertions', () => {
cy
.get('[data-cy=task]')
.should( item => {
if (item.length !== 3) {
throw new Error('Not enough elements!')
}
expect(item[0]).to.contain.text('bread')
expect(item[1]).to.contain.text('milk')
})
})
When I save this, you can see that my get
command is retrying. And then finally it will throw an error, “Not enough elements!”.
If we add an element, for example, “cheese”, and run our test again, our test is passing.
To recap, we can use the then
command to write multiple assertions at once.
The important thing to remember is that the then
command is not retried.
If we want to retry our assertions, we have to use the should
command.
And finally, passing elements to a function, enables us to write our custom logic, so we can write an error message or some other kind of condition that we want to use.