Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test React state after calling a component method that updates state - using Enzyme

Tags:

reactjs

enzyme

Enzyme newbie here. I am trying to test if the state of a React component is being updated after calling a method on that component.

This is a snippet of the component that I am testing:

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  state = {
    recipes: {},
    user: null
  };

  handleUnauth = () => {
    this.setState({
      user: null
    });
  };

  render() {
   //render children, pass down methods as props etc...
  }

}

Below is the test:

import createRouterContext from 'react-router-test-context';
import { shallow, mount } from 'enzyme';
import expect from 'expect';
import React from 'react';

import App from 'App';  //import with webpack alias

describe('App', () => {

  let wrapper, context;

  beforeEach(() => {
    context = createRouterContext();
    wrapper = mount(<App/>, { context });
  });

  it('should remove logged in user details on logout', () => {
    const user = {
      uid: 'abc123',
      name: 'John Doe'
    };

    wrapper.setState({ user }, () => {
      wrapper.instance().handleUnauth();
      const userState = wrapper.state('user');
      expect(userState).toEqual(null);
    });

  });

});

My test fails with the following error:

enter image description here

I understand that updating of state is not synchronous but I am not sure if that has something to do with this or if there are better ways to test this using Enzyme. Would be super grateful if someone can please point me in the right direction. Oh and I tried this by calling wrapper.update() right after calling wrapper.instance().handleUnauth() in the test but this too didn't work.

like image 841
larrydalmeida Avatar asked Aug 27 '17 11:08

larrydalmeida


People also ask

How do I check state update in React?

state , we use this. setState() . This is a function available to all React components that use state, and allows us to let React know that the component state has changed. This way the component knows it should re-render, because its state has changed and its UI will most likely also change.

What happens after the component state is being updated?

The state does not depend on the rendering of a component and remains unaffected by re-rendering. The state gets updated only by a lifecycle method or by a call to setState.

Can we use both Enzyme and React testing library?

Migrating from react-testing-library to EnzymeTo migrate tests from react-testing-library to Enzyme, you'll need to install an additional library called enzyme-adapter-react-[react-version] . This adapter library is necessary and there are different setup steps depending on your version.


1 Answers

From the React#setState,

setState(updater, [callback])

setState() enqueues changes to the component state. The setState doesn't immediately update the state. setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.Instead, use componentDidUpdate or a setState callback (setState(updater, callback))

Solution 1:

Remove callback from setState;

      wrapper.setState({ user });
      wrapper.instance().handleUnauth();
      const userState = wrapper.state('user');
      expect(userState).toEqual(null);

Solution 2:

Read the updated state in the callback parameter of setState callback

wrapper.setState({ user }, (userState) => {

      wrapper.instance().handleUnauth();
      //const userState = wrapper.state('user'); // comment it.
      expect(userState).toEqual(null);
});
like image 158
RIYAJ KHAN Avatar answered Sep 28 '22 00:09

RIYAJ KHAN