npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

babel-plugin-react-data-testid-generator

v0.3.2

Published

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

Downloads

90

Readme

babel-plugin-react-data-testid-generator

npm version Build Status Coverage

🧪 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.

✨ Features

  • 🎯 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.HeaderComponentName.Header)
  • 🛡️ Never overrides existing attributes

🚀 Installation

npm install --save-dev babel-plugin-react-data-testid-generator
# or
yarn add --dev babel-plugin-react-data-testid-generator

📖 Usage

Basic Setup

Add the plugin to your .babelrc.json or babel.config.js:

{
  "plugins": ["babel-plugin-react-data-testid-generator"]
}

Framework-Specific Setup

Create .babelrc.json in your project root:

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "babel-plugin-react-data-testid-generator",
      {
        "attributes": ["data-testid"]
      }
    ]
  ]
}

Configure in vite.config.js:

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"],
            },
          ],
        ],
      },
    }),
  ],
});

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:

module.exports = {
  presets: ["react-app"],
  plugins: [
    [
      "babel-plugin-react-data-testid-generator",
      {
        attributes: ["data-testid"],
      },
    ],
  ],
};

With Custom Attributes

{
  "plugins": [
    [
      "babel-plugin-react-data-testid-generator",
      {
        "attributes": ["data-testid", "data-cy"]
      }
    ]
  ]
}

🔄 Transformations

Functional Components

Before:

function UserCard({ name }) {
  return (
    <div>
      <h3>{name}</h3>
      <button>Follow</button>
      <button>Message</button>
    </div>
  );
}

After:

function UserCard({ name }) {
  return (
    <div data-testid="UserCard.div">
      <h3 data-testid="UserCard.h3">{name}</h3>
      <button data-testid="UserCard.button">Follow</button>
      <button data-testid="UserCard.button2">Message</button>
    </div>
  );
}

Unique Counter System

The plugin uses component-scoped counters to ensure uniqueness:

function FormComponent() {
  return (
    <div>
      {" "}
      {/* FormComponent.div */}
      <div>First</div> {/* FormComponent.div2 */}
      <div>Second</div> {/* FormComponent.div3 */}
      <button>Save</button> {/* FormComponent.button */}
      <button>Cancel</button> {/* FormComponent.button2 */}
    </div>
  );
}

JSX Member Expressions

function ModalComponent() {
  return (
    <Modal.Container>
      {" "}
      {/* ModalComponent.Container */}
      <Modal.Header>Title</Modal.Header> {/* ModalComponent.Header */}
      <Modal.Body>Content</Modal.Body> {/* ModalComponent.Body */}
      <Modal.Header>Second</Modal.Header> {/* ModalComponent.Header2 */}
    </Modal.Container>
  );
}

Class Components

class TodoList extends React.Component {
  render() {
    return (
      <div>
        {" "}
        {/* TodoList.div */}
        <h2>My Todos</h2> {/* TodoList.h2 */}
        <ul>
          {" "}
          {/* TodoList.ul */}
          <li>Todo 1</li> {/* TodoList.li */}
          <li>Todo 2</li> {/* TodoList.li2 */}
        </ul>
        <button>Add Todo</button> {/* TodoList.button */}
      </div>
    );
  }
}

Conditional Rendering

function ConditionalComponent({ isLoggedIn }) {
  if (isLoggedIn) {
    return <div>Welcome</div>; // ConditionalComponent.div
  }
  return <div>Please login</div>; // ConditionalComponent.div2
}

⚙️ Configuration Options

| Option | Type | Default | Description | | ------------ | ---------- | ----------------- | ------------------------------------------- | | attributes | string[] | ["data-testid"] | Array of attribute names to add to elements |

Examples

Multiple testing frameworks:

{
  "plugins": [
    [
      "babel-plugin-react-data-testid-generator",
      {
        "attributes": ["data-testid", "data-cy", "data-test-id"]
      }
    ]
  ]
}

Cypress only:

{
  "plugins": [
    [
      "babel-plugin-react-data-testid-generator",
      {
        "attributes": ["data-cy"]
      }
    ]
  ]
}

Disable plugin:

{
  "plugins": [
    [
      "babel-plugin-react-data-testid-generator",
      {
        "attributes": []
      }
    ]
  ]
}

🧪 Testing Integration

Jest + React Testing Library

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(<UserCard name="John" />);

  // 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();
});

Cypress

describe("UserCard Component", () => {
  it("should interact with elements", () => {
    cy.mount(<UserCard name="John" />);

    // Use generated data-cy attributes
    cy.get('[data-cy="UserCard.button"]').click();
    cy.get('[data-cy="UserCard.button2"]').should("be.visible");
  });
});

Playwright

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();
});

📁 Example Applications

We provide two complete example applications demonstrating the plugin:

🚀 Next.js Example

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

⚡ Vite Example

cd example/vite
npm install
npm run dev

Features:

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!

🛠️ Supported React Patterns

| Pattern | Supported | Example | | ---------------------- | --------- | ---------------------------------------------- | | Function Components | ✅ | function MyComponent() {} | | Arrow Functions | ✅ | const MyComponent = () => {} | | Class Components | ✅ | class MyComponent extends React.Component {} | | Anonymous Exports | ⚠️ | export default () => {} (skipped) | | JSX Member Expressions | ✅ | <Modal.Header>ComponentName.Header | | Fragments | ✅ | <> and <React.Fragment> | | Conditional Rendering | ✅ | Multiple return statements | | Existing Attributes | ✅ | Never overrides existing data-testid | | Self-Closing Elements | ✅ | <img />, <input /> | | Nested Components | ✅ | Deep nesting with unique counters |

🎯 Best Practices

  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:
const isProd = process.env.NODE_ENV === "production";

module.exports = {
  plugins: [...(!isProd ? [["babel-plugin-react-data-testid-generator"]] : [])],
};
  1. 🧪 Test ID Patterns - use consistent patterns in tests:
    • ComponentName.elementType for first occurrence
    • ComponentName.elementType2 for second occurrence
    • ComponentName.MemberExpression for JSX member expressions

🔧 Development

Setup

git clone https://github.com/Kazaz-Or/babel-plugin-react-data-testid-generator.git
cd babel-plugin-react-data-testid-generator
yarn install

Commands

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

Testing

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

🤝 Contributors

Thanks to these wonderful people who have contributed to this project:

How to Contribute

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
  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and add tests
  4. Ensure all tests pass (yarn test)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

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-cli
  2. Add yourself: all-contributors add <your-username> <contribution-type>
  3. Update the README: all-contributors generate
  • 💻 code - Code contributions
  • 📖 doc - Documentation
  • 🐛 bug - Bug reports
  • 💡 ideas - Ideas and suggestions
  • 🧪 test - Tests
  • 🎨 design - Design
  • 🚧 maintenance - Maintenance
  • 📦 platform - Packaging/platform support

📄 License

MIT © Or Kazaz


🙏 Acknowledgments

Made with 💙 for better testing