Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jest TypeError: (0 , _computedWithAutoFillData.computedOffsetXValueWithAutoFillData) is not a function #651

Open
andresouza-maple opened this issue Jul 25, 2024 · 13 comments
Assignees
Labels
bug Something isn't working

Comments

@andresouza-maple
Copy link

andresouza-maple commented Jul 25, 2024

Describe the bug

My test is broken on version 4.0.0-alpha.12 but it works correctly on version 3.5.1.
It is throwing the following error when running it:

 FAIL  shared/component-library/Carousel/Carousel.test.tsx
  Carousel
    ✕ renders properly (55 ms)

  ● Carousel › renders properly

    TypeError: (0 , _computedWithAutoFillData.computedOffsetXValueWithAutoFillData) is not a function

      19 |     render(<Carousel data={data} renderItem={renderItem} width={200} />);
      20 |
    > 21 |     jest.advanceTimersByTime(2000);
         |          ^
      22 |
      23 |     screen.debug();

My test:

import React from 'react';
import { Text } from 'react-native';
import Carousel, { CarouselRenderItem } from 'react-native-reanimated-carousel';
import { render, screen } from '@testing-library/react-native';

const data = ['Slide 1', 'Slide 2', 'Slide 3'];

const renderItem: CarouselRenderItem<string> = ({ item }) => (
  <Text>{item}</Text>
);

describe('Carousel', () => {
  beforeEach(() => {
    jest.useFakeTimers();
    jest.clearAllMocks();
  });

  it('renders properly', async () => {
    render(<Carousel data={data} renderItem={renderItem} width={200} />);

    jest.advanceTimersByTime(2000);

    screen.debug();

    const card1 = await screen.findByText(data[0]);

    expect(card1).toBeDefined();
  });
});

To Reproduce
Steps to reproduce the behavior:

  1. Install the version 4.0.0-alpha.12;
  2. Run the test above;
  3. See error

Expected behavior
The carousel should render the slides in the DOM and the test should pass.
What I expect to see when I run screen.debug():

    <View
      style={
        {
          "flex": 1,
        }
      }
    >
      <View
        collapsable={false}
        forwardedRef={[Function anonymous]}
        handlerTag={1}
        handlerType="PanGestureHandler"
        jestAnimatedStyle={
          {
            "value": {},
          }
        }
        onGestureHandlerEvent={[Function anonymous]}
        onTouchEnd={[Function anonymous]}
        onTouchStart={[Function anonymous]}
        style={
          {
            "flexDirection": "row",
            "height": "100%",
            "overflow": "hidden",
            "width": 200,
          }
        }
      >
        <View
          collapsable={false}
          jestAnimatedStyle={
            {
              "value": {
                "transform": [
                  {
                    "translateX": 0,
                  },
                ],
              },
            }
          }
          style={
            {
              "height": "100%",
              "position": "absolute",
              "transform": [
                {
                  "translateX": 0,
                },
              ],
              "width": 200,
            }
          }
          testID="__CAROUSEL_ITEM_0_READY__"
        >
          <Text>
            Slide 1
          </Text>
        </View>
        <View
          collapsable={false}
          jestAnimatedStyle={
            {
              "value": {
                "transform": [
                  {
                    "translateX": 200,
                  },
                ],
              },
            }
          }
          style={
            {
              "height": "100%",
              "position": "absolute",
              "transform": [
                {
                  "translateX": 200,
                },
              ],
              "width": 200,
            }
          }
          testID="__CAROUSEL_ITEM_1_READY__"
        >
          <Text>
            Slide 2
          </Text>
        </View>
        <View
          collapsable={false}
          jestAnimatedStyle={
            {
              "value": {
                "transform": [
                  {
                    "translateX": -200,
                  },
                ],
              },
            }
          }
          style={
            {
              "height": "100%",
              "position": "absolute",
              "transform": [
                {
                  "translateX": -200,
                },
              ],
              "width": 200,
            }
          }
          testID="__CAROUSEL_ITEM_2_READY__"
        >
          <Text>
            Slide 3
          </Text>
        </View>
      </View>
    </View>

Versions:

  • react: v18.2.0
  • react-native: v0.71.14
  • react-native-reanimated: v3.14.0
  • react-native-reanimated-carousel: v4.0.0-alpha.12
  • react-native-gesture-handler: v2.16.0

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6] N/A
  • OS: [e.g. iOS8.1] N/A
  • Browser [e.g. stock browser, safari] N/A
  • Version [e.g. 22] N/A
  • iTerm2: Build 3.5.3

Additional context
I know version 4.0.0 is still in Alpha, but I thought you wanted to know about this issue before the release.

@andresouza-maple andresouza-maple added the bug Something isn't working label Jul 25, 2024
Copy link

dosubot bot commented Jul 25, 2024

Hey @andresouza-maple! I'm here to help you with any bugs, questions, or contributions you have for the repository. Let me know how I can assist you!

The issue you're encountering with the test breaking on version 4.0.0-alpha.12 of react-native-reanimated-carousel but working correctly on version 3.5.1 is likely due to changes introduced in the newer version. Specifically, in 4.0.0-alpha.12, there was a fix for an issue where endWithSpring used outdated data from useSharedValue after onGestureEnd, causing incorrect carousel behavior on direction reversal [1].

To resolve the error TypeError: (0 , _computedWithAutoFillData.computedOffsetXValueWithAutoFillData) is not a function, ensure that the function computedOffsetXValueWithAutoFillData is properly defined and exported before it is used. Here is the relevant part of the code:

export function computedOffsetXValueWithAutoFillData(
  params: BaseParams<{
    rawDataLength: number
    value: number
    size: number
  }>,
) {
  "worklet";

  const { rawDataLength, value, size, loop, autoFillData } = params;

  if (isAutoFillData({ loop, autoFillData })) {
    switch (rawDataLength) {
      case SINGLE_ITEM:
        return value % size;
      case DOUBLE_ITEM:
        return value % (size * 2);
    }
  }

  return value;
}

Ensure that this function is not being referenced before its definition in your code. If the error persists, it might be due to a circular dependency or an import issue. Double-check your import statements and the order of your function definitions to ensure there are no circular dependencies [2].

Additionally, make sure you have the necessary Babel plugin configuration in your babel.config.js:

module.exports = {
  presets: [
    ...
  ],
  plugins: [
    ...
    'react-native-reanimated/plugin',
  ],
};

After editing your Babel plugin, try running npm start -- --reset-cache or yarn start --reset-cache [3].

If these steps do not resolve the issue, you may need to review and possibly update your test logic to ensure it aligns with the new behavior of the carousel component in version 4.0.0-alpha.12 [1].

To continue talking to Dosu, mention @dosu.

@andresouza-maple
Copy link
Author

Answering the bot above, I don't think the changes in the version 4.0.0-alpha.12 are causing it because I had the same issue with the version 4.0.0-alpha.0. I wonder if it is related to the new gesture handler API implemented in the v4.0.0-alpha.0

Copy link

dosubot bot commented Jul 25, 2024

The issue you're encountering is likely related to the new gesture handler API introduced in version 4.0.0-alpha.0 of react-native-reanimated-carousel. This version requires react-native-gesture-handler to be >=2.9.0 and replaces the usage of useAnimatedGestureHandler with the new gesture handler API [1].

To address this, ensure that all your dependencies are compatible with the new version of the carousel. Specifically, verify that react-native-gesture-handler is updated to >=2.9.0. Additionally, you might need to adjust your test setup to accommodate the changes in the internal implementation of the carousel component.

Here is an updated version of your test code that includes a check for the new gesture handler API:

import React from 'react';
import { Text } from 'react-native';
import Carousel, { CarouselRenderItem } from 'react-native-reanimated-carousel';
import { render, screen } from '@testing-library/react-native';

const data = ['Slide 1', 'Slide 2', 'Slide 3'];

const renderItem: CarouselRenderItem<string> = ({ item }) => (
  <Text>{item}</Text>
);

describe('Carousel', () => {
  beforeEach(() => {
    jest.useFakeTimers();
    jest.clearAllMocks();
  });

  it('renders properly', async () => {
    render(<Carousel data={data} renderItem={renderItem} width={200} />);

    jest.advanceTimersByTime(2000);

    screen.debug();

    const card1 = await screen.findByText(data[0]);

    expect(card1).toBeDefined();
  });
});

If the issue persists, you might need to investigate further into the specific changes introduced in the new version of the carousel and adjust your test setup accordingly.

To continue talking to Dosu, mention @dosu.

@jiroscripts
Copy link
Contributor

Any news on this issue ? I have the same here

@steviec
Copy link

steviec commented Aug 14, 2024

I was able to fix it by adding this in my jest.setup.ts:

jest.mock('react-native-reanimated', () =>
  require('react-native-reanimated/mock'),
);

@jiroscripts
Copy link
Contributor

I have the same issue without Jest. Did I miss something ?

@andresouza-maple
Copy link
Author

I was able to fix it by adding this in my jest.setup.ts:

jest.mock('react-native-reanimated', () =>
  require('react-native-reanimated/mock'),
);

I tried this, and the error is gone, but I still don't get the Expected Behaviour. When I call screen.debug(), I don't see the slides in the DOM, just an empty View that I guess is the Carousel container:

    <View
      style={
        {
          "flex": 1,
        }
      }
    >
      <View
        collapsable={false}
        onTouchEnd={[Function anonymous]}
        onTouchStart={[Function anonymous]}
        style={
          [
            {
              "overflow": "hidden",
            },
            {
              "height": "100%",
              "width": 200,
            },
            {},
            {
              "flexDirection": "row",
            },
          ]
        }
      />
    </View>

@steviec
Copy link

steviec commented Aug 26, 2024

@andresouza-maple You're right. My fix just makes the error go away, but it doesn't make the carousel component behave correctly.

@jiroscripts
Copy link
Contributor

I finally resolved the bug on my side with NX 19 and RN 0.73.8

I removed some lines in metro.config.js

  resolver: {
       ...
  -      resolverMainFields: ['sbmodern', 'browser', 'main'],
  -      blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]),
  }

I added some plugns in babel.config.js

    plugins: [
        '@babel/plugin-transform-flow-strip-types',
        '@babel/plugin-transform-class-properties',
        '@babel/plugin-transform-private-methods',
        '@babel/plugin-transform-private-property-in-object',
        'react-native-reanimated/plugin',
    ],

My package.json for plugins versions:

        "@babel/plugin-transform-class-properties": "^7.21.0",
        "@babel/plugin-transform-flow-strip-types": "^7.25.2",
        "@babel/plugin-transform-private-methods": "^7.21.0",
        "@babel/plugin-transform-private-property-in-object": "^7.21.0",

Hope it helps :)

@mmeissonnier
Copy link

Hey,
i use this mock. It doesn't reproduce complex behavior, but it renders all items correctly. You just have to create a react-native-reanimated-carousel.tsx file in the __mocks__ folder. Hope this helps.

import React, { forwardRef, useEffect, useImperativeHandle } from 'react'
import { FlatList, ListRenderItem } from 'react-native'
import { TCarouselProps } from 'react-native-reanimated-carousel'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default forwardRef<
  any,
  Omit<TCarouselProps, 'onProgressChange'> & {
    onProgressChange: (offsetProgress: number, absoluteProgress: number) => void
  }
>(function Carousel(
  { renderItem, data, testID, width, height, onProgressChange, defaultIndex = 0 },
  ref
) {
  useImperativeHandle(ref, () => ({
    next: jest.fn(),
    prev: jest.fn(),
    scrollTo: ({ index }: { index: number }) => {
      onProgressChange(0, index)
    },
    getCurrentIndex: jest.fn(),
  }))

  useEffect(() => {
    if (defaultIndex > 0) {
      onProgressChange(0, defaultIndex)
    }
  }, [defaultIndex, onProgressChange])

  return (
    <FlatList
      ref={ref}
      testID={testID}
      renderItem={renderItem as unknown as ListRenderItem<unknown>}
      data={data}
      keyExtractor={(_, index) => index.toString()}
      style={{ width, height }}
    />
  )
})

@professorkolik
Copy link

@mmeissonnier thank you, your mock worked for me.

@dohooo is there any chance you can put mock into library, which can be maintained?

@andresouza-maple
Copy link
Author

@mmeissonnier the mock worked for me as well. Thanks!
I guess this will do the work for now, until we have this fixed in the v4.0.0

@woo-industries
Copy link

@mmeissonnier Legend !! thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants