React Testing Library
Jed Dayo

- Introduction to React Testing Library
- Comparison with Enzyme
- Best Practices
- Demo
Agenda

The enzyme is a javascript testing utility for React that makes it easier to assert, manipulate and traverse the components. It was created by Airbnb and later transferred to an independent Organization. It was developed around December 2015. It provides manageable methods to find elements, render components and interact with the elements.
What is Enzyme
Enzyme - Sample Code
describe('Login Test Suite', () => {
it('should render the form', () => {
const wrapper = shallow(<Login />);
expect(wrapper.find('form.login').exists()).toBe(true);
expect(wrapper.find('#email').length).toEqual(1);
expect(wrapper.find('#password').length).toEqual(1);
})
})
describe("The events are working", () => {
it("The form is submitted when the click event is fired", () => {
const mockCallBack = jest.fn();
const wrapper = shallow(<Form onSubmit={mockCallBack()} />);
wrapper.find("#submit-button").simulate("click");
expect(mockCallBack).toHaveBeenCalledTimes(1);
});
});
describe("Snapshot", () => {
it("matches App the snapshot", () => {
const wrapper = mount(<App />);
expect(toJson(wrapper)).toMatchSnapshot();
});
});
React Testing Library
- "The more your test resemble the way your software is used" - Kent C. Dodds
- "You are not testing code, you are testing behaviour"
- "Test your function as a whole based on how your user uses it
- Accessibility first
Enzyme
- "Test your react components output by manipulating, traversing, and asserting output"
- "Test your internal code implementation"
- "Isolate your test as much as possible"
- "Not focused on accessibility"
- Rewrite test if implementation changed


Modern testing - Redux
https://redux.js.org/usage/writing-tests

- The @testing-library family of packages helps you test UI components in a user-centric way
- Opinionated on how to find elements
- Should find based on accessibility, on how screen reader find elements in the DOM
What Is React Testing Library ?
- ByRole
- ByLabelText
- ByPlaceholderText
- ByText
- ByDisplayValue
- ByAltText
- ByTitle
- ByTestId
Queries
Used to find and get elements in the DOM
Best Practice - Queries Accessible to Everyone
https://testing-library.com/docs/queries/about
Reflect the experience of visual/mouse users as well as those that use assistive technology.
#1 getByRole
This can be used to query every element that is exposed in the accessibility tree
Example: getByRole('button', {name: /submit/i})
#2 getByLabelText
This method is really good for form fields. When navigating through a website form, users find elements using label text. This method emulates that behaviour, so it should be your top preference
Example: getByLabelText('username')
#3 getByPlaceholderText
A placeholder is not a substitute for a label. But if that's all you have, then it's better than alternatives.
Example: getByPlaceholderText('enter username here')
#4 getByText
Outside of forms, text content is the main way users find elements. This method can be used to find non-interactive elements (like divs, spans, and paragraphs)
Example:
getByText('Contact Us'),
getByText(/Contact Us/i)
#5 getByDisplayValue
The current value of a form element can be useful when navigating a page with filled-in values
Example:
getByDisplayValue('100%')
Semantic Queries
HTML5 and ARIA compliant selectors. Note that the user experience of interacting with these attributes varies greatly across browsers and assistive technology.
#6 getByAltText
If your element is one which supports alt
text (img
, area
, input
, and any custom element), then you can use this to find that element
Example:
getByAltText('this is an image')
#7 getByTitle
The title attribute is not consistently read by screenreaders, and is not visible by default for sighted users
Example:
getByTitle('I get shown on hover')
Test Id - #8 getByTestId
The user cannot see (or hear) these, so this is only recommended for cases where you can't match by role or text or it doesn't make sense (e.g. the text is dynamic)
Example:
getByTestId('test-submit-button-id')
FireEvent
Convenience methods for firing DOM events
see for full list -> https://github.com/testing-library/dom-testing-library/blob/main/src/event-map.js
Commonly used
- fireEvent.click([element])
- fireEvent.change([element])
- fireEvent.input([element])
- fireEvent.blur([element])
- fireEvent.focus([element])
Lets test - amount 0 should show error

Sample Code
describe('payment form validation',()=>{
it('should show minimum amount error',()=>{
render(<PaymentForm/>);
const amountInput = screen.getByLabelText('Amount');
fireEvent.change(amountInput, {target: {value: 0}});
fireEvent.blur(amountInput);
expect(screen.getByText(/amount should be greater than 0/i));
})
})
UserEvent
user-event
is a companion library for Testing Library that simulates user interactions by dispatching the events that would happen if the interaction took place in a browser.
Best Practice - Use this instead of FireEvent
Sample Code
describe('payment form validation',()=>{
it('should show minimum amount error',()=>{
render(<PaymentForm/>);
const amountInput = screen.getByLabelText('Amount');
userEvent.type(amountInput, '0{enter}');
expect(screen.getByText(/amount should be greater than 0/i));
})
})
Best Practices - links
https://kentcdodds.com/blog/common-mistakes-with-react-testing-library
https://kentcdodds.com/blog/write-fewer-longer-tests
https://testingjavascript.com

React Testing Library
By Jed Dayo
React Testing Library
- 74