React: How to write UI logical test

A simple guide to writing tests for your react UI, using Jest and enzyme

Fabio Marcoccia
3 min readJan 10, 2021
Photo by tekiana

Jest is the most “famous” framework for writing tests for React (and probably the most used) and it is very very simple to configure, it also contains a complete set of APIs to perform a large scale of different tests.

Enzyme allows the abstraction of the DOM of a single component and its direct manipulation.

I start a project from CRA using:
npx create-react-app my-app — template typescript

The project will have 2 reusable components:

  • AmountInput
  • AmountLabel

    And 1 component to link the components above:
  • Conversion

AmountInput

AmountInput.component.tsx

This component is an input that accepts only a positive number and not greater than 10000

AmountLabel

AmountLabel.component.tsx

This component prints a number by assigning the className ‘amount_label_ok’ if the number is greater than 100 otherwise it assigns ‘amount_label_ko’

Before going on, let’s test these 2 components.
We need to install these libraries:

// To test UI after a useEffect run
jest-react-hooks-shallow
enzyme
enzyme-adapter-react-16

then add them in setupTest.ts

import { configure } from ‘enzyme’;
import React16Adapter from ‘enzyme-adapter-react-16’;
import enableHooks from ‘jest-react-hooks-shallow’;
configure({ adapter: new React16Adapter() });enableHooks(jest, { dontMockByDefault: true });

AmountInput Test

It makes sense to test the initial state, the onChange callback and the error state.

AmountInput.test.tsx

Note:
without using “withHooks” the internal state of the component would not be updated because the useEffect would not be executed

AmountLabel Test

It makes sense to test the initial state and the other 3 states: amount greater than 100, amount lower than 100 and zero (or negative it’s the same)

AmountLabel.test.tsx

Well done! We will now create a Conversion component to render a user interface that allows you to enter an amount and print a conversion from EUR to GBP

Conversion

Conversion.component.tsx

getRateEURGBP is a fake promise that returns a random number between 0 and 0.9999999.
Loading component is just a spinner.

Conversion Test

It makes sense to test the initial state, the loading state and success state (write a positive amount and will print the converted amount).

Conversion.test.tsx

In the second test, we don’t need to mock the API¹ because the state must remain isLoading = true (to test the presence of <Loading/> in the UI

In the last test, we need to mock the API because we have to simulate the onChange of amount, the response of API and the presence of <AmountLabel/> in the UI

¹see comment “don’t mock the returns of api”

In the next article we will see how to test a component that uses a redux hooks!

Thanks!!
I hope I was helpful :)

--

--