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