Hover in Cypress

January 11th, 2021
4 min read

If you looked at Cypress documentation and looked for .hover() command, you might get a little disappointed. There is no such command. Even worse, .hover() is the oldest issue on Cypress’ GitHub page that is still open. So no hover in Cypress? Well, this would be a short post if there wasn’t a solution 😃.

I will be using my Trello clone app, so make sure you clone it on GitHub if you want to follow along. Let’s take a look onto our board list and see what happens when we hover over a board.

Our board card gets darker and a star icon appears on top right corner. Upon further examination, you can see that these two changes are triggered differently. Looking at DevTools, you can see that the color change is handled by CSS, but our icon is not displayed when we force hover state via DevTools:

trigger hover state via devtools

Instead, there is an event listener that will change the visibility of our star icon.

User of course does not see this. The functionality here enables user to bookmark a board, so that’s what we need to focus on in our test. Let’s now try to write a test, in which we attempt to mimic this user behavior.

Copy to clipboard
undefined

This will of course throw an error, because the element we want to click on is not visible. Cypress has some great explanatory error messages, with some recommendations on how to solve the problem.

Cypress error message on invisible element

As a quick fix, we can apply .click({force: true}) to skip checks that Cypress does for us before we click on an element. There’s a really good article on what this means in Cypress docs. Of course, there are many reasons you might not want to skip these checks.

If we want to avoid this, we can use .invoke() command. This enables us to display a hidden element, same way you would using jQuery .show() function. In fact, .invoke() command enables you to use many of jQuery functions. The code will look something like this:

Copy to clipboard
undefined

This way, we don’t need to force our click, because our icon will be visible.

You may argue, that we are manipulating our application to a state that user does not really get into. And you would be right. Our icon is not displayed by user invoking a function on the icon element, but by hovering over our board item. As described above, there are event listeners bound to our item, called mouseover and mouseout. Instead of forcing our icon to show, we can trigger these events onto our board item.

With using a .trigger() command, our code will look something like this:

Copy to clipboard
undefined

This comes closer to our real-world scenario, as our icon is shown when a mouseover event is fired. Note that this event is not the same thing as CSS :hover state. When you run this test, you can see that the board item does not change color. Since this is change is handled by CSS, there is no real way we can trigger this change using JavaScript.

Luckily, there is a way to trigger a real hover state by accessing Chrome DevTools protocol. To make things easier, awesome Dmitriy Kovalenko has created a Cypress plugin that handles accessing this protocol. Installation of this plugin is pretty standard and readme file should get you through it. This plugin will add 4 new commands:

Copy to clipboard
undefined

Using the .realHover() command enables us to properly hover over our board item. Our test will look something like this:

Copy to clipboard
undefined

In our test, we can now actually check the changed color of our board item. That’s pretty cool. Note that this plugin only works in Chrome-based browsers, so you may need to skip this test while running in Firefox.

If you enjoyed this article, consider sharing it with your friends on your favorite social network. More great content is coming, so you may want to subscribe my to newsletter or follow me on YouTube and Twitter.

Let’s keep in touch

From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.

is required.

I treat your email address like I would my own. That means no ads. Just notifications of when I do cool stuff. Unsubscribe anytime. Click here to read about how I handle your data