Unable to compare object containing functions bound to my class in React

Viewed 850

My class has the following constructor:

constructor() {
    super();

    this.togglePlay = this.togglePlay.bind(this);
    this.toggleMute = this.toggleMute.bind(this);
    this.toggleMaximize = this.toggleMaximize.bind(this);

    this.state = {
      play: false,
      mute: false,
      maximize: false,
      actions: {
        togglePlay: this.togglePlay,
        toggleMute: this.toggleMute,
        toggleMaximize: this.toggleMaximize
      }
    };
  }

In my test, I want to compare the state...

it('should have the correct state', () => {
    const wrapper = shallow(<Provider {...minProps} />);

    const expectedState = {
      play: false,
      mute: false,
      maximize: false,
      actions: {
        togglePlay: () => {},
        toggleMute: () => {},
        toggleMaximize: () => {}
      }
    };

    const actualState = wrapper.state();

    expect(expectedState).toEqual(actualState);
  });

When running the test, I receive the following error:

Expected value to equal:
  {"actions": {"toggleMaximize": [Function bound toggleMaximize], "toggleMute": [Function bound toggleMute], "togglePlay": [Function bound togglePlay]}, "maximize": false, "mute": false, "play": false}
Received:
  {"actions": {"toggleMaximize": [Function toggleMaximize], "toggleMute": [Function toggleMute], "togglePlay": [Function togglePlay]}, "maximize": false, "mute": false, "play": false}

The test fails due to the function comparisons. How can I get this test to pass?

1 Answers

Tests are failing because you're comparing different function references, in your mock you're creating anonymous functions and they explicitly need to be the ones bound on your constructor. One way to make this test pass would be to access the instance of the component and then access the bound functions and assign them to your mocked state:

it('should have the correct state', () => {
    const wrapper = shallow(<Provider {...minProps} />);

    const expectedState = {
      play: false,
      mute: false,
      maximize: false,
      actions: {
        togglePlay: wrapper.instance().togglePlay,
        toggleMute: wrapper.instance().toggleMute,
        toggleMaximize: wrapper.instance().toggleMaximize
      }
    };

    const actualState = wrapper.state();

    expect(expectedState).toEqual(actualState);
});

In this way, you're pointing to the same bound functions and their references.

An alternative solution that might as well work would be to make use of jest's expect.any(constructor)

it('should have the correct state', () => {
    const wrapper = shallow(<Provider {...minProps} />);

    const expectedState = {
      play: false,
      mute: false,
      maximize: false,
      actions: {
        togglePlay: expect.any(Function),
        toggleMute: expect.any(Function),
        toggleMaximize: expect.any(Function)
      }
    };

    const actualState = wrapper.state();

    expect(expectedState).toEqual(actualState);
});

Not 100% sure about this last idea though, hope it helps!

Related