Removing data-test Attributes from React Production DOM
This article uses React version 17.0.1 with testing dev dependencies enzyme, jest-enzyme and the React 17 enzyme adapter @wojtekmaj/enzyme-adapter-react-17. If you are using different versions of React you may have to use a different adapter for Enzyme. This article also assumes that you are using create-react-app as it makes use of multiple prepackaged npm scripts.
All great code starts with Test Driven Development, which is a process of coding tests for your app before coding the actual app. Testing can take many forms depending on whether you are testing the code’s behavior or implementation. These include unit, integration and end to end testing and generally follow the red green testing pattern of forcing the test to fail before writing passing tests.
There are many tools for testing, from Chai and Mocha to Selenium and Cypress. For React testing I usually use Enzyme and Jest to do unit and integration testing. In order to target components and elements in our DOM, we insert a data-test attribute pointer in the target element. This allows us to identify and isolate the node for node specific tests.
Why do we use data-test attributes instead of using classes or ID’s for our testing pointers? ID’s and classes are most commonly used in styling with CSS and functionality with Javascript, and are therefore more likely to be edited by other engineers on your team. It is much safer to use a custom data attribute, in this case data-test, to create pointers for our elements to test on because of the clarity of their purpose. Because they are unrelated to functional or aesthetic code, they are unlikely to be changed during development.
However, once you are done with testing in your development environment, you do not want to push a DOM to production that is littered with data-test attributes. Anyone who inspects your website will see a cluttered DOM filled with attributes with no production value. Because of this, we want to remove the data-test attributes during the build process so our final DOM is clean and data-test attribute free!
I have coded a very simple Hello World React App that displays “Hello World” in an h1 element. There is a single test running on this app which checks that a component was rendered for the header. To be able to correctly identify the h1 element for my test, I have added a data-test attribute with a value of “component-welcome” to the h1 and am using an expect and toBe assertion test on a shallow rendering of my App component to see if it is rendering correctly:
But wait! When I run the app on a local server, the data-test attribute shows up in the DOM:
This may not seem like an issue now, but what happens when we are testing 5 elements on each component of a 30 component render? Things get messy really fast. To combat that, we will remove the data-test attributes by adding and configuring the babel-plugin-react-remove-properties package.
The first step is to add the babel-plugin-react-remove-properties package as a dev dependency by running “npm i –save-dev babel-plugin-react-remove-properties.” This will add the package to our package.json file, but will not be added by webpack to our development package file.
After this dependency is installed, we run “npm run eject” which will allow us to edit our project’s config files. Because this script will expose our files to possible harmful changes, by us the users, we will have to create a commit before we are able to run this eject script.
With a commit made to allow us to revert our changes, and the eject script run, we are now ready to edit the package.json file. This file holds all of our dependencies, including all of our babel files.
We want to be able to remove certain properties from our DOM. The babel-plugin-react-remove-properties package allows us to do this. In the npm docs (listed in the resources at the bottom of the page) there are two blocks of code, one with options and one without. We will copy the code with options and put it in our babel dependency:
I edited the properties value to only include data-test as that is the only thing I care to remove. After adding this code to our package.json and modifying it to focus on data-test, we are ready for the next step, creating our production build.
From the terminal run “npm run build” which will create a production version of our React app. After the build is finished running we will have the option to run it on a local server.
If this is your first time running a production build you will need to run “npm i –g serve” which will install the serve package globally on your machine. Once this is complete, run “serve –s build” which will start a local server. Mine is on localhost:5000. When I navigate to this address I find that my app is running, and the data-test attribute is no longer in my DOM! Success!
You now have a data-test attribute free DOM that you can safely create and deploy at any time!
Resources
https://www.npmjs.com/package/babel-plugin-react-remove-properties
https://github.com/wojtekmaj/enzyme-adapter-react-17
https://www.udemy.com/course/react-testing-with-jest-and-enzyme/