react18-enzyme-to-rtl
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact 18 Enzyme → RTL Migration
React 18 Enzyme → RTL 迁移
Enzyme has no React 18 adapter and no React 18 support path. All Enzyme tests must be rewritten using React Testing Library.
Enzyme没有适配React 18的适配器,也没有支持React 18的后续规划。所有Enzyme测试都必须使用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.
Enzyme测试实现逻辑,RTL测试用户行为。
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();这不是1:1的直译。验证内部状态或实例方法的Enzyme测试没有对应的RTL等价写法——因为RTL刻意不暴露内部逻辑。请重写测试,转而断言可见的输出结果。
API Map
API 映射
For complete before/after code for each Enzyme API, read:
- - full mapping: shallow, mount, find, simulate, prop, state, instance, configure
references/enzyme-api-map.md - - waitFor, findBy, act(), Apollo MockedProvider, loading states, error states
references/async-patterns.md
要获取每个Enzyme API对应的完整前后对照代码,请阅读:
- - 完整映射:shallow, mount, find, simulate, prop, state, instance, configure
references/enzyme-api-map.md - - waitFor, findBy, act(), Apollo MockedProvider, 加载状态, 错误状态
references/async-patterns.md
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();
});
});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)
RTL 查询优先级(按此顺序使用)
- - matches accessible roles (button, textbox, heading, checkbox, etc.)
getByRole - - form fields linked to labels
getByLabelText - - input placeholders
getByPlaceholderText - - visible text content
getByText - - current value of input/select/textarea
getByDisplayValue - - image alt text
getByAltText - - title attribute
getByTitle - -
getByTestIdattribute (last resort)data-testid
Prefer over . It tests accessibility too.
getByRolegetByTestId- - 匹配可访问角色(button, textbox, heading, checkbox等)
getByRole - - 关联了label的表单字段
getByLabelText - - 输入框占位符
getByPlaceholderText - - 可见文本内容
getByText - - input/select/textarea的当前值
getByDisplayValue - - 图片alt文本
getByAltText - - title属性
getByTitle - -
getByTestId属性(最后备选方案)data-testid
优先使用而非,它同时还能测试可访问性。
getByRolegetByTestIdWrapping with Providers
使用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 providersjsx
// 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