Let's now take a look into what we can do with TypeScript inside our Cypress tests.
In this first test, I'm going to get this input field and start typing into it.
TypeScript compiler is immediately going to start complaining if I don't pass any arguments into my function.
As you can see in this error, TypeScript is telling me that the type function has expected 1-2 arguments, but instead got 0.
As the mini documentation over here suggests, we should be adding text that we want to type in, so in my command, I'm going to type some numbers 1234
.
This, again, also doesn't make my TypeScript compiler happy because I'm not passing the proper options.
The error says, "Argument of type 'number' is not assignable to parameter of type 'string'" - what that means is that I'm passing a number, but I should be passing a string.
If I change this, I will finally get rid of the errors.
This way, TypeScript can guide me into writing less errors in my code.
Another way of how TypeScript can be useful can be by auto-suggesting different command arguments.
For example, I want to make sure that my heading over here, "Get Started", is visible.
As I start typing my command, I'll get all of these different arguments as a suggestion.
If I choose be.visible
, I can run my test and make sure that the heading is actually visible, and the same goes for some other commands.
For example, let me find an element on the page, select it within my test, and then with the invoke
command, then I can call different jQuery functions on the element that I have selected.
For example, I want to make sure that I get the text
of my element.
As I save my test and look into invoke
in the console, I can see that my command has yielded the "Get started!" text.
There are many of these very useful jQuery functions - for example, hide
, which will hide the element on page, and many more.
TypeScript works really well with all of the commands that are in Cypress, because each and every one of them has its own TypeScript definitions.
Cypress can also work with custom commands that were added through a plugins, so I'm going to go ahead and install one of the very popular plugins called cypress-real-events
.
I'm going to do the usual stuff - add the plugin into the e2e.ts
file, and I'll create a "new board".
In my test, I want to do a hover action, so I'm going to select the item, and then I want to use the command that is inside this plugin that's called realHover
.
As you can see, TypeScript doesn't recognize this command.
If I save my test, it's still going to work.
We can see that our report item is actually in hover state - we can see it has darkened, and we see the star, which appears when we hover over.
So the command is functional, but it's not recognized by TypeScript.
To fix that, I'm going to go to tsconfig.json
, and inside the types
section, I'm going to add cypress-real-events
plugin, save the json file, and go back to my spec.
Now, all of the errors are fixed.
If I hover over my command, I can already not only see the definition, but also this little documentation that's written for this command.
Now let's say we want to do a little bit of data-driven testing.
I'm going to open my board in the following test, save it, and inside of this test, I want to add a couple of lists.
What I'm going to do is go to my fixtures
folder, create a new json called lists.json
, and in here, I'm going to create an array of objects and every object will be a separate list.
Every object will have a name and a value.
I'm going to call the first one "list 1" and then I will also have an order
for list order, and that will be 0
for the first one.
For the second one, the name
will be "list 2", and the order
will be 1
.
I'll save this, and what I'm going to do is that I'm going to import this json into my test.
I'll do import
and I want to import everything as lists
from ..fixtures/list.json
.
In my test, I want to select this input and then type
some text into it and then confirm that with a {enter}
key.
After I do that, I want to make sure that the list was actually created, so I'm going to create an intercept
, which will map the POST
request for an /api/lists
, and I'm going to call it "listCreate".
After I hit the enter key, I want to wait for that request, and then later, I'm just going to test something.
These two commands are going to be in a loop so I'll add lists.forEach()
so for each list, we're going to repeat a set of actions, and these two actions will basically be inside here.
Now, the really cool thing about TypeScript is that when I want to use an iteration from my json file - for example, add the name
parameter as a text into my type
command, I can just add a variable, start typing list
, and it will automatically invoke the attributes from my json.
So, list.name
is going to use the list name from my list json file.
In the first iteration, it's going to type "list 1", and in the second one, it's going to type "list 2".
When I now save my test, you can see that the test has iterated over the json file and has created "list 1" and "list 2".
If I reset my application and decide to add some more lists into my json file, I can again add a name
- let's call it "list 3", and add an order
, which will be number 2
.
When I save this and run my test, now it's going to create three lists.
As a final step, I want to make sure that these are created with the correct order.
What I'm going to do is to access the response.body.order
, which is part of this request.
If I take a look into the details of that request and take a look into the response body, I can see the order
with a certain value.
Using this test, I'm going to check that value and make an assertion that this order should
equal list.order
.
I'll save my test, reset my application, and run my test again.
Now I'm not only creating my lists through a loop, but I'm also checking whether the APIs that were called actually return the proper data.
There's another cool thing you can do with TypeScript, and that is related to this import path.
As the project gets bigger, sometimes it's hard to get that relative path to the file that you need to reference.
What we can do is to go to that tsconfig
file and define two options.
The first one will be baseUrl
- this URL actually represents the base of our project, so that will actually be the root of the project.
Then, the second one will be paths
. Here, I'm going to define @fixtures/*
, and I'm going to make it so that it will always reference cypress/fixtures/*
.
When I save this now and go to my spec, I can reference my json file like this - @fixtures/lists.json
.
Even if I move my spec file around or add it to some subfolder or something, it will always reference the correct file inside the fixtures
folder.
Let me reset my app, save my test to run it again, and as you can see, nothing has changed and my file is still working.