UX Testing with Cypress + Storybook

Lisa Law
Coverwallet Engineering
7 min readMar 25, 2022

A practical example for beginners

One of our goals in CoverWallet is to constantly improve the testing experience of our code. Amongst other things, we test in order to prevent errors, to increase code quality, and to be cost-effective by reducing bugs and time spent fixing them.

There are many great testing tools out there, and I’ve just had my first experience with Cypress. Cypress is one of the tools we’re embracing more and more at Coverwallet (see here).

There are many reasons I like Cypress. The most important one for me at the moment is that cypress, in conjunction with storybook, lets you test UX components in a super friendly, visual way.

If you’ve never worked with cypress before — you’re missing out! I honestly think it can revolutionize the way you test your UX. Note — a basic understanding of how tests work will help you with this. :)

Index:

  1. Setting up the code
  2. Setting up the test
  3. Testing
  4. Running cypress

TLDR:
Cypress testing of a simple toggle component in storybook via `cy.visit()` , `cy.beforeEach()`, `cy.get()` and `children()`.

Setting up the code

The react component

Let’s imagine we are creating a new toggle element and we want to test the code above. (I’m using styled components here, in case this confuses you, feel free to replace all of the components with `div` tags in your head.)

The data-test attribute

I’ve added a `data-test` attribute to the `Wrapper` element so cypress can find the component later in our test file. You could find your components via id or className but @ Coverwallet we prefer to keep our tests decoupled from styling to prevent errors. We’ll name it `my-toggle` for the scope of this blog, but you could also make it dynamic by using template literals. For example, we could add the value of `on` to our string like so:

But for today, we’ll stick with a static data attribute.

Styling

I’ve added the following styles via styled components: height, width, color, border, background properties. We will test our toggle on some of these further down.

The storybook

Cypress will access a storybook file — so let’s do this now.

Nice and simple, we have our story.

The toggle will look like this in the storybook when we open the browser:

Toggle on
Toggle off

You can change between these two states by clicking on the toggle.

Great! We’re ready to go.

Setting up the tests

The test file

Let’s create a test file like such: `cypress/integration/toggle.spec.js`.

Creating constants

The first thing we’ll do here is to create some constants. Why? These provide readability and reusability for our tests and reduce chances for errors.

For now, we’ll stick with these:

The TOGGLE constant refers back to the `data-test` attribute we set before. Note that this finds all elements with the given attribute! This means that if you have more than one toggle in your project, the tests will run for all of them. This is likely to happen with buttons, for example.

The COLOR selectors will help with readability later on. Note that if we’re testing CSS, cypress expects colors to come in rgb values. Sadly, this has not yet been fixed by cypress, but a nice workaround can be found in this answer, if your project uses other color configurations.

Testing

Cypress Setup

We wrap each set of tests in a context.

beforeEach()

beforeEach() runs, as with other testing suits before starting the tests of this context. It is optional and you could instead include its content, in our case cy.visit(), in each test instead.

cy.visit()

This function takes a string as input, composed of two parts. The first one, `/iframe.html?id=` creates a video of the tests when you run them later, shown via iframe in the cypress testing frame. This is a really neat feature that lets you see exactly what your tests are doing at any given moment.

The second part of the string is the story id which we get from our storybook file. The first part (`toggle`) reflects the title. The second part, linked by two dashes, reflects the actual story name.

Let’s test!

Our first test starts with the function `it` (as will all others). It expects a name or a description of what we expect of the test — here I went for ‘exists’. This name should be as descriptive and close to the actual test as possible while still being legible.

cy.get()

This function yields all the DOM elements it’s found with data-test `my-toggle`.

.should()

Should defines the assertion, the actual test. What should our test do or have? What do we actually want to test?

For this example, we’ll check if our toggle exists first — this is good practice and it will cause cypress to stop and throw an error if it can’t find any element with this data-test.

Testing CSS properties

Cypress makes it incredibly easy to check for any styling. Above I’ve included a test for height and width, but we could keep going — any CSS property can be checked the same way.

As you can see, we’re using `get` and `should` just like in the first test. Since we’re testing the same component here, we can also unite the two lines, linking them via `and`:

Testing children

Maybe you’ve noticed that we’ve put the data-test attribute on the outer `Wrapper` tag. What to do now if we want to check that the children get rendered correctly as well?

First we could use `.children()`. This works well if you want to check something that holds true for all children.

If you want to check the properties for a specific child, we can access one child after the other by using `.eq(i)` (read “equal to i”) with a growing index for each child. For the first, we could also access via `.children().first()` .

In the case of our toggle Wrapper, we only have one child: StyledToggle. So we would have to go for `children().first()` or `children().eq(0)`. I prefer the second one as in my opinion it looks neater when we have more children.

Nice work! Let’s run them and see what happens.

Running cypress

To run the test, you need to be connected to your localhost (e.g. via `npm run dev`: connecting to your local storybook in the usual way).

The running `cypress open` will open a new window in the browser in which you can see all of your test files. Choose the one that you want to run.

Next, yet another window opens and we can see the test running. Aaaand… success!

On the right, you can follow step by step what the test inspector does and get snapshots. A really neat feature!

If you’ve made it until here, well done — give yourself a clap on the back.

There’s one more thing we want to test, though — our onclick behavior. If you look back to our component, you can see that we change the toggleState on clicking on the wrapping. The color should go from green to red.

Here is the test:

Let’s have a look at what’s happening here.

First, we assert that the children of the toggle (the StyledToggle) should have a green background.

Next, we simulate clicking on the toggle via the `click()` function.

Finally, we make another assertion: the background should now be red.

That’s it! Congratulations on running a successful test suite.

Below you can find the complete cypress test file for reference (`toggle.spec.js`):

There are obviously more tests we would have to write for this toggle. Maybe it would also make sense to add more data-test attributes to each child instead of accessing all through the `.children()` properties.

But hopefully, this was a good introduction to how straightforward cypress is and how easy it is to use.

Happy testing!

Curious about cypress? Check out their docu: https://docs.cypress.io/guides/overview/why-cypress#In-a-nutshell

--

--

Lisa Law
Coverwallet Engineering

programmer, world traveler, linguist. Karate 2nd kyu, beginner Muay Thai fighter, bouldering enthusiast.