
React18 Enzyme To Rtl
Rewrite React tests that still import Enzyme so they run on React 18 using React Testing Library behavior-first queries instead of brittle wrapper internals.
Overview
React 18 Enzyme to RTL is an agent skill for the Ship phase that rewrites Enzyme-based React tests into behavior-focused React Testing Library suites compatible with React 18.
Install
npx skills add https://github.com/github/awesome-copilot --skill react18-enzyme-to-rtlWhat is this skill?
- Explicit Enzyme → RTL API mapping for shallow, mount, find, simulate, prop, state, and instance patterns
- Philosophy shift: behavior and user-visible outcomes instead of internal state and instance methods
- Warns against 1:1 API translation that produces brittle RTL tests
- Covers configure/Adapter removal and React 18–compatible testing setup expectations
- Guides rewriting assertions around roles, labels, and document queries
Adoption & trust: 619 installs on skills.sh; 34.6k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your React 18 upgrade is blocked because Enzyme tests fail or cannot run without an adapter, and direct API swaps create fragile tests.
Who is it for?
Maintainers of React SPAs or extensions with legacy Enzyme coverage who are upgrading to React 18 and want guided rewrites in Cursor or Claude Code.
Skip if: Greenfield React apps already on RTL/Vitest, or non-React stacks where enzyme never appeared.
When should I use this skill?
Any test file imports enzyme or uses shallow, mount, wrapper.find(), wrapper.simulate(), wrapper.prop(), wrapper.state(), wrapper.instance(), or Enzyme configure/Adapter calls during a React 18 upgrade.
What do I get? / Deliverables
Enzyme imports are removed and tests assert user-visible behavior with RTL queries so the suite runs on React 18 and survives refactors.
- RTL test files replacing Enzyme imports
- Behavior-based assertions without wrapper internals
Recommended Skills
Journey fit
Ship is where test suites must pass CI and Enzyme blocks React 18 upgrades; the skill is invoked during migration and hardening before release. Testing subphase covers unit and integration test rewrites, not feature implementation—exactly when Enzyme APIs must be replaced.
How it compares
Migration playbook for test philosophy and API mapping—not a generic unit-test generator or E2E Playwright skill.
Common Questions / FAQ
Who is react18-enzyme-to-rtl for?
Solo developers and small teams upgrading React codebases that still depend on enzyme shallow/mount tests and need RTL patterns that match React 18 support reality.
When should I use react18-enzyme-to-rtl?
In Ship/testing when CI fails on enzyme imports, before merging a React 18 bump, or whenever you open a test using wrapper.find, wrapper.simulate, wrapper.state, or enzyme Adapter configuration.
Is react18-enzyme-to-rtl safe to install?
The skill guides test refactors only; confirm repo trust and review the Security Audits panel on this Prism page before letting an agent edit test files at scale.
SKILL.md
READMESKILL.md - React18 Enzyme To Rtl
# React 18 Enzyme → RTL Migration Enzyme has no React 18 adapter and no React 18 support path. All Enzyme tests must be rewritten using React Testing Library. ## The Philosophy Shift (Read This First) Enzyme tests implementation. RTL tests behavior. ```jsx // Enzyme: tests that the component has the right internal state expect(wrapper.state('count')).toBe(3); expect(wrapper.instance().handleClick).toBeDefined(); expect(wrapper.find('Button').prop('disabled')).toBe(true); // RTL: tests what the user actually sees and can do expect(screen.getByText('Count: 3')).toBeInTheDocument(); expect(screen.getByRole('button', { name: /submit/i })).toBeDisabled(); ``` This is not a 1:1 translation. Enzyme tests that verify internal state or instance methods don't have RTL equivalents - because RTL intentionally doesn't expose internals. **Rewrite the test to assert the visible outcome instead.** ## API Map For complete before/after code for each Enzyme API, read: - **`references/enzyme-api-map.md`** - full mapping: shallow, mount, find, simulate, prop, state, instance, configure - **`references/async-patterns.md`** - waitFor, findBy, act(), Apollo MockedProvider, loading states, error states ## Core Rewrite Template ```jsx // Every Enzyme test rewrites to this shape: import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import MyComponent from './MyComponent'; describe('MyComponent', () => { it('does the thing', async () => { // 1. Render (replaces shallow/mount) render(<MyComponent prop="value" />); // 2. Query (replaces wrapper.find()) const button = screen.getByRole('button', { name: /submit/i }); // 3. Interact (replaces simulate()) await userEvent.setup().click(button); // 4. Assert on visible output (replaces wrapper.state() / wrapper.prop()) expect(screen.getByText('Submitted!')).toBeInTheDocument(); }); }); ``` ## RTL Query Priority (use in this order) 1. `getByRole` - matches accessible roles (button, textbox, heading, checkbox, etc.) 2. `getByLabelText` - form fields linked to labels 3. `getByPlaceholderText` - input placeholders 4. `getByText` - visible text content 5. `getByDisplayValue` - current value of input/select/textarea 6. `getByAltText` - image alt text 7. `getByTitle` - title attribute 8. `getByTestId` - `data-testid` attribute (last resort) Prefer `getByRole` over `getByTestId`. It tests accessibility too. ## Wrapping with Providers ```jsx // Enzyme with context: const wrapper = mount( <ApolloProvider client={client}> <ThemeProvider theme={theme}> <MyComponent /> </ThemeProvider> </ApolloProvider> ); // RTL equivalent (use your project's customRender or wrap inline): import { render } from '@testing-library/react'; render( <MockedProvider mocks={mocks} addTypename={false}> <ThemeProvider theme={theme}> <MyComponent /> </ThemeProvider> </MockedProvider> ); // Or use the project's customRender helper if it wraps providers ``` # Async Test Patterns - Enzyme → RTL Migration Reference for rewriting Enzyme async tests to React Testing Library with React 18 compatible patterns. ## The Core Problem Enzyme's async tests typically used one of these approaches: - `wrapper.update()` after state changes - `setTimeout` / `Promise.resolve()` to flush microtas