April 16, 2024

Using data-testid in React Cypress tests

In React applications, using data-testid with Cypress makes it easy to select elements for testing. This approach is ideal when UI components change frequently but need consistent functionality. By using a unique data-testid for each element, tests are simpler to maintain and more stable, as these identifiers allow straightforward access to components, regardless of visual changes.

Why data-testid?

Since they look the same, why should would we use data-testid over id?

// Using data-testid
function LoginButton() {
  return <button data-testid="login-button">Log In</button>;

// Using id
function LoginButton() {
  return <button id="login-button">Log In</button>;
  • data-testid indicates its use for testing, which helps it stand out from other attributes like id or class that might be used for styling or scripting.
  • Since data-testid is solely for testing, your tests remain unaffected by changes to styles or scripts that use id or class for other purposes.
  • data-testid can be safely removed in production. This keeps the production code clean and optimized, while also preventing easy scraping.

A large benefit is also the improved readability. With data-testid, you can use descriptive names that reflect the element's role. Additionally, this can be added to more elements since it doesn't affect the styles.


For a comparison of different selectors, the Cypress documentation provides a table which can be found here. But in summary, data-testid offers the best benefit, allowing full isolation from testing and production.


Let's take a look at a practical example.

Suppose we had this test that relies on id selectors:

it("Should reset password", () => {
  // this will send an email with a reset link to the provided email address

  cy.mailiskSearchInbox(Cypress.env("MAILISK_NAMESPACE"), {
    to_addr_prefix: testEmailAddress,
    subject_includes: "reset",
    timeout: 1000 * 60,
  }).then((response) => {
    const emails = response.data;
    const email = emails[0];
    resetLink = email.text.match(/.*\[(http:\/\/localhost:3000\/.*)\].*/)[1];

If we change the component a bit and add our data-testid attribute:

return (
  <div className="flex justify-center mt-9">
    <div className="bg-gray-100 rounded-md">
      <form data-testid="password-form" ...>
        <p>We'll send a password reset link</p>

We can then use these data-testid attributes directly instead:

it("Should reset password", () => {

Removing data-testid from production

This is dependent on your project tooling and frameworks. There's a plugin for every popular tool that allows the removal of custom attributes (data-testid is an attribute, after all).

For example, let's say you're using Babel and JSX components (React). In that case, something like the babel-plugin-jsx-remove-data-test-id library will fit your needs.

No matter what you choose, make sure to look at the documentation and select the correct attribute. In this post, we mentioned data-testid, but this is by no means a standard, so adjust accordingly to your project.

Ready to start testing emails?
Create a free account.

Get started