React with Enzyme

Krzysztof Kwieciński
2 min readOct 29, 2019

Every workday I write plenty of tests using Enzyme. Even though the library is well designed, there are some tricky points, where it is easy to make a mistake and spend much precious time trying to figure out why one test does not pass… 😤

Enzyme or Enzyme?

Updating state onEvent

Let’s consider a simple scenario:

  • we mount a component and get a wrapper
  • prop.value of the tab has initially value before
  • a click event is simulated
  • prop.value should have value after
const tab = wrapper.find('.tab');
expect(tab.props().value).toEqual('before');
tab.find('button').simulate('click');
expect(tab.props().value).toEqual('after');

Looks good, doesn’t it? Unfortunately, this might not work 🥴

The issue is further described in the Enzyme’s official issue tracker.

TLDR: wrapper does not update its values on its own — we need to trigger the update manually. Moreover, already found-wrappers are not updated. That means, two lines of code have to be added to make the test green:

...
tab.find('button').simulate('click');
wrapper.update();
tab = wrapper.find('tab');

expect(tab.props().value).toEqual('after');

Real-life example

There are two buttons, initially the first is active. After clicking on the other one, the second button becomes active.

function findButtons(wrapper: ReactWrapper) {
const buttons = wrapper.find(buttonClass);
return { first: buttons.first(), last: buttons.last() };
}
it('should select active button when clicked', () => {
const panel = mount({ buttons, activeIndex: 0 });
expect(findButtons(panel).first.find(Styles.active)).exists())
.toBeTruthy();
expect(findButtons(panel).last.find(Styles.active)).exists())
.toBeFalsy();

findButtons(panel).last.simulate(EVENT_CLICK);
panel.update();
expect(findButtons(panel).first.find(Styles.active)).exists())
.toBeFalsy();
expect(findButtons(panel).last.find(Styles.active)).exists())
.toBeTruthy();
});

Simulating different types of events

Above the click-event was described. However, there are plenty of other events, for instance:

  • change
  • blur
  • focus

It may happen that in our app there is a textarea. For our use-case imagine that the length of the text, the user can write, is limited. We want to have a test that checks if our logic behaves correctly and the textarea gets a red border when too many letters are typed.

How can we set a text in the textarea?

wrapper.find('textarea').simulate('click');

Obviously, it won’t work — to change the text, we need change event, not just click 🤭 So maybe:

wrapper.find('textarea').simulate('change');

Nope. We have to pass a text value to be shown 💡 An event has to be specified!

const event = { target: { value: 'comment '} };
wrapper.find('textarea').simulate('change', event);

Conclusion: simulate accepts two parameters — an arbitrary event name and its value.

Summary

React + Enzyme = 🌩️❤️🌩️

--

--

Krzysztof Kwieciński

Software Craftsman who loves learning new things and is always eager to share his knowledge with others