DEV Community

Cover image for How to add data-* attributes to your component library and benefit from them in your E2E tests
Marco Streng
Marco Streng

Posted on

How to add data-* attributes to your component library and benefit from them in your E2E tests

Intro

When building a component library, one of the most important things is a seamless and clean documentation of the available properties of a component.

Users of your component library should not be able to write random properties on components which are not used by it. Otherwise an error like Warning: React does not recognize the 'isVisible' prop on a DOM element. [...] If you accidentally passed it from a parent component, remove it from the DOM element. can be thrown quickly.

The data-* and why we sometimes need it

There are use cases in which users need to have the ability to pass some kind of random properties on the components.

For me, such a use case was adding selector attributes for End-2-End tests like data-test-element="header" to the libraries components in my project.
(BTW: I love to write my E2E tests with cypress.)

Solution

A small and simple function which takes your property object and returns just valid properties that should appear in the rendered markup.

const validateProps = (props) => {
  const newProps = {}

  Object.keys(props).forEach((key) => {
    if (key.startsWith('data-') || key === 'className') newProps[key] = props[key]
  })

  return newProps
}

Enter fullscreen mode Exit fullscreen mode

Usage

In your components you can extract the properties which are used by it self. All other properties are passed through validateProps().

const Badge = ({ onToggle, isActive, children, ...props }) => (
  <Wrapper
    isActive={isActive}
    onClick={onToggle}
    {...validateProps(props)}
  >
    {children}
  </Wrapper>
)
Enter fullscreen mode Exit fullscreen mode

??? className ???

Maybe you wonder why validateProps() keeps the className property? That's because I work with styled-components. If you add some custom styling from outside to a component you will have to write this property on the component (see styled-component docs)

Prod vs. Dev

Depending on how and where you run your tests, you maybe don't want to see those data-test-* attributes in your markup in production.

In this case I recommend babel-plugin-react-remove-properties.

Usage

Filter all data-test-element properties only in production with the following config in the .babelrc of your project.

{
  "env": {
    "production": {
      "plugins": [
        [
          "react-remove-properties", {
            "properties": [
              "data-test-element"
            ]
          }
        ]
      ]
    },
  }
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)