kirillzyusko / react-native-keyboard-controller

Keyboard manager which works in identical way on both iOS and Android
https://kirillzyusko.github.io/react-native-keyboard-controller/
MIT License
1.77k stars 81 forks source link

Tests failing after upgrading from v0.75.4 to to v0.76.1 #675

Closed eduardo-santos-tribia closed 2 weeks ago

eduardo-santos-tribia commented 2 weeks ago

Description

Hi, I'm having multiple errors when running my Jest tests after upgrading to v0.76.1. Previously all of them were working fine in v0.75.4.

All errors show the same "ReferenceError: _ii is not defined" message:

Test suite failed to run

    ReferenceError: _ii is not defined

      1 | jest.mock('react-native-keyboard-controller', () =>
    > 2 |   require('react-native-keyboard-controller/jest'),
        |   ^
      3 | )
      4 |

Setup files for Test:

__mocks__/react-native-keyboard-controller.js

jest.mock('react-native-keyboard-controller', () =>
  require('react-native-keyboard-controller/jest'),
)

jest.config.js

module.exports = {
  preset: 'react-native',
  modulePaths: ['<rootDir>'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  setupFiles: [
    './__mocks__/react-native-keyboard-controller.js',
  ],
  setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
  transformIgnorePatterns: [
    'node_modules/(?!(jest-)?@?react-native|@react-native-community|@react-navigation|@pdftron|newrelic-react-native-agent)',
  ],
  moduleNameMapper: {
    '@storybook': '<rootDir>/__mocks__/storybook-react-native.js', // required to prevent storyboook import module error
    '\\.svg': '<rootDir>/__mocks__/svgMock.js',
  },
  testTimeout: 10000,
}

metro.config.js

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')

const path = require('path')

const defaultConfig = getDefaultConfig(__dirname)
const { assetExts, sourceExts } = defaultConfig.resolver

/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  transformer: {
    experimentalImportSupport: false,
    inlineRequires: true,
    babelTransformerPath: require.resolve(
      'react-native-svg-transformer/react-native',
    ),
  },
  resolver: {
    assetExts: assetExts.filter(ext => ext !== 'svg'),
    sourceExts: [...sourceExts, 'svg', 'mjs'],
  },
}

const mergedConfig = mergeConfig(defaultConfig, config)

// Storybook v8
const withStorybook = require('@storybook/react-native/metro/withStorybook')
const storybookOptions = {
  // Set to false to remove storybook specific options
  // you can also use a env variable to set this
  enabled: true,

  // set this to 'true' to remove storybook from the bundle when "enabled" is set to 'false'
  onDisabledRemoveStorybook: true,

  // Path to your storybook config
  configPath: path.resolve(__dirname, './.storybook'),
}

module.exports = withStorybook(mergedConfig, storybookOptions)

Steps to reproduce

  1. run the tests with the command yarn jest --config jest.config.js

React Native Version

0.76.1

Stacktrace or Logs

Test suite failed to run

    ReferenceError: _ii is not defined

      1 | jest.mock('react-native-keyboard-controller', () =>
    > 2 |   require('react-native-keyboard-controller/jest'),
        |   ^
      3 | )
      4 |

      at ii (node_modules/react-native/src/private/animated/NativeAnimatedHelper.js:100:38)
      at createNativeOperations (node_modules/react-native/src/private/animated/NativeAnimatedHelper.js:99:68)
      at Object.createNativeOperations (node_modules/react-native/src/private/animated/NativeAnimatedHelper.js:120:26)
      at Object.<anonymous> (node_modules/react-native/Libraries/Animated/AnimatedEvent.js:16:1)
      at Object.<anonymous> (node_modules/react-native/Libraries/Animated/AnimatedImplementation.js:23:1)
      at Object.<anonymous> (node_modules/react-native/Libraries/Animated/Animated.js:21:1)
      at Object.require [as Animated] (node_modules/react-native/index.js:215:12)
      at Object.Animated (node_modules/react-native-keyboard-controller/jest/index.js:5:19)
      at require (__mocks__/react-native-keyboard-controller.js:2:3)
      at Object.<anonymous> (src/providers/BaseProviders.tsx:2:1)
      at Object.<anonymous> (src/providers/index.tsx:1:1)
      at Object.<anonymous> (src/test/providers.tsx:2:1)
      at Object.<anonymous> (src/test/utils.ts:4:1)

Reproducer

This happens in my company project.

kirillzyusko commented 2 weeks ago

Hey @eduardo-santos-tribia

This is my config: https://github.com/kirillzyusko/react-native-keyboard-controller/blob/main/example/jestSetup.js

In this branch https://github.com/kirillzyusko/react-native-keyboard-controller/pull/656 tests don't fail 🤔

What is _ii in NativeAnimatedHelper? 🤔

Maybe you need to add:

jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); // or `react-native/src/private/animated/NativeAnimatedHelper.js`?

To your mock setup file?

eduardo-santos-tribia commented 2 weeks ago

Thanks for the reply @kirillzyusko . I've tried to add your setup to mine, but still not working. I also tried to mock the NativeAnimatedHelper as you suggested, didn't work too.

I'm not sure what _ii means, looks like it's not related to NativeAnimatedHelper. My guess is that something has changed for jest and tests in react-native v0.76.+ because my setup and tests were working just fine without any changes.

The error disappears if I change the mock from react-native-keyboard-controller to:

jest.mock('react-native-keyboard-controller', () => {})

I know this is wrong and I'll not do this, but looks like something from require('react-native-keyboard-controller/jest') is causing the issue with the new version of react-native.

kirillzyusko commented 2 weeks ago

I know this is wrong and I'll not do this, but looks like something from require('react-native-keyboard-controller/jest') is causing the issue with the new version of react-native.

Most likely the import of Animated module 🤷‍♂️ If you can provide a reproduction example then I'll look into it 👀

eduardo-santos-tribia commented 2 weeks ago

I guess the problem is not only the Animated module, but also importing and using the ScrollView component.

I've removed the Animated and ScrollView from react-native-keyboard-controller/jest/index.js file and it "works".

Do you have any idea why by using the ScrollView is also returning this _ii is not defined error?

react-native-keyboard-controller/jest/index.js

import { View, useWindowDimensions  } from "react-native";

const values = {
  animated: {
    progress: 0,
    height: 0,
  },
  reanimated: {
    progress: { value: 0 },
    height: { value: 0 },
  },
};
const focusedInput = {
  input: {
    value: {
      target: 1,
      parentScrollViewTarget: -1,
      layout: {
        x: 0,
        y: 0,
        width: 200,
        height: 40,
        absoluteX: 0,
        absoluteY: 100,
      },
    },
  },
};

const mock = {
  // hooks
  /// keyboard
  useKeyboardAnimation: jest.fn().mockReturnValue(values.animated),
  useReanimatedKeyboardAnimation: jest.fn().mockReturnValue(values.reanimated),
  useResizeMode: jest.fn(),
  useGenericKeyboardHandler: jest.fn(),
  useKeyboardHandler: jest.fn(),
  useKeyboardContext: jest.fn().mockReturnValue(values),
  /// input
  useReanimatedFocusedInput: jest.fn().mockReturnValue(focusedInput),
  useFocusedInputHandler: jest.fn(),
  /// module
  useKeyboardController: jest
    .fn()
    .mockReturnValue({ setEnabled: jest.fn(), enabled: true }),
  // internal
  useWindowDimensions,
  // modules
  KeyboardController: {
    setInputMode: jest.fn(),
    setDefaultMode: jest.fn(),
    dismiss: jest.fn(),
    setFocusTo: jest.fn(),
  },
  AndroidSoftInputModes: {
    SOFT_INPUT_ADJUST_NOTHING: 48,
    SOFT_INPUT_ADJUST_PAN: 32,
    SOFT_INPUT_ADJUST_RESIZE: 16,
    SOFT_INPUT_ADJUST_UNSPECIFIED: 0,
    SOFT_INPUT_IS_FORWARD_NAVIGATION: 256,
    SOFT_INPUT_MASK_ADJUST: 240,
    SOFT_INPUT_MASK_STATE: 15,
    SOFT_INPUT_MODE_CHANGED: 512,
    SOFT_INPUT_STATE_ALWAYS_HIDDEN: 3,
    SOFT_INPUT_STATE_ALWAYS_VISIBLE: 5,
    SOFT_INPUT_STATE_HIDDEN: 2,
    SOFT_INPUT_STATE_UNCHANGED: 1,
    SOFT_INPUT_STATE_UNSPECIFIED: 0,
    SOFT_INPUT_STATE_VISIBLE: 4,
  },
  KeyboardEvents: {
    addListener: jest.fn(() => ({ remove: jest.fn() })),
  },
  // views
  KeyboardControllerView: "KeyboardControllerView",
  KeyboardGestureArea: "KeyboardGestureArea",
  OverKeyboardView: "OverKeyboardView",
  // providers
  KeyboardProvider: "KeyboardProvider",
  // components
  KeyboardStickyView: View,
  KeyboardAvoidingView: View,
  KeyboardAwareScrollView: View,
  KeyboardToolbar: View,
};

module.exports = mock;
kirillzyusko commented 2 weeks ago

Do you have any idea why by using the ScrollView is also returning this _ii is not defined error?

Honestly, don't have any ideas 🤔 This is actually very strange, because theoretically if you have a test where you would test a component that uses ScrollView then it will fail as well, right?

eduardo-santos-tribia commented 2 weeks ago

Yes, you're right, any test with ScrollView would fail. I'll try to create a react-native cli project from scratch to test more and will update this issue when I have more info.

eduardo-santos-tribia commented 2 weeks ago

@kirillzyusko I've figured it out after creating a new react-native v0.76.1 project from scratch. My yarn.lock file was not updating some important stuff when I updated to v0.76.1. I had to delete my yarn.lock file and run yarn install again to create a new one with fresh dependency links. Don't know exactly why the normal update didn't update all necessary yarn.lock dependencies.

It's working now and has nothing to do with your library. Sorry for the inconvenience.

kirillzyusko commented 2 weeks ago

Awesome! Glad to hear you managed to fix it! 🔥