Enhanced babel plugin for automatic React data-testid generation with unique IDs and class component support
npm install babel-plugin-react-data-testid-generator


> ๐งช Enhanced Babel plugin for automatic React data-testid generation with unique IDs and comprehensive component support
Automatically adds data-testid attributes to your React components during the build process, making it easier to write reliable end-to-end tests. Features component-scoped unique counters for predictable, collision-free test IDs.
- ๐ฏ Automatic data-testid generation for functional and class components
- ๐ข Component-scoped unique counters to prevent ID conflicts
- ๐ Predictable naming like ComponentName.element, ComponentName.element2
- ๐ญ Full React support: Functional components, arrow functions, class components
- ๐ง Customizable attributes (data-testid, data-cy, data-test-id, etc.)
- ๐ Zero configuration - works out of the box
- ๐ฆ TypeScript support with full type definitions
- ๐ Framework agnostic - works with Next.js, Vite, CRA, and more
- ๐ JSX member expressions support (Modal.Header โ ComponentName.Header)
- ๐ก๏ธ Never overrides existing attributes
``bash`
npm install --save-dev babel-plugin-react-data-testid-generatoror
yarn add --dev babel-plugin-react-data-testid-generator
Add the plugin to your .babelrc.json or babel.config.js:
`json`
{
"plugins": ["babel-plugin-react-data-testid-generator"]
}
๐ Next.js
Create .babelrc.json in your project root:
`json`
{
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-react-data-testid-generator",
{
"attributes": ["data-testid"]
}
]
]
}
โก Vite
Configure in vite.config.js:
`javascript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [
react({
babel: {
plugins: [
[
"babel-plugin-react-data-testid-generator",
{
attributes: ["data-testid"],
},
],
],
},
}),
],
});
`
๐ฆ Create React App
Note: CRA v5+ ignores custom babel configs. Use Next.js or Vite instead, or eject from CRA.
For ejected CRA, add to babel.config.js:
`javascript`
module.exports = {
presets: ["react-app"],
plugins: [
[
"babel-plugin-react-data-testid-generator",
{
attributes: ["data-testid"],
},
],
],
};
`json`
{
"plugins": [
[
"babel-plugin-react-data-testid-generator",
{
"attributes": ["data-testid", "data-cy"]
}
]
]
}
Before:
`jsx`
function UserCard({ name }) {
return (
{name}
);
}
After:
`jsx`
function UserCard({ name }) {
return (
{name}
);
}
The plugin uses component-scoped counters to ensure uniqueness:
`jsx`
function FormComponent() {
return (
{" "}
{/ FormComponent.div /}
First {/ FormComponent.div2 /}
Second {/ FormComponent.div3 /}
{/ FormComponent.button /}
{/ FormComponent.button2 /}
);
}
`jsx`
function ModalComponent() {
return (
{" "}
{/ ModalComponent.Container /}
);
}
`jsx`
class TodoList extends React.Component {
render() {
return (
{" "}
{/ TodoList.div /}
My Todos
{/ TodoList.h2 /}
{" "}
{/ TodoList.ul /}
{/ TodoList.button /}
);
}
}
`jsx`
function ConditionalComponent({ isLoggedIn }) {
if (isLoggedIn) {
return Welcome; // ConditionalComponent.div
}
return Please login; // ConditionalComponent.div2
}
| Option | Type | Default | Description |
| ------------ | ---------- | ----------------- | ------------------------------------------- |
| attributes | string[] | ["data-testid"] | Array of attribute names to add to elements |
Multiple testing frameworks:
`json`
{
"plugins": [
[
"babel-plugin-react-data-testid-generator",
{
"attributes": ["data-testid", "data-cy", "data-test-id"]
}
]
]
}
Cypress only:
`json`
{
"plugins": [
[
"babel-plugin-react-data-testid-generator",
{
"attributes": ["data-cy"]
}
]
]
}
Disable plugin:
`json`
{
"plugins": [
[
"babel-plugin-react-data-testid-generator",
{
"attributes": []
}
]
]
}
`javascript
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import UserCard from "./UserCard";
test("should interact with generated test ids", async () => {
render(
// Predictable test IDs
const followButton = screen.getByTestId("UserCard.button");
const messageButton = screen.getByTestId("UserCard.button2");
await userEvent.click(followButton);
expect(screen.getByTestId("UserCard.div")).toBeInTheDocument();
});
`
`javascript
describe("UserCard Component", () => {
it("should interact with elements", () => {
cy.mount(
// Use generated data-cy attributes
cy.get('[data-cy="UserCard.button"]').click();
cy.get('[data-cy="UserCard.button2"]').should("be.visible");
});
});
`
`javascript
import { test, expect } from "@playwright/test";
test("user card interactions", async ({ page }) => {
await page.goto("/user-profile");
// Reliable selectors with generated IDs
await page.locator('[data-testid="UserCard.button"]').click();
await expect(page.locator('[data-testid="UserCard.div"]')).toBeVisible();
});
`
We provide two complete example applications demonstrating the plugin:
`bash`
cd example/babelrc
npm install
npm run dev
Features:
- Next.js 13+ with App Router
- Beautiful modern UI with animations
- Interactive components demonstrating test ID generation
- Open http://localhost:3000
`bash`
cd example/vite
npm install
npm run dev
Features:
- Vite with React 18
- Lightning-fast HMR
- Same UI as Next.js example
- Open http://localhost:3001
Both examples include:
- โ
Interactive forms and buttons
- โ
Modal components
- โ
Card layouts
- โ
Class and functional components
- โ
Conditional rendering
- โ
JSX member expressions
Inspect the DOM to see the automatically generated data-testid attributes!
| Pattern | Supported | Example |
| ---------------------- | --------- | ---------------------------------------------- |
| Function Components | โ
| function MyComponent() {} |const MyComponent = () => {}
| Arrow Functions | โ
| |class MyComponent extends React.Component {}
| Class Components | โ
| |export default () => {}
| Anonymous Exports | โ ๏ธ | (skipped) |
| JSX Member Expressions | โ
| โ ComponentName.Header |<>
| Fragments | โ
| and |data-testid
| Conditional Rendering | โ
| Multiple return statements |
| Existing Attributes | โ
| Never overrides existing |
| Self-Closing Elements | โ
| , |
| Nested Components | โ
| Deep nesting with unique counters |
1. ๐ท๏ธ Use PascalCase for component names to get predictable test IDs
2. ๐ Inspect Generated IDs in development to understand the structure
3. ๐ Environment-Specific - consider disabling in production:
`javascript
const isProd = process.env.NODE_ENV === "production";
module.exports = {
plugins: [...(!isProd ? [["babel-plugin-react-data-testid-generator"]] : [])],
};
`
4. ๐งช Test ID Patterns - use consistent patterns in tests:
- ComponentName.elementType for first occurrenceComponentName.elementType2
- for second occurrenceComponentName.MemberExpression
- for JSX member expressions
`bash`
git clone https://github.com/Kazaz-Or/babel-plugin-react-data-testid-generator.git
cd babel-plugin-react-data-testid-generator
yarn install
`bash`
yarn test # Run tests
yarn test:watch # Run tests in watch mode
yarn test:coverage # Run tests with coverage
yarn build # Build the plugin
yarn lint # Lint code
yarn fmt # Format code
The plugin has comprehensive test coverage (96%+) including:
- โ
62 test cases covering all React patterns
- โ
Snapshot testing for consistent output
- โ
Edge case handling
- โ
CI/CD with coverage thresholds
Thanks to these wonderful people who have contributed to this project:
![]() Or Kazaz ๐ง ๐ป ๐จ ๐ ๐ค |
We welcome contributions! Here are some ways you can help:
- ๐ Report bugs by opening an issue
- ๐ก Suggest features or improvements
- ๐ Improve documentation
- ๐งช Add test cases
- ๐ง Submit pull requests
๐ Contribution Process
1. Fork the repository
2. Create a feature branch (git checkout -b feature/amazing-feature)yarn test
3. Make your changes and add tests
4. Ensure all tests pass ()git commit -m 'Add amazing feature'
5. Commit your changes ()git push origin feature/amazing-feature
6. Push to the branch ()
7. Open a Pull Request
๐ค Adding Yourself as a Contributor
If you contribute to this project, you can add yourself to the contributors list:
1. Install the all-contributors CLI: npm install -g all-contributors-cliall-contributors add
2. Add yourself: all-contributors generate
3. Update the README:
๐ท๏ธ Contribution Types
- ๐ป code - Code contributionsdoc
- ๐ - Documentationbug
- ๐ - Bug reportsideas
- ๐ก - Ideas and suggestionstest
- ๐งช - Testsdesign
- ๐จ - Designmaintenance
- ๐ง - Maintenanceplatform` - Packaging/platform support
- ๐ฆ
MIT ยฉ Or Kazaz
---
- Inspired by babel-plugin-react-data-testid
Made with ๐ for better testing