8

I have a component that has few useState hooks:

const [resizing, setResizing] = React.useState(false);
const [x, setX] = React.useState(0);
const [y, setY] = React.useState(0);

And in some places I am calling more than one hook at a time, for example here in onResize, I am calling both setResizing and setX or setY hook:

<ResizableBox
    height={520}
    width={370}
    minConstraints={[370, 520]}
    maxConstraints={[Infinity, Infinity]}
    className={classes.resizable}
    onResize={(e) => {
      if (e.movementX !== 0) {
        setResizing(true);
        setX((prev) => prev + e.movementX);
      } else if (e.movementY !== 0) {
        setResizing(true);
        setY((prev) => prev + e.movementY / 2);
      }
    }}
    onResizeStop={() => {
      setResizing(false);
    }}
  >

I am used to testing class components where it is easy to test state changes.

I would like to test it with something like this:

const setXSpy = jest.spyOn(React, 'setX');
const setYSpy = jest.spyOn(React, 'setY');
const setResizeSpy = jest.spyOn(React, 'setResize');


it('calls useState hooks correctly', () => {
  resizableBox.props.onResize({movementX: 1});

  expect(setXSpy).toHaveBeenCalledWith(1);
  expect(setYSpy).not.toHaveBeenCalled();
  expect(setResizeSpy).toHaveBeenCalledWith(true);
});

But, I am not sure how test hooks like that in this example?

Leff
  • 1,968
  • 24
  • 97
  • 201

2 Answers2

3

You're testing the implementation details of that component which is not a good idea (you're basically coupling the test to that implementation, instead of using the test to determine that the component does what it is supposed to do).

Instead I would try and find a way to test the component as a user would and determine that the output is correct.

Start by integrating testing-library and then follow some of the patterns described here and here.

The question is, what are you trying to test? what is the expected outcome of this test and which behaviour will it cover?

LE: in your case, as I see you're trying to test React-Resizable, you can try and mouseDown on the resize handle, then emit mouseMove and mouseUp and see if the right things happens (I don't see from the code what you are doing with the state values, what are you using them for)

tudor.gergely
  • 4,800
  • 1
  • 16
  • 22
0

The code I use to do that is the following:

const mockSetState = jest.fn();

jest.mock('react', () => ({
  ...jest.requireActual('react'),
  useState: () => ['', mockSetState],
}));


it('...', () => {
    expect(mockSetState).toHaveBeenNthCalledWith(1, first expected value);
    expect(mockSetState).toHaveBeenNthCalledWith(2, second expected value');
})
Andrey Solera
  • 2,311
  • 2
  • 26
  • 51