Open einatnielsen opened 4 years ago
I also found this tool called Spearmint: a tool to create RTL tests from UI, I tested it but I am not sure it is good enough: https://www.spearmintjs.com/
One more thing I encountered: Testing components with async componentDidMount come in pretty complicated when trying to test them in enzyme: airbnb/enzyme#1587
RTL unlike Enzyme, waits and retries to get element until it is available therefor we can test async componentDidMount in other ways like loader appears and disappears and so on (many other ways available).
Another thing is like @einatnielsen mentioned, enzyme uses enzyme-adapter that also creates some extra configuration and from time to time - updates.
CC: @lidoravitan @einatnielsen @liadShiranNielsen @thehulke @amitNielsen @MatanBorenkraoutNielsen
Issues:
With RTL:
function HiddenMessage({children}) {
const [showMessage, setShowMessage] = React.useState(false)
return (
<div>
<label htmlFor="toggle">Show Message</label>
<input
id="toggle"
type="checkbox"
onChange={e => setShowMessage(e.target.checked)}
checked={showMessage}
/>
{showMessage ? children : null}
</div>
)
}
test('shows the children when the checkbox is checked', () => {
const testMessage = 'Test Message'
const {queryByText, getByLabelText, getByText} = render(
<HiddenMessage>{testMessage}</HiddenMessage>
)
expect(queryByText(testMessage)).toBeNull()
fireEvent.click(getByLabelText(/show/i))
expect(getByText(testMessage)).toBeInTheDocument()
})
With Enzyme:
function HiddenMessage({children}) {
const [showMessage, setShowMessage] = React.useState(false)
return (
<div>
<label htmlFor="toggle">Show Message</label>
<input
id="toggle"
type="checkbox"
class="my-checkbox-class"
onChange={e => setShowMessage(e.target.checked)}
checked={showMessage}
/>
{showMessage ? <span class="my-children-class"> {children} </span> : null}
</div>
)
}
test('shows the children when the checkbox is checked', () => {
const testMessage = 'Test Message'
const wrapper = mount(
<HiddenMessage>{testMessage}</HiddenMessage>
)
expect(wrapper.find('.my-children-class').text()).not.toBe('Test Message')
const checkbox = wrapper.find('.my-checkbox-class')
checkbox.simulate('change', { target: { checked: true } })
expect(wrapper.find('.my-children-class').text()).toBe('Test Message')
})
With RTL:
expect(getByText('Test Message')).toBeInTheDocument()
With Enzyme:
const element = wrapper.find('.my-class')
expect(element.text()).toBe('Test Message')
componentDidMount
- When having side effects inside componentDidMount
, we want to test the DOM after the async componentDidMount
finished.
In order to do that in Enzyme we can:
Flush all open promises by (Explained here):
await new Promise(resolve => setImmediate(resolve));
or just as seen in our Enzyme tests now:
mount(<MyComponent/>)
wait(randomNumberOfMs)
Waiting doesn't ensure us that what we wanted will happen, it's a matter of luck and our computer's CPU.
In RTL we can just:
import { render, wait } from "@testing-library/react";
const { getByText } = render(<MyComponent />);
await wait(() => expect(getByText("Mocked Data")).toBeInTheDocument());
@lidoravitan @einatnielsen - I didn't sum things up while in the meeting so if I missed something please let me know and I'll add it.
@einatnielsen @MatanBorenkraoutNielsen what are the cons of using RTL? what are the risks of switching from enzyme? (@talJoffeExelate )
At the moment we couldn't find the cons, as @thehulke mentioned, it looks like Enzyme was a step along the way and RTL actually expands its abilities and makes writing tests simpler and easier.
The only thing we saw for now is that Enzyme is widely adopted and RTL is being adopted at these moments. Enzyme weekly downloads on npm are about 1.7M and RTL has only 500K.
The main risk I see with switching is that we won't be able to rewrite all of our tests, and using both enzyme and RTL in our testbase might cause troubles with webapps-app-test-utils
, looking forwards I believe this risk will pay out.
@lidoravitan @einatnielsen While looking a bit more on RTL I found that they also have a cypress wrapper, it adds RTL functionality to cypress so selectors will work the same in Cypress as they will work when using RTL.
CRA(Create React App) version 3.3.0 added built in support for React-Testing-Library: https://twitter.com/kentcdodds/status/1202591559272648705
The purpose of this issue is to review the pros and cons between Enzyme and React Testing Library.
RTL Pros:
Enzyme Cons: