NativeBase icon indicating copy to clipboard operation
NativeBase copied to clipboard

A warning thrown with jest

Open tmhao2005 opened this issue 1 year ago • 13 comments

Description

There was a warning thrown as we ran test as following: TypeError: _reactNative.AppState.removeEventListener is not a function

CodeSandbox/Snack link

https://codesandbox.io/s/codesandbox-sse-example-forked-izm8zv?file=/sample.test.jsx

Steps to reproduce

  1. Visit the above codesanbox
  2. Run yarn test command then you will the see the warning

NativeBase Version

3.4.15

Platform

  • [ ] Android
  • [ ] CRA
  • [X] Expo
  • [ ] iOS
  • [ ] Next

Other Platform

No response

Additional Information

No response

tmhao2005 avatar Sep 16 '22 15:09 tmhao2005

my stack trace for this issue

    console.error
      Warning: Internal React error: Attempted to capture a commit phase error inside a detached tree. This indicates a bug in React. Likely causes include deleting the same fiber more than once, committing an already-finished tree, or an inconsistent return pointer.

      Error message:

      TypeError: _reactNative.AppState.removeEventListener is not a function
          at HybridProvider (/Users/xxx/node_modules/native-base/lib/commonjs/core/hybrid-overlay/HybridProvider.tsx:9:3)
          at ResponsiveQueryProvider (/Users/xxx/node_modules/native-base/lib/commonjs/utils/useResponsiveQuery/ResponsiveQueryProvider.tsx:20:12)
          at RNCSafeAreaProvider
          at Component (/Users/xxx/node_modules/react-native/jest/mockNativeComponent.js:17:18)
          at SafeAreaProvider (/Users/xxx/node_modules/react-native-safe-area-context/lib/commonjs/SafeAreaContext.tsx:35:3)
          at Provider (/Users/xxx/node_modules/native-base/lib/commonjs/utils/createContext.tsx:9:13)
          at NativeBaseProvider (/Users/xxx/node_modules/native-base/lib/commonjs/core/NativeBaseProvider.tsx:52:5)
          at TestingNativeBaseProvider (/Users/xxx/tests/ui/TestingNativeBaseProvider.tsx:5:3)

ahilles107 avatar Sep 18 '22 03:09 ahilles107

Same issue when updating from version^3.4.12 to ^3.4.16.

devpgcs avatar Sep 21 '22 00:09 devpgcs

Hey everyone, Thanks for reporting the issue. We'll fix it.

ankit-tailor avatar Sep 22 '22 07:09 ankit-tailor

Hey guys, I've created temporary patch for this issue:

File: /patches/native-base+3.4.16.patch

diff --git a/node_modules/native-base/lib/commonjs/core/color-mode/hooks.js b/node_modules/native-base/lib/commonjs/core/color-mode/hooks.js
index 8e28efe..68490c8 100644
--- a/node_modules/native-base/lib/commonjs/core/color-mode/hooks.js
+++ b/node_modules/native-base/lib/commonjs/core/color-mode/hooks.js
@@ -45,9 +45,9 @@ const useAppState = () => {
   const subscription = _react.default.useMemo(() => ({
     getCurrentValue: () => _reactNative.AppState.currentState,
     subscribe: callback => {
-      _reactNative.AppState.addEventListener('change', callback);
+      const sb = _reactNative.AppState.addEventListener('change', callback);
 
-      return () => _reactNative.AppState.removeEventListener('change', callback);
+      return () => sb.remove()
     }
   }), []);

After next release, just delete this patch.

MateuszRostkowski avatar Sep 25 '22 13:09 MateuszRostkowski

Any idea on witch version this fix will be introduced? The new version native-base 3.4.18 still dont fix this bug

Still getting this warning:

Warning: Internal React error: Attempted to capture a commit phase error inside a detached tree. This indicates a bug in React. Likely causes include deleting the same fiber more than once, committing an already-finished tree, or an inconsistent return pointer.

Error message:

TypeError: _reactNative.AppState.removeEventListener is not a function
    in HybridProvider (created by NativeBaseProvider)
    in ResponsiveQueryProvider (created by NativeBaseProvider)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by NativeBaseProvider)
    in NativeBaseConfigProviderProvider (created by NativeBaseProvider)
    in NativeBaseProvider (created by CameraView)
    in CameraView (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RNSScreen (created by AnimatedComponent)
    in AnimatedComponent
    in AnimatedComponentWrapper (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)

am2619015 avatar Oct 13 '22 16:10 am2619015

Getting the same error here when running tests with Jest

`console.error Warning: Internal React error: Attempted to capture a commit phase error inside a detached tree. This indicates a bug in React. Likely causes include deleting the same fiber more than once, committing an already-finished tree, or an inconsistent return pointer.

Error message:

TypeError: _reactNative.AppState.removeEventListener is not a function
    at children (\node_modules\native-base\lib\commonjs\core\hybrid-overlay\HybridProvider.tsx:9:3)
    at disableCSSMediaQueries (node_modules\native-base\lib\commonjs\utils\useResponsiveQuery\ResponsiveQueryProvider.tsx:20:12)
    at RNCSafeAreaProvider
    at RNCSafeAreaProvider (node_modules\react-native\jest\mockNativeComponent.js:17:18)
    at children (node_modules\react-native-safe-area-context\lib\commonjs\SafeAreaContext.tsx:35:3)
    at children (\node_modules\native-base\lib\commonjs\utils\createContext.tsx:9:13)
    at colorModeManager (\node_modules\native-base\lib\commonjs\core\NativeBaseProvider.tsx:52:5)`

austinrbrown01 avatar Oct 26 '22 18:10 austinrbrown01

I'm using native-base version 3.4.19 and still have the issue! Any updates on this?

maaliHasan avatar Jan 16 '23 11:01 maaliHasan

Yes, got the same error, please fix it 🙏

Update:

After updating to "native-base": "^3.4.25", jest no longer throws this error 👍

bebe84 avatar Jan 25 '23 11:01 bebe84

Hi The problem is still there but it has moved to a different file? Using 3.4.25

%s%s, TypeError: react_native_1.Dimensions.removeEventListener is not a function. (In 'react_native_1.Dimensions.removeEventListener('change', onChange)', 'react_native_1.Dimensions.removeEventListener' is undefined), in CheckinScreen (created by Screens)

node_modules/native-base/src/utils/useResponsiveQuery/common.ts

// The below implementation is taken from React Native's source and added a flag to conditionally attach/remove listeners
export const useDimensionsWithEnable = ({ enable }: { enable?: boolean }) => {
  const [dimensions, setDimensions] = React.useState(() =>
    Dimensions.get('window')
  );

  React.useEffect(() => {
    if (enable) {
      function handleChange({ window }: { window: ScaledSize }) {
        if (
          dimensions.width !== window.width ||
          dimensions.height !== window.height ||
          dimensions.scale !== window.scale ||
          dimensions.fontScale !== window.fontScale
        ) {
          setDimensions(window);
        }
      }
      Dimensions.addEventListener('change', handleChange);
      // We might have missed an update between calling `get` in render and
      // `addEventListener` in this handler, so we set it here. If there was
      // no change, React will filter out this update as a no-op.
      handleChange({ window: Dimensions.get('window') });

      return () => {
        Dimensions.removeEventListener('change', handleChange);  //  <- HERE! ####################
      };
    }
    return () => {};
  }, [dimensions, enable]);
  return dimensions;
};

dhcmega avatar Feb 15 '23 13:02 dhcmega

Version 3.4.28 still has this bug:

 console.error
    Warning: Internal React error: Attempted to capture a commit phase error inside a detached tree. This indicates a bug in React. Likely causes include deleting the same fiber more than once, committ
ing an already-finished tree, or an inconsistent return pointer.
    
    Error message:
    
    TypeError: Cannot read properties of undefined (reading 'remove')
        at HybridProvider (C:\personal_projects\clean-gta-clients\node_modules\native-base\lib\commonjs\core\hybrid-overlay\HybridProvider.tsx:9:3)
        at ResponsiveQueryProvider (C:\personal_projects\clean-gta-clients\node_modules\native-base\lib\commonjs\utils\useResponsiveQuery\ResponsiveQueryProvider.tsx:20:12)
        at RNCSafeAreaProvider
        at Component (C:\personal_projects\clean-gta-clients\node_modules\react-native\jest\mockNativeComponent.js:17:18)
        at SafeAreaProvider (C:\personal_projects\clean-gta-clients\node_modules\react-native-safe-area-context\src\SafeAreaContext.tsx:35:3)
        at Provider (C:\personal_projects\clean-gta-clients\node_modules\native-base\lib\commonjs\utils\createContext.tsx:9:13)
        at NativeBaseProvider (C:\personal_projects\clean-gta-clients\node_modules\native-base\lib\commonjs\core\NativeBaseProvider.tsx:52:5)

r3dm1ke avatar Apr 26 '23 19:04 r3dm1ke

Same here but with the badge component, im doing the following:

const TestComponent = (props: Record<string, unknown>) => <View {...props} />

jest.mock('native-base', () => ({
  ...jest.requireActual('native-base'),
  HamburgerIcon: () => <TestComponent testID="menu-icon" />,
  AddIcon: () => <TestComponent testID="add-icon" />,
}))

the error:

TypeError: Cannot read properties of undefined (reading 'Badge')

       7 | const TestComponent = (props: Record<string, unknown>) => <View {...props} />
       8 |
    >  9 | jest.mock('native-base', () => ({
         |                          ^
      10 |   ...jest.requireActual('native-base'),
      11 |   HamburgerIcon: () => <TestComponent testID="menu-icon" />,
      12 |   AddIcon: () => <TestComponent testID="add-icon" />,

      at Object.get [as Badge] (node_modules/native-base/lib/commonjs/index.js:95:24)
          at Function.assign (<anonymous>)
      at assign (app/test/ui/pages/HomePage/components/Header.test.tsx:9:26)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/primitives/Hidden/HiddenSSR.tsx:2:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/primitives/Hidden/index.tsx:9:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/primitives/index.ts:69:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/composites/Alert/AlertIcon.tsx:2:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/composites/Alert/index.tsx:1:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/components/composites/index.ts:13:1)
      at Object.<anonymous> (node_modules/native-base/lib/commonjs/index.tsx:1:1)

joaosousafranco avatar May 03 '23 20:05 joaosousafranco

Came across this and same issue as @joaosousafranco

jest.mock('native-base', () => {
  console.log(jest.requireActual('native-base'))
  return {
    ...jest.requireActual('native-base'),
    Collapse: (props: ICollapseProps) => {
      if (props.isOpen) {
        props.onAnimationEnd?.()
      }
      return props.isOpen ? props.children : null
    },
  }
})
TypeError: Cannot read properties of undefined (reading 'Badge')

ammanvedi avatar Nov 29 '23 19:11 ammanvedi

This solved the last two issues for me, from https://stackoverflow.com/a/70174052:

jest.requireActual inside of jest.mock seems like the way to go, however I needed to add a proxy instead of the object spread to prevent the type error Cannot read properties of undefined (reading ...) which can occur in certain import scenarios. This is the final result:

jest.mock('the-module-to-mock', () => {
  const actualModule = jest.requireActual('the-module-to-mock')

  return new Proxy(actualModule, {
    get: (target, property) => {
      switch (property) {
        // add cases for exports you want to mock
        // 👇👇👇
        case 'foo': {
          return jest.fn() // add `mockImplementation` etc
        }
        case 'bar': {
          return jest.fn()
        }
        // fallback to the original module
        default: {
          return target[property]
        }
      }
    },
  })
})

unpunnyfuns avatar Mar 08 '24 14:03 unpunnyfuns