Search code examples
reactjstestingreact-reduxjestjsenzyme

Error shallow Jest Enzyme React cannot find "store"


I have an interesting error in testing my component and don't now to fix(

I use jest, enzyme, react, redux.

In front end part of the app all is working correctly.

What error I can see now:

  ● Body Component › Body Component is loading › Is loading

    Invariant Violation: Could not find "store" in the context of "Connect(Body)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(Body) in connect options.

      25 |       };
      26 | 
    > 27 |       const BodyComponent = shallow(<Body />);
         |                             ^
      28 |     });
      29 |   });
      30 | });

my setupTests.js:

import Enzyme, { shallow, render, mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
//import toJson from 'enzyme-to-json'

// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() });

global.shallow = shallow;
global.render = render;
global.mount = mount;
//global.toJson = toJson

// Fail tests on any warning
console.error = message => {
  throw new Error(message);
};

My Test for component:

import React from "react";
import Body from "./Body";
import  { shallow, render, mount } from "enzyme";

describe("Body Component", () => {
  const props = {
    data: {
      time: undefined,
      products: [],
      filteredProducts: [],
      search: undefined
    }
  };

  describe("Body Component is loading", () => {
    it("Is loading", () => {
      const nextProps = {
        ...props,
        data: {
          products: [{}, {}],
          filteredProducts: [{ name: "sdffd" }, { name: "sdf" }],
          search: "sdf"
        }
      };

      const BodyComponent = shallow(<Body  />);
    });
  });
});

Also I can send my component:

import React from "react";
import ProductListItem from "./ProductListItem";
import { connect } from "react-redux";

const names = ["Seattle", "Bellevue", "Tacoma", "Puyallup"];

const Body = props => {
  const { products, filteredProducts, search } = props;
  console.log("FILTERED IN BODY", filteredProducts);
  console.log(products);
  return (
    <div className="main">
      {names.map(name => (
        <ProductListItem
          name={name}
          data={search ? filteredProducts : products}
          key={Math.random()}
        />
      ))}
    </div>
  );
};

const mapStatesToProps = state => {
  return {
    products: state.data.products,
    filteredProducts: state.data.filteredProducts,
    search: state.data.search
  };
};

export default connect(mapStatesToProps)(Body);

Can somebody tell me what I do incorrectly? I think something is wrong with {shallow}. Maybe someone knows how to fix this error?

Thank you so much!


Solution

  • You need to create a mocked store and pass it to the component as its props. connect(mapStatesToProps)(Body) statement will create a wrapped component. So you need to use wrapper.find(Body) of enzyme to get the Body stateless functional component.

    index.tsx:

    import React from 'react';
    import ProductListItem from './ProductListItem';
    import { connect } from 'react-redux';
    
    const names = ['Seattle', 'Bellevue', 'Tacoma', 'Puyallup'];
    
    export const Body = props => {
      const { products, filteredProducts, search } = props;
      console.log('FILTERED IN BODY', filteredProducts);
      console.log(products);
      return (
        <div className="main">
          {names.map(name => (
            <ProductListItem name={name} data={search ? filteredProducts : products} key={Math.random()} />
          ))}
        </div>
      );
    };
    
    const mapStatesToProps = state => {
      return {
        products: state.data.products,
        filteredProducts: state.data.filteredProducts,
        search: state.data.search
      };
    };
    
    export default connect(mapStatesToProps)(Body);
    
    

    index.spex.tsx:

    import React from 'react';
    import ConnectedBody, { Body } from './';
    import { shallow } from 'enzyme';
    import configureMockStore from 'redux-mock-store';
    
    const initialState = {
      data: {
        time: undefined,
        products: [],
        filteredProducts: [],
        search: undefined
      }
    };
    const mockStore = configureMockStore();
    const store = mockStore(initialState);
    
    describe('Body Component', () => {
      const props = {
        data: {
          time: undefined,
          products: [],
          filteredProducts: [],
          search: undefined
        }
      };
    
      describe('Body Component is loading', () => {
        it('Is loading', () => {
          const nextProps = {
            ...props,
            data: {
              products: [{}, {}],
              filteredProducts: [{ name: 'sdffd' }, { name: 'sdf' }],
              search: 'sdf'
            }
          };
    
          const wrapper = shallow(<ConnectedBody store={store} />);
          const BodyComponent = wrapper.find(Body);
          expect(BodyComponent.prop('products')).toEqual(props.data.products);
          expect(BodyComponent.prop('filteredProducts')).toEqual(props.data.filteredProducts);
          expect(BodyComponent.prop('search')).toEqual(props.data.search);
        });
      });
    });
    
    

    Unit test result:

    PASS  src/stackoverflow/57942218/index.spec.tsx
      Body Component
        Body Component is loading
          ✓ Is loading (37ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        4.771s, estimated 5s
    

    Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57942218