Search code examples
react-nativejestjsreact-animated

Jest: How can I mock out Animated loops?


I'm trying to run a snapshot test for an animated component which has the following animated code (called on componentDidMount):

animate() {
  Animated.loop(
    Animated.sequence([
      Animated.timing(this.state.pulseAnimation, {
        toValue: 1,
        duration: 1000,
        easing: Easing.in(Easing.ease)
      })
    ]),
    {
      iterations: this.props.totalNumPulses
    }
  ).start();
}

I've tried to mock Animated with the following:

  jest.mock('Animated', () => {
    return {
      loop: jest.fn(() => {
        return {
          start: jest.fn(),
          reset: jest.fn()
        };
      }),
      timing: jest.fn(() => {
        return {
          start: jest.fn(),
        };
      }),
      Value: jest.fn(() => {
        return {
          interpolate: jest.fn(),
        };
      }),
    };
  });

However, running the test results in this error:

TypeError: animation.reset is not a function

  54 |         iterations: this.props.totalNumPulses
  55 |       }
> 56 |     ).start();
  57 |   }
  58 | 

I've put the reset mocking in various places and checked the source code on the 'loop' method in React Native, but haven't had any luck successfully mocking it out. Has anyone successfully done this before?


Solution

  • The issue in your example is that you are completely replacing Animated with an object, rather than only replacing the methods you need to test.

    In the example below, I mock out parallel().start(callback) so that it immediately invokes the callback.

    // Tests/__mocks__/react-native.js
    
    export const Animated = {
      ...RN.Animated,
      parallel: () => ({
        // immediately invoke callback
        start: (cb: () => void) => cb()
      })
    };
    

    This allowed me to skip the animation and better test my start callback. You can use a similar approach for any property or subproperty of Animated!