Hints for Adding Data-cy Attributes for Cypress Testing
Cypress has quickly become my favorite tool for end-to-end testing. I continue to be amazed at the ease and accuracy Cypress provides.
The Cypress documentation is terrific, and for any questions you might have about using Cypress, the docs are the best place to start!
In this post, I will share some tricks I have learned for selecting elements to test.
In the Cypress Best Practices section, Cypress provides a guide for selecting elements. In my experience, if at all possible, add a data-cy
or data attribute to an element as it helps prevent flaky tests.
There are some cases (lists, buttons, or other elements that are rendered multiple times on a page) where adding a data attribute can be interesting. Here are a few helpful hints for adding data attributes.
Example One: adding a data attribute to a React DayPicker
I wanted to add a data attribute to an imported package, React DayPicker.
I have two DayPickers
on the same page so I definitely need to specify which one I am targeting. This is what the selector playground provided for DayPicker
number one:
cy.get(‘[style=”margin-right: 5px; font-weight: normal;”] > input’)
And for DayPicker
number two:
cy.get(‘[style=”margin-right: 10px; font-weight: normal;”] > input’)
If I return to the component, I see that the selector playground is honing in on the style, and then the input field after that:
<DayPickerInputContainer
style={{ marginRight: 10, fontWeight: “normal” }}
That is not what I want to target. In such an instance, things get interesting. The selector playground won’t automatically give me the data attribute I want, so I have to prompt it a bit.
Reading through the documentation for React DayPicker
, I understand that one place I can add a data attribute is in the inputProps
field:
inputProps={{
disabled: false,
data: “CollaboratePlanner-daypicker-start”,
}}
I add the same data attribute for the ending DayPicker
inputProps={{
disabled: false,
data: “CollaboratePlanner-daypicker-end”,
}}
The selector playground still recommended the selector based on the style attributes, so I manually enter the attribute I am looking for (and know exists because I can see it when I select the item in my browser console).
The “1” that appears in the selector navbar lets you know there is exactly one matching element. Perfect! I grab that element by clicking the “Copy to clipboard” icon in the selector playground navbar, and I am on my way!
Example Two: dynamic data attributes
I use dynamically generated data attributes for any instance where the element will appear multiple times on the screen. Here is one example where I want to target the icons in a list of elements:
This list shows that simply putting a data-cy
attribute on the element won’t work because it will result in several elements with the same data-cy
attribute 😢. Such a case is a perfect chance to use dynamic data attributes! Here is an example:
<td data-cy={`List-${club.name}`}>
That dynamically generates the data-cy
attribute with the club name passed into the cell. Perfect!
I can do the same for each element. For example, the edit and delete buttons also need to have dynamic data-cy
attributes, so I add those attributes on the button elements:
data-cy={`List-edit-${club.name}`}
and for delete:
data-cy={`List-delete-${club.name}`}
Now I have dynamic data attributes generated, and my tests are much more robust!
Example Three: data attributes and Material UI components
My best recommendation is to REFER TO THE DOCUMENTATION when working with Material UI components or any other component library. The documentation is where you will find all of the information needed to add data attributes. You can most of the time add a data-cy
attribute just like adding an id, but sometimes you might need to add it in inputProps
or somewhere else (it differs based on the component so read the docs and then play around with the data attributes to see what works).
I had some issues determining how to add a data-cy
attribute to my Autocomplete
and TextField
Material UI components. In this instance, I realized (yet again) that the selector playground can be fickle and may need some prompting.
For example, I added a data-cy
attribute to the Autocomplete
component, but when I used the selector playground it prompted me to use the id:
Using the id, in this case, would be just fine. However, if you want to go with the data-cy
attribute, you will have to prompt a bit. When I typed in the following in the input field for the selector playground, I was pleased to see the “1” element appear:
(😃)
As a side note, you don’t have to add double quotation marks for the name after the equal sign if there are no spaces, but you DO need double quotation marks if there are spaces in the data-cy
attribute name. For example, data-cy=” microschoolname dropdown listbox”
would need double quotation marks.
Conclusion
Cypress continues to be an absolute joy to use in my testing journey. To write tests that are less prone to flaking, invest the time in adding data attributes! You will be much happier in the long run ✨.