1

I'm new to Jest / Enzyme and React, I am trying to test a container component.

My test is to check a prop matches with initialState.

This is my component

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

import { loadHomeAction } from '../../actions/home';

export class Home extends Component {
  componentDidMount() {
    this.props.dispatch(loadHomeAction());
  }

  render() {
    const { content, loading } = this.props.home;
    return (
      <div>
        <div>{loading && <p>Loading...</p>}</div>
        <div>{!loading && content.map(item => <p key={item.message}>{item.message}</p>)}</div>
      </div>
    );
  }
}

const mapStateToProps = ({ home }) => ({ home });

export default connect(mapStateToProps)(Home);

This are my tests

import React from 'react';
import { shallow, mount, configure } from 'enzyme';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';

import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import { createStore } from 'redux';

import App from '../../App';
import ConnectedHome, { Home } from './';

configure({ adapter: new Adapter() });

describe('HOME', () => {
  it('should render the DUMB component', () => {
    const { wrapper } = setup(defaultProps);
    expect(wrapper.length).toEqual(1);
  });

  it('should display the initial loading message', () => {
    const { wrapper } = setup(defaultProps);
    expect(wrapper.contains('Loading...')).toEqual(true);
  });
});

describe('CONNECTED HOME', () => {
  it('should render the SMART component', () => {
    const { container } = setup(defaultProps, initialState);
    expect(container.length).toEqual(1);
  });

  it('should match props with initial state', () => {
    const { container } = setup(defaultProps, initialState);
    expect(container.prop('home')).toEqual(initialState);
  });
});

const initialState = {
  content: [],
  loading: true,
  error: null
};

const defaultProps = {
  home: {
    content: [],
    loading: true,
    error: null
  },
  dispatch: () => {}
};

function setup(props = {}, state = {}) {
  const mockStore = configureStore();
  const store = mockStore(state);

  const wrapper = shallow(<Home {...props} />);
  const container = shallow(<ConnectedHome store={store} />);

  return { wrapper, container };
}

Currently, all tests are passing, except should match props with initial state - this test returns :

 CONNECTED HOME › should match props with initial state

    expect(received).toEqual(expected)

    Expected value to equal:
      {"content": [], "error": null, "loading": true}
    Received:
      undefined

    Difference:

      Comparing two different types of values. Expected object but received undefined.

On logging out the container I can see that home is undefined.

I am confused as to how / why this is not working.

I have been following along this blog post in an attempt to understand testing these connected components - https://medium.com/netscape/testing-a-react-redux-app-using-jest-and-enzyme-b349324803a9

EDIT

Ok, so I made some changes to my tests, my setup function now looks like

function setup(props = {}, state = {}) {
  const mockStore = configureStore();
  const store = mockStore(state);

  const wrapper = shallow(<Home {...props} />);
  const container = shallow(
    <Provider store={store}>
      <ConnectedHome />
    </Provider>
  );

  return { wrapper, container };
}

and my test looks like

  it('should match props with initial state', () => {
    const { container } = setup({}, initialState);

    expect(container.props().home).toEqual(initialState);
  });

Now I get this from the console

TypeError: Cannot destructure property `content` of 'undefined' or 'null'.

EDIT #2 By adding <ConnectedHome {...props} /> my test is now valid. However it feels like I have essentially said is 1 = 1.

Harry Blue
  • 4,202
  • 10
  • 39
  • 78

1 Answers1

0

In my opinion, you should not export a class just to make it testable. I have posted a neater solution as an answer to a similar question. Please have a look here: How to Unit Test React-Redux Connected Components?

Also, to answer your question, my recommendation is:

  1. Use snapshot testing to test the render method.
  2. Test the componentDidMount method separately.

How to test componentDidMount it? Here you go:

it('componentDidMount should dispatch loadHomeAction', () => {
  const wrapper = shallow(<Home dispatch={jest.fn()} />);
  wrapper.instance().componentDidMount();
  expect(wrapper.instance().props.dispatch).toBeCalledWith(loadHomeAction());
});
Rahul Gaba
  • 460
  • 4
  • 6