Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test getDerivedStateFromProps with Jest and Enzyme

I have this simple code that is using the new getDerivedStateFromProps lifecycle:

static getDerivedStateFromProps(nextProps: Props, prevState: State) {
  if (nextProps.value !== prevState.value) {
    console.log('hello');
    return {
      value: nextProps.value
    };
  }

  return null;
}

And this is the test:

it('should call getDerivedStateFromProps', () => {
  const instance = shallow(mockComponent());

  instance.setProps({ value: 'test2' });

  expect(instance.state.value).toEqual('test2');
});

But I have this error but I know that is calling because of the console.log().

Expected value to equal:
  "test2"
Received:
  undefined

How do I test properly getDerivedStateFromProps?

I'm using:

react: 16.4
react-Dom: 16.4
enzyme-adapter-react-16: 1.1.1
react-test-renderer: 16.4.1
like image 476
Albert Olivé Avatar asked Dec 14 '22 16:12

Albert Olivé


2 Answers

It's a static function with no dependency. I think you can test it in isolation like every other function:

const givenProps = {...};
const givenState = {...};
const result = MyComponent.getDerivedStateFromProps(givenProps, givenState);

expect(result).toEqual({
  ...
})

I think it is a valid approach because of getDerivedStateFromProps should not contain any side-effects and be pure - which means - given the same input it will produce the same output. And because the instance of a component has no relevance here creating one would test nothing but react internals.

This would be also similar to how you would test a redux reducer.

like image 174
Tomasz Mularczyk Avatar answered Dec 17 '22 22:12

Tomasz Mularczyk


In my experience you should not call directly the "getDerivedStateFromProps" function to test it. It's part of the component's lifecycle, therefore all you need to do is to:

  1. Initiate the component with a value in state.
  2. Update props with new value.
  3. check the state (since it will be updated because the "getDerivedStateFromProps" function will be automatically called.

For example:

describe('getDerivedStateFromProps', () => {
        it('new value arrived from props and state is updated', () => {
            const newValue = 'NewVal';
            const wrapper = createAndMountComponent(params); // here initiate your component wrapper
            const instance = wrapper.instance();

            wrapper.setProps({ value: newValue });  // update props

            const { value, valueFromProps } = instance.state; // check if the value in state was updated
            expect(value).toEqual(newValue);
            expect(valueFromProps).toEqual(newValue);
        });
});

This is enough to test the "getDerivedStateFromProps" function. Of course you should not forget to update the value inside the "getDerivedStateFromProps" function:

static getDerivedStateFromProps(props, state) {
    const { value } = props;
    const { valueFromProps } = state;

    if (value !== valueFromProps) {
        return {
            value,
            valueFromProps: value
        };
    }
    return null;
}
like image 45
Sophie Cooperman Avatar answered Dec 17 '22 22:12

Sophie Cooperman