react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Animated.createAnimatedComponent mock returns undefined instead of the Component when running jest

Open mahdieh-dev opened this issue 1 year ago • 1 comments

Description

I have a screen that contains an animated FlatList and I need to use ref for it, so I created my Animated list like below:

const AnimatedList = Animated.createAnimatedComponent(FlatList)

I need to test an element in this list is working fine, however, I cannot get the test running. Because it fails on my AnimatedList component with the following error:

console.error
    Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

I have mocked the react-native-reanimated component like this:

jest.mock('react-native-reanimated', () => {
  return {
    ...jest.requireMock('react-native-reanimated/mock'),
    useSharedValue: jest.fn,
    useAnimatedStyle: jest.fn,
  };
});

So I tried to log what is really inside my AnimatedList and got undefined. I tried to log Animated.createAnimatedComponent itself since I knew it exists in the package mock, and this is what is logged in the console:

 [Function: createAnimatedComponent] {
      _isMockFunction: true,
      getMockImplementation: [Function (anonymous)],
      mock: [Getter/Setter],
      mockClear: [Function (anonymous)],
      mockReset: [Function (anonymous)],
      mockRestore: [Function (anonymous)],
      mockReturnValueOnce: [Function (anonymous)],
      mockResolvedValueOnce: [Function (anonymous)],
      mockRejectedValueOnce: [Function (anonymous)],
      mockReturnValue: [Function (anonymous)],
      mockResolvedValue: [Function (anonymous)],
      mockRejectedValue: [Function (anonymous)],
      mockImplementationOnce: [Function (anonymous)],
      mockImplementation: [Function (anonymous)],
      mockReturnThis: [Function (anonymous)],
      mockName: [Function (anonymous)],
      getMockName: [Function (anonymous)]
    }

But when I log Animated.createAnimatedComponent(FlatList) it returns undefined. I tried to mock this function after the line ...jest.requireMock('react-native-reanimated/mock'), like (Component) => Component but it didn't work. So I tried to remove this line ...jest.requireMock('react-native-reanimated/mock'), and try to mock the required components and functions myself. This time it worked and in the logs, I could see that the component is returned by the Animated.createAnimatedComponent(FlatList), however, the test failed again, because other reanimated components were not mocked correctly. So I believe the issue should be inside the mock file, I couldn't figure out what is the reason it is not returning undefined instead of the component. I would be grateful if you help me fix this issue, it took me 2 days but has not been resolved yet.

Steps to reproduce

  1. Clone the provided repo
  2. Run npm i to install the dependencies
  3. Run npx jest (it will fail on AnimatedList component and I provided the logs I described above which you can check on the console)

Snack or a link to a repository

https://github.com/mshavandi/reanimatedMockIssueWithJest

Reanimated version

3.0.0-rc.1

React Native version

0.68.2

Platforms

Android

JavaScript runtime

No response

Workflow

No response

Architecture

No response

Build type

No response

Device

No response

Device model

No response

Acknowledgements

Yes

mahdieh-dev avatar Aug 17 '22 17:08 mahdieh-dev

For those who need a solution to this problem: I ended up mocking the reanimated package like this:

jest.mock('react-native-reanimated', () => {
  return {
    ...jest.requireMock('react-native-reanimated/mock'),
    useSharedValue: jest.fn,
    useAnimatedStyle: jest.fn,
    useAnimatedRef: () => ({ current: null }),
    default: {
      ...jest.requireMock('react-native-reanimated/mock').default,
      createAnimatedComponent: (Component) => Component,
    },
  };
});

This solves the issue with Animated components, and also some features related to reanimated V2

Update:

Actually, the problem was with the requireMock, it works with requireActual. Changing the mock to:

jest.mock('react-native-reanimated', () => {
  return {
    ...jest.requireActual('react-native-reanimated/mock'),
    ...jest.requireActual('react-native-reanimated/src/reanimated2/mock'),
  };
});

solves the problem.

mahdieh-dev avatar Sep 02 '22 07:09 mahdieh-dev

For those who need a solution to this problem: I ended up mocking the reanimated package like this:

jest.mock('react-native-reanimated', () => {
  return {
    ...jest.requireMock('react-native-reanimated/mock'),
    useSharedValue: jest.fn,
    useAnimatedStyle: jest.fn,
    useAnimatedRef: () => ({ current: null }),
    default: {
      ...jest.requireMock('react-native-reanimated/mock').default,
      createAnimatedComponent: (Component) => Component,
    },
  };
});

This solves the issue with Animated components, and also some features related to reanimated V2

Update:

Actually, the problem was with the requireMock, it works with requireActual. Changing the mock to:

jest.mock('react-native-reanimated', () => {
  return {
    ...jest.requireActual('react-native-reanimated/mock'),
    ...jest.requireActual('react-native-reanimated/src/reanimated2/mock'),
  };
});

solves the problem.

I have the same problem, but this mock doesn't work for me.

Invariant Violation:createAnimatedComponent` does not support stateless functional components; use a class component instead.

  46 | }
  47 |
> 48 | const AnimatedColumn = Animated.createAnimatedComponent(Column);
     |                                 ^
  49 | const defaultAnimationDuration = 0;
  50 |
  51 | const Overlay: ForwardRefRenderFunction<OverlayRef, OverlayProps> = (

  at invariant (node_modules/invariant/invariant.js:40:15)
  at Object.createAnimatedComponent (node_modules/react-native/Libraries/Animated/src/createAnimatedComponent.js:28:3)`

i`m tryng testing with a styled component library, maybe my error is because styled components doesnt works with animated components, but idk.

Michelalmeidasilva avatar Nov 04 '22 14:11 Michelalmeidasilva