Test React function components promises behaviour with Jest,

871 views Asked by At

I have a React function component. I pass a function to the component as a prop, that returns a promise. I use that function on an onClick event and once the promise is resolved, I change the state of the component. Something like:

import React, { useState } from 'react';

function myComponent({ aPromiseReturningFunction }) {
    const [myState, setState] = useState('12');
    const clickHandler = () => {
      aPromiseReturningFunction().then(() => { setState('123') })
    };

    return <div onClick={ clickHandler }>{myState}</div>
}

Inside my test:

const myFunc = jest.fn(() => Promise.resolve(true));
const componentWrapper = shallow(<myComponent aPromiseReturningFunction={ myFunc }/>);
componentWrapper.simulate('click');
expect(componentWrapper.text()).toEqual('123');

Obviously the above fails, but I have not found anything that would explain how to properly test the above. Of course If I change the state outside the promise, the test passes.

Any suggestions?

2

There are 2 answers

0
manosagent On

Thanks to alextrastero, I managed to come to a solution eventually.

What is missing from alextrastero's answer is that we should enclose the act() inside async/await like:

import { act } from 'react-dom/test-utils'; // other testing libraries have similar methods that test async events

const myFunc = jest.fn(() => Promise.resolve(true));

it('updates text after onclick', async () => {
  const componentWrapper = shallow(<myComponent aPromiseReturningFunction={ myFunc }/>);
  await act(() => {
    componentWrapper.simulate('click');
  });

  expect(componentWrapper.text()).toEqual('123');
});

And in order for that to work, I also needed to use the regenerator-runtime/runtime package.

0
alextrastero On

Since click is updating the state after a promise aka asynchronously, I would use act

import { act } from 'react-dom/test-utils'; // other testing libraries have similar methods that test async events

const myFunc = jest.fn(() => Promise.resolve(true));

it('updates text after onclick', () => {
  const componentWrapper = shallow(<myComponent aPromiseReturningFunction={ myFunc }/>);
  act(() => {
    componentWrapper.simulate('click');
  });

  expect(componentWrapper.text()).toEqual('123');
});