DavidWorldpeace
DavidWorldpeace

Reputation: 549

React: how to test if method is called when updating props?

I'm trying to write a test which checks if a method is called when updating the props of the component.

This is the component (removed unnecessary stuff):

import React from 'react';
import styled from 'styled-components';

const Video = styled.video`
  display: block;
  width: 100%;
`;

export default class VideoPlayer extends React.Component {
  componentWillReceiveProps(nextProps) {
    if (this.props.isPaused !== nextProps.isPaused) {
      this.togglePlayPause(nextProps.isPaused);
    }
  }

  togglePlayPause(isPaused) {
    if (isPaused) {
      this.video.pause();
    } else {
      this.video.play();
    }
  }

  render() {
    return (
      <Video />
    );
  }
}

This is the test I've written:

import React from 'react';
import Enzyme, { mount } from 'enzyme';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';
import 'jest-styled-components';
import sinon from 'sinon';
import VideoPlayer from './../src/app/components/VideoPlayer/VideoPlayer';

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

test('Checks if togglePlayPause gets called', () => {
  const spy = sinon.spy(VideoPlayer.prototype, 'togglePlayPause');
  const Component = mount(<VideoPlayer videoURL="http://localhost:3001/vid/local-video.mp4" volume={100} isPaused={false} />);

  Component.setProps({ isPaused: true });
  expect(spy).toBeCalled();
});

However, when I run this test I get the following error:

expect(jest.fn())[.not].toBeCalled()

jest.fn() value must be a mock function or spy.
Received:
  function: [Function proxy]

  21 |
  22 |   Component.setProps({ isPaused: true });
> 23 |   expect(spy).toBeCalled();
  24 | });
  25 |

  at Object.<anonymous> (__tests__/VideoPlayer.react-test.js:23:15)

How can I write a test which checks if a method is called when the props are updated? Been googling for hours now, can't find any articles/tutorials/help/issues on this.

Don't hesitate to ask for additional information. Thanks!

Upvotes: 0

Views: 1211

Answers (2)

Edgar Abgaryan
Edgar Abgaryan

Reputation: 137

const createTestFunction = (yourCheckFunction) => {
  let amountOfCalls = 0;
  const testFunction = function() {
    amountOfCalls++;
    return yourCheckFunction.apply(this, arguments);
  };

  testFunction.getCalls = (() => amountOfCalls);

  return testFunction;
}

const testabelFunction = createTestFunction(Math.max);

testabelFunction.getCalls(); // 0

testabelFunction(1, 3, 2) // Math.max(1,3,2) -> 3

testabelFunction.getCalls(); // 1

Upvotes: 1

alechill
alechill

Reputation: 4522

You are passing a sinon spy to an assertion that expects a Jest spy. Jest's built in assertions know how to check its own mocks and spies, but it does not know how to do that with spy's from another library

Either use a Jest spy

const spy = jest.spyOn(VideoPlayer.prototype, 'togglePlayPause')
//...
expect(spy).toBeCalled()

Or assert on the sinon spy's properties directly

const spy = sinon.spy(VideoPlayer.prototype, 'togglePlayPause')
//...
expect(spy.calledOnce).toBe(true)

Upvotes: 2

Related Questions