React: How to write UI logical test
A simple guide to writing tests for your react UI, using Jest and enzyme
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
This component is an input that accepts only a positive number and not greater than 10000
AmountLabel
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.
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)
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
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).
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 :)