Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest/Enzyme Unit Testing: How to pass store to shallow component that uses redux 4 and react-redux 6 connect function

I'm doing as usual some unit tests with jest and enzyme for one new project. I used to test components that were connected to redux in this way:

a) a store generator

import { createStore } from 'redux';

import rootReducer from '../src/reducers';

export const storeFactory = (initialState) => {
   return createStore(rootReducer, initialState);
}

which is consumed by the Input.test.js file

import React from 'react';
import { shallow } from 'enzyme';

import { findByTestAttr,storeFactory } from '../../../test/testUtils';
import Input from './Input';



const setup = (initialState={}) => {
    const store = storeFactory(initialState);
    const wrapper = shallow(
        <Input store={store} />
        ).dive();
    console.log(wrapper.debug());

}

being the example component Input.js:

import React, { Component } from 'react';
import { connect } from 'react-redux';

class Input extends Component {
    render(){
        return <div />;
    }
}

const mapStateToProps = (state) => {
    return {};
}

export default connect(mapStateToProps)(Input);

My npm package versions are:

 "dependencies": {
    "ajv": "^6.6.2",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-redux": "^6.0.0",
    "react-scripts": "2.1.3",
    "redux": "^4.0.1"
  }

  "devDependencies": {
    "check-prop-types": "^1.1.2",
    "enzyme": "^3.8.0",
    "enzyme-adapter-react-16": "^1.7.1",
    "jest": "^23.6.0",
    "jest-enzyme": "^7.0.1",
    "prop-types": "^15.6.2"
  }

And that used to work, but I'm getting this message when running the tests on the tests execution report:

Invariant Violation: Passing redux store in props has been removed and does not do anything. To use a custom Redux store for specific components, create a custom React context with React.createContext(), and pass the context object to React-Redux's Provider and specific components like: . You may also pass a {context : MyContext} option to connect

I tried to pass the context as a parameter of shallow

const setup = (initialState={}) => {
    const store = storeFactory(initialState);
    const wrapper = shallow(
        <Input  />, { store }
        );
    console.log(wrapper.debug());

}

But then I get this logged to console

<ContextConsumer>
        [function bound renderWrappedComponent]
      </ContextConsumer>

and if I try to use then enzyme dive() method I get:

const setup = (initialState={}) => {
    const store = storeFactory(initialState);
    const wrapper = shallow(
        <Input  />, { store }
        ).dive();
    console.log(wrapper.debug());

}

Test suite failed to run

TypeError: ShallowWrapper::dive() can only be called on components

Which is the suggested way of doing it now? I know what the message says but before there was no need of wrapping the element into a Provider for jest/enzyme unit tests. Thank you very much!

like image 486
Juan Avatar asked Jan 07 '19 06:01

Juan


People also ask

How do you test for Jest and enzymes?

Both Jest and Enzyme are meant to test the react applications. Jest can be used with any other Javascript framework, but Enzyme is meant to run on react only. Jest can be used without Enzyme, and snapshots can be created and tested perfectly fine. But the Enzyme adds additional functionality to it.


1 Answers

shallow and dive doesn't work as expected in react-redux 6, so you may want to downgrade it to react-redux 5.0.7 for it to work.

But if you prefer using react-redux 6, then you might want to use mount instead. So, the above code can be rewritten as follows:

Input.test.js

import React from 'react'
import {Provider} from 'react-redux'
import {mount} from 'enzyme'

import {findByAttr, storeFactory} from '../test/testUtils'
import Input from './Input'

const setup = (initialState={}) => {
  const store = storeFactory(initialState)
  const wrapper = mount(<Provider store={store}><Input /></Provider>)
  console.log(wrapper.debug())
}

setup()

Console

    console.log src/Input.test.js:11
      <Provider store={{...}}>
        <Connect(Input)>
          <Input dispatch={[Function: dispatch]}>
            <div />
          </Input>
        </Connect(Input)>
      </Provider>

And there is another workaround if prefer testing the component as unconnected component, you can still use react-redux 6 and use shallow; code can be rewritten as follows:

Add export keyword to Input

Input.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

export class Input extends Component {
    render(){
        return <div />;
    }
}

const mapStateToProps = (state) => {
    return {};
}

export default connect(mapStateToProps)(Input);

Input.test.js

import React from 'react';
import { shallow } from 'enzyme';

import { findByTestAttr } from '../../../test/testUtils';
import { Input } from './Input';



const setup = (props={}) => {
    const wrapper = shallow(<Input {...props} />);
    console.log(wrapper.debug());

}

Console

<div />

Hope this helps!

like image 141
Pranav Avatar answered Oct 31 '22 23:10

Pranav