Search code examples
reactjsjestjscomponentsparent-childenzyme

Error when unit testing child React component


I have the following React Component:

import { getSeasonsalCode } from "./DiscountCodes.js";
import React, { Component } from "react";
import Rating from "./Rating.js";
import ReactDOM from "react-dom";
import "regenerator-runtime/runtime";

class Product extends Component {
  constructor(props) {
    super(props);
    this.handleEvent = this.handleEvent.bind(this);

    this.state = {
      name: "",
      rating: 0,
    };
  }

  setStarCount = (ct) => {
    this.setState({ rating: ct });
  };

  render() {
    var discount = getSeasonsalCode();
    return (
      <div>
        <span>{discount}</span>
        <Rating
          name="star_rating"
          size="2x"
          setStarCount={this.setStarCount}
        ></Rating>
      </div>
    );
  }
}

export default connect(mapStateToProps, null)(Product);

And the following product.test.js. It tests the Rating child component, which requires a callback function from the parent component to set the rating value:

import Rating from "../src/Rating.js";
import Product from "../src/Product.js";
import { shallow, mount } from "enzyme";
import expect from "expect";
import React from "react";
import { Provider } from "react-redux";
import { connect } from "react-redux";
import rootReducer from "../src/reducers/RootReducer.js";
import { createStore } from "redux";

describe("Product test suite", () => {
  it("set rating", () => {
    const store = createStore(
      rootReducer,
      window.__REDUX_DEVTOOLS_EXTENSION__ &&
        window.__REDUX_DEVTOOLS_EXTENSION__()
    );

    const rf_wrapper = mount(
      <Provider store={store}>
        <Product />
      </Provider>
    ).dive();
    const rf_instance = rf_wrapper.instance();
    const sr_wrapper = shallow(
      <Rating
        name="star_rating"
        size="2x"
        setStarCount={rf_instance.setStarCount()}
      />
    );

    sr_wrapper.find("#star4").simulate("click");
    expect(rf_wrapper.state("starcount")).toEqual(4);
  });
});

When I run the test, I get a TypeError saying discount is null or undefined at this line:

<span>{discount}</span>

What is causing this issue?


Solution

  • Had to make a few changes to my original test suite and this is what worked for me:

    import * as disc_module from '../src/DiscountCodes.js'
    
    describe("Product test suite", () => {
      it("set rating", () => {
        const store = createStore(
          rootReducer,
          window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
        );
        
        var disc_mock_obj = {
            "discount":{
                "expiration": new Date()
                "code": "OAABYT"
            }}
    
        jest
        .spyOn(disc_module, 'getSeasonsalCode')
        .mockImplementation(() => disc_mock_obj);
    
        //Got rid of call to dive() since it was not needed
        const rf_wrapper = mount( <Provider store={store}><Product></Product></Provider>);
        const prod_inst = rf_wrapper.find('Product');
        
        //Find clickable child component of Rating by id or any other unique attribute
        const child = rf_wrapper.find({'#star2'})   
        child.simulate('click')     
        expect(prod_inst.state('starcount')).toEqual(2);
      });
    });