Let's switch gears for a bit and talk about Chai.js.
Chai.js is an assertion library that is really popular for JavaScript frameworks.
It can be used in almost any JavaScript framework really. I have used it a lot in my WebdriverIO automation.
It is really simple to install using npm install chai
, and it contains a lot of valuable assertions that you can use.
It has 3 different interfaces that you can use — you can say should
, you can say expect
, or you can say assert
.
Should
and expect
are really similar, as they provide a chain type of assertion, while assert
is a bit different.
You can visit each individual assertion guide and it breaks down and tells you further about the different things that you can use.
If it is you're using should
, you can do should.not.toBe
, for example.
Same thing with expect
.
And then assert
is similar to how WebdriverIO was doing it's expect
command.
You can read through the guides to get a better understanding of the different commands that's out there and how you can use them.
This is one of the things that I think the WebdriverIO expect
assertion wins — it's just straightforward and simple.
There's one way to do things. And the documentation is so much better in my opinion. It allows me to see examples of how I can use each and every single command that is there.
With Chai, a lot of times I stuck to using the assert
because it was more straightforward for me to use because I didn't have to do the chain. I didn't know all of the chain commands.
With WebdriverIO expect
, you don't need to know all of that.
It just provides you with the command, a very extensive list of commands that you can use, and when you click on those commands, it gives you examples.
It tells you what it's for, how you can use it, different ways that you can use these commands. And it's just really straightforward.
We're going to now add Chai to our project that we already have by saying, npm i chai
. This is going to install the Chai package along with the 3 different interfaces that we just talked about.
If I go into my package.json
, I'll see that I can also then install npm i chai-webdriverio
. This is a module that helps to combine WebdriverIO and Chai in our WebdriverIO config file (wdio.conf.js).
We're going to put in our beforeTest
the requirements for Chai so that we can use the global assert
and global expect
command.
So, we are going to require
Chai as follows:
beforeTest: function () {
const chai = require('chai')
const chaiWebdriver = require('chai-webdriverio').default
chai.use(chaiWebdriver(browser))
global.assert = chai.assert
global.expect = chai.expect
chai.Should()
},
Whenever we use the keyword assert
globally or expect
, they're now going to be calling the chai.assert
and chai.expect
, respectively.
In the test that we had before it was using WebdriverIO expect
assertion, so I'm going to comment that out for now, and I'm going to put that same thing down below.
I'm going to convert all of those WebdriverIO assertions into Chai assertions.
So instead of saying, expect
SecurePage toBeExisting
, I would need to say assert.equal
and pass in what I'm asserting it to equal to, which in this case is “true”.
And I would need to do the isExisting
command on the locator. The isExisting
command is a WebdriverIO command that just returns true or false based on if the element is present in the DOM.
Now, [toBeExisting](https://webdriver.io/docs/api/expect-webdriverio/#tobeexisting)
for WebdriverIO, this was pretty simple as it was already calling the toExist
command for you.
So, I didn't need to call that on the command because it just calls isExisting
on its own. But when I'm using Chai, I need to call isExisting
for myself.
So, I need to say element locator isExisting
and it's going to return “true” or “false” to me.
With WebdriverIO expect
, I don't need to do any of that. It will just automatically check for me and call the isExisting
function.
So that's a slight difference between both.
With Chai, you have to do the calls to return whether or not it's true or false.
You need to do the isExisting
, isDisplayed
, et cetera, based on what assertions you're using. With WebdriverIO expect
you don't need to do any of that. It's going to call it for you.
In my test here, I'm going to say assert.equal
. And that is me using the assert
method, passing “true”. And then I call isExisting
on the locator.
I can also do something similar for the next function.
Instead of saying toHaveTextContaining
, I would have to get the text and then, verify that the text is included in what I got back.
So for Chai, I would have to say assert.include
, which is something that checks for text to be included or contained.
And I would say getText
.
So instead of saying toHaveTextContaining
, because toHaveTextContaining
would automatically check the text for me, I have to do it for myself.
And I would have to do that against the value that I am expecting to be returned.
So, for WebdriverIO could use toHaveText
or toHaveTextContaining
.
For the third command here, where we were checking if the URL is equal to what we assumed, we can do that in Chai by doing a getUrl
.
A getUrl
is going to return the URL for the page that you're on. And we're going to have to say assert.equal
, the URL we're expecting.
And then we're going to have to do the WebdriverIO command browser.getUrl()
.
This is going to get the URL and compare it to the value that is on the left.
it('should login with valid credentials', () => {
LoginPage.open();
LoginPage.login('tomsmith', 'SuperSecretPassword!');
assert.equal(true,SecurePage.flashAlert.isExisting());
assert.include(SecurePage.flashAlert.getText(),
'You logged into a secure area!');
assert.equal('http://the-internet.herokuapp.com/secure',brower.getURL());
});
And if we run our test, it passes.
This is just another way of writing assertions using Chai.
You could have used the expect
Chai assertion, or the should
expect assertion, as I am putting here.
This is using the should
, but it's a chain command.
And I personally prefer to use the assert
if I'm doing Chai.
What I like about WebdriverIO, as I said before, it's more intuitive and I don't have to do all of those commands to getText
on my own, getUrl
my own, et cetera.
I can just use a command and it will do that for me.
So, on the screen right now, you should be seeing assertions using the should
.
And theexpect
assertion is similar to the should. So, you can format that to be similar.
If it is that you want to use WebdriverIO expect
along with Chai in your project, say that you were using Chai in your project all along, and you want to now start using WebdriverIO expect
assertion and you want to do it slowly.
You just need to require('expect-webdriverio')
and create the global.expect
in the config file.
You need to do this at the very start because WebdriverIO is going to come with the global expect
being for the WebdriverIO expect
package.
We're going to store that into a new variable called “wdioExpect.”
beforeTest: function () {
require('expect-webdriverio');
global.wdioExpect = global.expect;
const chai = require('chai')
const chaiWebdriver = require('chai-webdriverio').default
chai.use(chaiWebdriver(browser))
global.assert = chai.assert
global.expect = chai.expect
chai.Should()
},
So, wherever we want to use WebdriverIO expect
we have to use that command.
And so, the text that we commented out before, we can just go in and change that out to wdioExpect
and our tests should all now pass because we're using both WebdriverIO expect
and we're using the different Chai assertions as well.
This is our final test.
We can see where we are using both Chai and WebdriverIO assertions.
For the WebdriverIO assertions, it's more straightforward.
toHaveUrl
, toHaveUrlContaining
, toHaveTitle
.assert
, we have to make a call to say getText
or getUrl
in order to do the assertion on it.So, we can use Chai assert
, Chai expect
or Chai should
.
I personally now prefer using WebdriverIO expect
assertion.
I love the documentation and I love the way I can just make my calls and they are pretty straight forward. And the naming convention of them tells you exactly what it's about.