Testing front-end applications with Cypress

Leonardo Tironi Fassini
TaqtileBR
Published in
6 min readDec 1, 2020

In this article I’ll be showing how I tested a front-end application with Cypress, together with some explanations of the most common usages and tools. Since the application is just to apply the techniques that I learned, the codebase is quite simple and it can be found here.

In another article, I explained how to install Cucumber together with Cypress to create user stories and implement each step. Although the focus is installing Cucumber, I also showed how to install Cypress (which is actually one command line).

Photo by Scott Graham on Unsplash

First steps

After installing cypress, there will be a new folder onto your project called cypress.

Inside, you’ll find 4 other folders. They’re:

  • Fixtures: Basically a file of datas for you to work. Usually used to mock responses data, but can also be used as consts folder.
  • Integration: Here is where your code test is written.
  • Plugins: The name already says everything, right?
  • Support: It’s the right place to put commands you might need when running your tests. It runs before each test. This means that here you can also put the code to run every time a test starts. Ex:

You can also use hooks to run things before a test block (describe) or before each test inside that test block (before each it).

But what is ‘it’ and ‘describe’?

Some cypress features (as should, expect, it and describe) are the same as the ones used in Mocha and Chai. Actually, they’re just imported and used by Cypress. In this way, Cypress support most of those features.

Before creating the tests, you need to specify about what feature this test is about. In Cypress we say that the feature is specified by describe. As an example, suppose that we have the following login page:

Here we have what it produces:

If we want to test this page, then we should describe the test as the login page.

The it specifies what behavior of the feature we are testing. In the above example, we are testing if our website can handle a correct login. Also, we could verify his behavior with wrong username and/or wrong password, too.

Cypress commands

below, you will see a list of the most common commands that is used on cypress. The language is somewhat like Typescript, which is <command>(<input>: <type>) .

Visit

First of all, to test a page you need to be in that page, right? To do it, cy.visit(url: string) is what you need. Ex:

Get

After visiting the website, it is needed to get the element, either to verify it’s value or to simulate a click. For this, you use cy.get(DOMElement: string) . You can give to the input a class, a type, basically anything that can be got with Jquery. Ex:

In the emaples I’ll be showing, I’m using React to code them. That said, I’m using the HTML properties to find the elements. So, usually you’ll see something like cy.get('[data-test=someValue]') .

If you look at the DOM, you’ll see that almost all key elements will have a property called data-test. That’s the tag I’ll be using to get them with Cypress. This helps maintaining a pattern for testing.

After a cy.get you can chain more commands.

  • Click: After you cy.get() an element, if you need to simulate a click on it, use the chainable .click() command. The example is the same as above.
  • Then: the .then($element: DOMElement | value: number) chainable command allows you to use the element or value you got. If you use .then right after a get, the element will be a jquery element. If you use the .then after an .its(value: JQueryCall) (which can be something like .its('length') ), the .then value will be the result of the call. In this case, a number.
  • Should: Test if a condition is true. Cypress support Chai commands. This way, you can use any of it to make the assertions. Ex:

Expect

This can be used as an alternative to use get() with the chainable .should(). Cypress assert the existence of the element by default using the cy.get(), and according to that statement, .should() should be used only to verify values from elements gotten with cy.get(). To maintain a pattern, it’s preferable to use cy.get() and .should() to make the assertions instead of expect.

Route

Route is used to simulate a request, it may it be a GET, POST, a Graphql request… You just need to pass the request type, the url that you’re requesting to and the answer. The last one can be either a fixture or anything you may need.

In the example below, I’m using .route() to mock a GET for the url todos/list expecting a json.

Fixtures

I could just create an constant with the response. But then, it would be mixed with the tests, which is not a good thing. So, Cypress create a folder for you called fixtures. This folder is used to store all the mocked data you may need. Then, when using a route, you just need to say to Cypress ‘Hey, get me the specified fixture for this request, please’ and he will automatically look for it on the fixture folder.

Good Practices

Avoid as much as possible HTML tags or styling classes.

They are too generic, or coupled with the style, so it won’t get exactly the element you want and, what is worse, if you change the style, you may delete the selector on your test.

When trying to get an element in cypress, there’s a lot of possible methods. Yet, the best way to get it is by passing down some property to the HTML element, as used above.

You can also use the text on the element, but only when you can’t differ one property for another. As an example, you can have a lot of options, but with different contents, and the content is dynamic, so you can’t put a specific value on the option data-test property. Use the string of the option, then.

Test one thing at a time

Another thing to remember (and I may not have followed it when I started) is to always test things one at a time and assert that it exists before using it. Don’t try to test login by doing everything on a go.

Experiences

Testing feedbacks

Given the following task:

Your system have a way to give feedbacks to every client the employee meet with. You shall test all possible feedbacks that can be given to the client.

I started mounting some tests. I’ve tried to iterate through feedback variables and test, but there’s too many nuances to account, so the test can’t be done in an iterative way.

The problem is: In the first step, you have around 8 options to choose. In the second step of a option you have another 8 to 10 options in the worst case. Summing up all of the possible combinations, that’s something like 24 possible paths you can take. That means 24 tests. Just for one little feature. So, you need to remember that maybe, just maybe, testing some feature may not be worth your time. Always remember this.

It was done in a hard coded way. But then, a light came out and I heard of Cucumber. It was said that you can give an option to a test, and make it try with it. I’ll figure out how to do it in the following work.

That’s all folks!

So far, this is my experiences and learnings using Cypress. It’s been a good roller coaster, whenever I thought there was something I needed to test, Cypress could handle it. Also, as my experiences grow, I’ll keep updating this article on create new ones, so stay tuned for more and thanks!

Future research

Cypress + Cucumber.

Test Cookies and local/session storage.

Remove the data-test from the code before going to production. Can use this to do it, maybe?

References

A talk about testing in Cypress by his creator.

https://www.cypress.io/

--

--