loading...
Cover image for How to test Vue apps with the popular Cypress framework

How to test Vue apps with the popular Cypress framework

napoleon039 profile image Nihar Raote Updated on ・6 min read

Introduction

This article explains how you can use Cypress to test a Vuejs app. A simple todo app created with Vuejs is used as an example.

This article does not go in-depth about testing with Cypress, the Cypress docs are a better source for that. Rather than simply explain about Cypress and how it works, a working (simple yet somewhat practical) app is used to show how Cypress can be used with Vuejs.

Cypress has a lot of features that can be amazing to use. But at the same time, it is also a double-edged sword. These same abundant features can sometimes make it confusing when looking for that perfect assertion to create a proper test, so I've explained some of my thought processes when I was looking for a proper condition to use in my tests.

The app will not be tested extensively. Only the basic functionality will be tested, enough to make sure the fundamental features work properly.

Setting up the application

Since the focus of this article is writing tests, we will not spend much time on creating the app itself. This is a simple todo app, so I've only given it the basic features - adding a task, crossing off a task, and deleting a task. There are also some additional features like not being able to add an empty task and not being able to add duplicate tasks. If you want you can refactor it to be able to handle duplicate tasks as well.

Todo app main code

This is the code for the todo app. It's very minimal and doesn't have much styling. But it works, and that's all we need to start writing our tests. So let's get to writing tests. We have to install Cypress first.

Installing and setting up Cypress

To install Cypress with npm:

Cypress install command

Now that we have installed Cypress as a dev dependency, we can start writing tests. If you are using Cypress for the first time, then follow these steps in the docs.

When starting up Cypress for the first time in a project, it will create a ton of tests for us to get us started. We don't really need those so it's okay to remove them.

After installing Cypress, a new folder by the same name will be created and it will also have some folders inside with the tests that I mentioned. Though it's fine to delete all those tests and folders, keep a folder named integration. This is because Cypress will look inside this folder for tests. I tried creating a test file outside this folder and it did not show up in the Cypress UI. I'm not sure whether I missed something or if there is a way around it. If someone knows about this, let me know in the comments below 🙂

As for the naming of the test files, although the Cypress docs seem to name all their example files as something_spec.js(meaning they all end with _spec.js), it is not necessary to do so. You can name it what you want as long as it is a JavaScript file. Make sure to use meaningful names though instead of random ones. If you have a naming system, then that's excellent!

Writing tests

The app is ready, Cypress is installed and set up. Now it's time to start writing our tests.

The first test we will write is checking whether a todo gets added. Looking at the app code, we can write our task in an input field, click a button and our task gets added to an unordered list. Thus we can create todos by writing in the input field and clicking a button.

I have previously used Jest for writing tests for my Vue apps and also wrote an article on it. While writing this test, I used the same mental process of writing a Jest test. In Jest, the Vue component is imported and then we mount it and so on. In Cypress, however, I couldn't find anything like that. Until I saw an example that used visit(). I immediately went to the console and started the app using npm run serve. This command is for Vue 3.x so if you use Vue 2.x that would be npm run start. Since I can visit the app on my browser using localhost, I used that address for cy.visit().

Cool! Cypress can visit the app page as if I was visiting it. So now what's left is selecting the input field, typing out a task, and clicking a button.

First test

it is a term used by most testing libraries for writing test cases. You can read my article where I explain about it a bit more.

Here, we visit the app via localhost, find the input field using cy.get() and start typing something inside. To type something, we simply chain cy.type() to cy.get(). Then we get the button in the same way and click it by chaining cy.click(). Now what's left is to check whether the todo is actually added to the list or not.

I first thought of getting the entire list, but then realized we're only checking whether the task we've created has been added. Since we are only checking for that one, I used cy.get() to find a list element that contains our task.

Seems quite easy now doesn't it! This is your first test with Cypress!!

Let's not stop here and continue on. Our second test will be checking whether clicking the task crosses it out.

Second test

We have already visited the app page and created a todo during our first test, so all we have to do this time is to click it and check whether it's crossed. To click it, we get it just like we did in the first test using cy.get(). Then we make sure to specify which task we're looking for by chaining cy.contains(). Next, we click it the same way we did with the button, by chaining cy.click().

Finally, to check whether it's crossed out, we get the specific task again and then assert that it has the class of completed.

If you look at our app code again, we have written some CSS that gives the element with a class of completed, a text-decoration of strike-through. You can be more thorough with this test and instead check whether the task actually has that CSS applied to it. This would make sure that the test would work even in situations where, for some reason, the class of completed is added but the CSS isn't applied. You can search for the appropriate assertion in the Cypress docs. It will serve as a good exercise in navigating the docs.

Now for the final test, we will check whether a task can be deleted by clicking a button.

Third test

The test this time is quite small. We get the button using cy.get() and chain click() to it. Finally, we get the specific task and assert that it doesn't contain the task contents. And with this, we have now written all our tests and ensure that the basic features of the app work.

Here are all the tests we wrote in one place:

All todo app tests

Conclusion

You might have noticed that we've only been interacting with HTML elements and haven't even touched any Vuejs in our tests, even though our entire app is written in Vue. That's because Cypress is made like that. Take Jest, for example, you would write tests differently for React apps as compared to Vue apps. In my opinion, I think Cypress, however, is made to be independent of any particular framework. It doesn't matter whether you use a component-based approach in your app, use a server, or make it serverless, Cypress is designed to test your app as it runs in your browser. It mimics the behavior a regular user would take if they were actually using your application. You don't have to import or mount any component.

With that said, we have finished writing all our tests. We created a minimal todo app and actually wrote tests for it using Cypress. Cypress provides some really cool tools and features for testing. You're missing out if you haven't tried it yet.

Discussion

pic
Editor guide
Collapse
bahmutov profile image
Gleb Bahmutov

Nihar, good article but I don't think the statement "Cypress makes sure this test will not run if the first test doesn't pass." is correct. Cypress will not run the test if a "before" or "beforeEach" hook fails, but it will happily run the second test even if the first test fails. We advise to make your tests independent from each other - if you need a couple of todos for the second test to complete - just create them using a beforeEach and a custom command.

See our example tests for TodoMVC here github.com/cypress-io/cypress-exam... and in-depth TodoMVC tests for Vue.js specifically here cypress.io/blog/2017/11/28/testing...

Collapse
napoleon039 profile image
Nihar Raote Author

Thank you for correcting me. I started with Cypress recently so I didn't know it was like this. I think I saw an example with a test failing and subsequent tests not running in some specific situation and thought that meant a test failing means the tests following it will fail as well.

I will make sure to check out the GitHub example you linked to 🙂

Collapse
mirelspr profile image
Mirel Springer

"Here, we visit the app via localhost, find the input field using cy.get() and start typing something inside. To type something, we simply chain cy.click() to cy.get(). Then we get the button in the same way and click it by chaining cy.click(). Now what's left is to check whether the todo is actually added to the list or not."

Shouldn't this be "we simply chain cy.type()" ?

Collapse
napoleon039 profile image
Nihar Raote Author

Thank you for pointing it out. I should edit my posts more carefully.