Closed fbartho closed 5 years ago
To add on, mocking react-native-gesture-handler
doesn't work either.
Here's how it looks like.
import 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
import App from '../App';
global.fetch = jest.fn(() => new Promise(resolve => resolve()));
jest.mock('react-native-gesture-handler', () => {});
it('renders correctly', () => {
const tree = renderer.create(<App />).toJSON();
expect(tree).toMatchSnapshot();
});
I'm not sure if it's good or not but I made this running with:
jest.mock('NativeModules', () => ({
UIManager: {
RCTView: () => {},
},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {},
},
}))
after mocking a new error ocurred
Update to @dsznajder workaround:
RCTView actually should return an empty object else you'll run into TypeError: Cannot read property 'directEventTypes' of undefined
Next issue you'll run into is Invariant Violation: Native module cannot be null.
. Add the KeyboardObserver
mock to work around that one.
That leaves us with this patch work:
jest.mock("NativeModules", () => ({
UIManager: {
RCTView: () => ({
directEventTypes: {}
})
},
KeyboardObserver: {},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {}
}
}))
What I noticed in addition was that version 1.0.9
was working. But I had to upgrade to 1.0.12 in order use latest DrawerLayout
, after this jest tests started crashing with:
TypeError: Cannot read property 'forceTouchAvailable' of undefined
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:422:1)
at Object.<anonymous> (node_modules/react-native-gesture-handler/Swipeable.js:11:23)
at Object.<anonymous> (node_modules/react-native-gesture-handler/index.js:1:525)
@codeflowee You can mock forceTouchAvailable
as rest of nativeModules
jest.mock('NativeModules', () => ({
PlatformConstants: {
forceTouchAvailable: false,
},
}))
Any updates on this issue? These workarounds didn't work for me. After mocking I get similar error: Cannot read property propTypes of undefined.
If anyone here have some experience in writing these mocks, I'll be happy to merge them
How about this one?
● rendering test › encountered a declaration exception
TypeError: Cannot read property 'directEventTypes' of undefined
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:47:19)
at Object.<anonymous> (node_modules/react-native-gesture-handler/Swipeable.js:11:23)
at Object.<anonymous> (node_modules/react-native-gesture-handler/index.js:1:440)
Update: Nevermind, above solutions works right. Here is what I've done.
NativeModules.RNGestureHandlerModule = {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
forceTouchAvailable: jest.fn(),
State: {},
Directions: {}
};
NativeModules.PlatformConstants = {
forceTouchAvailable: false,
};
NativeModules.UIManager = {
RCTView: () => ({
directEventTypes: {},
}),
};
@hyochan, can I ask which file are you putting this code in?
I managed to fix this issue for me by creating a setup file called jestSetup.js
with the following content:
import { NativeModules as RNNativeModules } from "react-native";
RNNativeModules.UIManager = RNNativeModules.UIManager || {};
RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {};
RNNativeModules.RNGestureHandlerModule = RNNativeModules.RNGestureHandlerModule || {
State: { BEGAN: "BEGAN", FAILED: "FAILED", ACTIVE: "ACTIVE", END: "END" },
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
};
RNNativeModules.PlatformConstants = RNNativeModules.PlatformConstants || {
forceTouchAvailable: false
};
Which is a combination of the workaround posted by others in this issue.
I then added
"setupFiles": [
"./jestSetup.js"
]
to the jest configuration section in package.json
.
Hi @Lythenas ,
I tried your configuration above.It returned me this TypeError: Cannot set property RCTView of #<Object> which has only a getter
.
@linux08 I don't know why you get that error. I'm also quite new to react-native. Maybe someone else can help.
For reference here is the jest section of my package.json:
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"transformIgnorePatterns": [
"/node_modules/(?!react-native|native-base-shoutem-theme|react-navigation-stack|@react-navigation|react-navigation-fluid-transitions)"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"setupFiles": [
"./jestSetup.js"
]
}
Hilarious... I managed to mock it without changing a setup file.
Folder structure:
__mocks__
- react-native-gesture-handler.js
- react-native-gesture-handler/
-- Swipeable.js
react-native-gesture-handler.js is empty!
Swipeable.js
import React from "react";
const RN = require("react-native");
class Swipeable extends React.Component {
render() {
return <RN.View>{this.props.children}</RN.View>;
}
}
export default Swipeable;
package.json
"enzyme": "3.6.0",
"enzyme-adapter-react-16": "1.5.0",
"enzyme-to-json": "3.3.4",
"jest": "23.6.0",
"react-native-mock-render": "0.1.2",
"react-test-renderer": "16.4.1",
The workarounds above didn't solve my problem for components where I'm using react-navigation's own FlatList component (strongly recommend it). As a temporary solution I also added
jest.mock('react-native/Libraries/Lists/FlatList', () => 'FlatList');
to these components to use the default RN FlatList component instead to make the tests pass.
I tried all the solutions , and keep getting one error after other.
at starting i got:
● Test suite failed to run
TypeError: Cannot read property 'State' of undefined
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:54:36)
at Object.<anonymous> (node_modules/react-native-gesture-handler/Swipeable.js:11:23)
at Object.<anonymous> (node_modules/react-native-gesture-handler/index.js:1:525)
After trying @jeffmwells I got @rsmelo92 's error as above.
After trying @Lythenas i got :
/Users/ravipiyush/testing/RNTesting/node_modules/@react-navigation/native/dist/withOrientation.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from 'react';
SyntaxError: Unexpected identifier
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/ScriptTransformer.js:440:17)
at Object.get withOrientation [as withOrientation] (node_modules/@react-navigation/native/dist/index.js:17:12)
at Object.<anonymous> (node_modules/react-navigation-stack/dist/views/Header/Header.js:538:13
Its been hours . Is there a way to get jest working with react-native-gesture-handler.
Hi all. This seems like a very important problem for us to solve. I saw many people reporting here, would any of you have time to prepare a minimal repo on github that'd illustrate the problem. It would help us a ton and allow for a much quicker resolution of this issue
Hi @kmagiera . I have a similar error to others. I created a simple repo on GitHub: https://github.com/mehranabi/rn-gh-error , when I try to run the test in that project, I get an error (Not the same as my main project but a similar one). Check it out!
hey @kmagiera , I also created a repo . not sure if the errors are exactly same with @mehranabi . https://github.com/Kida007/RnghTesting Thanks
Hi everyone, Actually this mock fixes react-native-gesture-handler
problems for me:
jest.mock('NativeModules', () => ({
UIManager: {
RCTView: () => ({
directEventTypes: {},
}),
},
KeyboardObserver: {},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {},
},
PlatformConstants: {
forceTouchAvailable: false,
},
}))
But after this i get this error, and think it's releated to react-navigation
...:
D:\Mehran\Projects\ReactNative\RNGestureHandlerError\node_modules\@react-navigation\native\dist\withOrientation.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from 'react';
^^^^^
SyntaxError: Unexpected identifier
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/ScriptTransformer.js:440:17)
at Object.get withOrientation [as withOrientation] (node_modules/@react-navigation/native/dist/index.js:17:12)
at Object.<anonymous> (node_modules/react-navigation-stack/dist/views/Header/Header.js:538:16)
I think that
UIManager: {
RCTView: () => ({
directEventTypes: {},
}),
},
is no longer needed. Also I faced bug like @mehranabi, but after removing react-navigation it was no longer present, so I don't know whether it's because of RNGH. / @brentvatne
@osdnk have you used Swipeable component of RNGH after removing react-navigation ?
Yes, it works. Built our example app without react-navigation
with swipeable
screen instead of App.js
and it works 🤷♂️ .
@osdnk You were Right ! after removing React-Navigation
and mocking Directions and forceTouchAvailable , the Swipeable Errors Went away. Great Deduction.
Edit: Created a Branch for this . https://github.com/Kida007/RnghTesting/tree/v2
@Kida007 @osdnk
Hey everyone, I added this to transformIgnorePatterns
and finally my test passed:
@react-navigation/.*
jset
in package.json
:
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-navigation|react-navigation-redux-helpers|@react-navigation/.*)"
]
},
Nice, nice.
I hope I will prepare some repo with example how to make tests in jest
with RNGH soon. Or maybe some of you have already done it and I could share it somewhere in docs? 😄 Would be so grateful!
the expo jest preset might be useful for people to reference here:
@brentvatne Hm, I'm not sure if I want to mock it on this level. I don't have strong use case for it, but I believe that we should not mock anything but for native module.
yeah you're probably right @osdnk, i'll replace that with whatever else people come up with that works :)
This is related to issue I've posted in react-native
. I will share my jest.config.js and jestSetup.js for those who's suffering with current issue (@carmenchapa).
Thank you @brentvatne for sharing useful links with me in https://github.com/react-navigation/react-navigation/issues/5662 and https://github.com/kmagiera/react-native-gesture-handler/issues/344#issuecomment-470306357 , that helped me solve my problem... And now, my repo https://github.com/mehranabi/rn-gh-error is working ... :)
If someone is still facing this, I solved with this:
package.json
...
"setupFiles": [
"./jest.setup.js"
]
jest.setup.js
jest.mock('react-native-gesture-handler', () => {
const View = require('react-native/Libraries/Components/View/View');
return {
Swipeable: View,
DrawerLayout: View,
State: {},
ScrollView: View,
Slider: View,
Switch: View,
TextInput: View,
ToolbarAndroid: View,
ViewPagerAndroid: View,
DrawerLayoutAndroid: View,
WebView: View,
NativeViewGestureHandler: View,
TapGestureHandler: View,
FlingGestureHandler: View,
ForceTouchGestureHandler: View,
LongPressGestureHandler: View,
PanGestureHandler: View,
PinchGestureHandler: View,
RotationGestureHandler: View,
/* Buttons */
RawButton: View,
BaseButton: View,
RectButton: View,
BorderlessButton: View,
/* Other */
FlatList: View,
gestureHandlerRootHOC: jest.fn(),
Directions: {},
};
});
taken from here expo/jest-expo
After all the suggested mocking, I still ran into this error.
TypeError: Cannot read property 'Direction' of undefined
at Object.<anonymous> (node_modules/react-native-gesture-handler/Directions.js:5:24)
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:22:42)
at Object.<anonymous> (node_modules/react-native-gesture-handler/Swipeable.js:10:23)
at Object.<anonymous> (node_modules/react-native-gesture-handler/index.js:1:440)
jest.mock('NativeModules', () => ({
UIManager: {
RCTView: () => ({
directEventTypes: {},
}),
},
KeyboardObserver: {},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Direction: {}, // this is Direction not Directions right? Tried both and didn't work either
},
}));
after trying many suggestions and getting the most variable errors i did what @matheushf said and finally got it solved.
jest.mock('NativeModules', () => ({
... this will mock EVERY native module!
}))
I think the problem with mocking NativeModules is that EVERY native module is mocked! Thus after the tests pass a RNGH related line it will fail at the next line related to another native module p.ex. Keyboard, AsyncStorage, UIManager, ... This is maybe not what you want to archive.
Instead replace single modules like suggested by @fbartho:
import { NativeModules } from "react-native";
NativeModules.RNGestureHandlerModule = {};
Alternatively you can mock all components of react-native-gesture-handle like @matheushf suggested
I put this stuff into my jest setup file like @Lythenas
const mockNativeModules = {
UIManager: {
getViewManagerConfig: jest.fn(),
},
KeyboardObserver: {},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {},
},
PlatformConstants: {
forceTouchAvailable: false,
},
WebSocketModule: {
connect: jest.fn(),
send: jest.fn(),
sendBinary: jest.fn(),
ping: jest.fn(),
close: jest.fn(),
addListener: jest.fn(),
removeListeners: jest.fn(),
},
};
fixed the issue for me
If someone is still facing this, I solved with this:
package.json
... "setupFiles": [ "./jest.setup.js" ]
jest.setup.js
jest.mock('react-native-gesture-handler', () => { const View = require('react-native/Libraries/Components/View/View'); return { Swipeable: View, DrawerLayout: View, State: {}, ScrollView: View, Slider: View, Switch: View, TextInput: View, ToolbarAndroid: View, ViewPagerAndroid: View, DrawerLayoutAndroid: View, WebView: View, NativeViewGestureHandler: View, TapGestureHandler: View, FlingGestureHandler: View, ForceTouchGestureHandler: View, LongPressGestureHandler: View, PanGestureHandler: View, PinchGestureHandler: View, RotationGestureHandler: View, /* Buttons */ RawButton: View, BaseButton: View, RectButton: View, BorderlessButton: View, /* Other */ FlatList: View, gestureHandlerRootHOC: jest.fn(), Directions: {}, }; });
taken from here expo/jest-expo
I also added the NativeModules mock to jest.setup.js
jest.mock('react-native-gesture-handler', () => {
const View = require('react-native/Libraries/Components/View/View');
return {
Swipeable: View,
DrawerLayout: View,
State: {},
ScrollView: View,
Slider: View,
Switch: View,
TextInput: View,
ToolbarAndroid: View,
ViewPagerAndroid: View,
DrawerLayoutAndroid: View,
WebView: View,
NativeViewGestureHandler: View,
TapGestureHandler: View,
FlingGestureHandler: View,
ForceTouchGestureHandler: View,
LongPressGestureHandler: View,
PanGestureHandler: View,
PinchGestureHandler: View,
RotationGestureHandler: View,
/* Buttons */
RawButton: View,
BaseButton: View,
RectButton: View,
BorderlessButton: View,
/* Other */
FlatList: View,
gestureHandlerRootHOC: jest.fn(),
Directions: {},
};
});
jest.mock('NativeModules', () => ({
UIManager: {
RCTView: () => {},
},
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {}
},
PlatformConstants: {
forceTouchAvailable: false,
},
KeyboardObserver: {
}
}))
Modified the package.json jest section in this way
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "./jest/preprocessor.js"
},
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|react-native-vector-icons|react-native-version-number|react-native-device-info|react-navigation|react-native-safe-area-view|react-navigation-drawer|react-native-easy-grid|react-native-elements|react-navigation-stack|react-native-fontawesome|react-native-progress|react-native-material-dropdown|react-native-material-ripple|react-native-material-textfield|react-native-material-buttons|react-native-languages|react-native-restart|react-native-keyboard-aware-scroll-view|react-native-iphone-x-helper|react-native-collapsible|react-native-modal|react-native-animatable|@react-native-community/async-storage|@react-navigation/.*))"
],
"setupFiles": [
"./jest/jest.setup.js"
]
},
And also had to create a temporary jest/preprocessor.js https://github.com/facebook/react-native/issues/22175#issuecomment-477138096
/**
* Your own [temporary?] transform for React Native
*/
const generate = require('@babel/generator').default
const transformer = require('metro-react-native-babel-transformer')
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction')
const metroBabelRegister = require('metro-babel-register')
metroBabelRegister([])
module.exports = {
process(src, file) {
const { ast } = transformer.transform({
filename: file,
options: {
ast: true,
dev: true,
enableBabelRuntime: false,
experimentalImportSupport: false,
hot: false,
inlineRequires: false,
minify: false,
platform: '',
projectRoot: '',
retainLines: true,
sourceType: 'unambiguous',
},
src,
plugins: metroBabelRegister.config.plugins,
})
return generate(
ast,
{
code: true,
comments: false,
compact: false,
filename: file,
retainLines: true,
sourceFileName: file,
sourceMaps: true,
},
src,
).code
},
getCacheKey: createCacheKeyFunction([
__filename,
require.resolve('metro-react-native-babel-transformer'),
require.resolve('@babel/core/package.json'),
]),
}
My workaround below is only needed, if you're on a version prior to 1.2.1. That version ships with it's own jestSetup.js that can be used.
Instead of duplicating most of what was already defined in the jest setup for react-native itself, my working solution now looks like this – thanks to @robaca for helping me to come to that solution:
Note: You probably need to adjust the transformIgnorePatterns to the list of libraries that you have in your project, which still need to be processed by Babel.
"dependencies": {
"react": "16.8.6",
"react-native": "0.59.5",
"react-native-gesture-handler": "^1.0.16",
"react-native-vector-icons": "^6.3.0",
"react-navigation": "^3.3.2",
"react-navigation-header-buttons": "^2.1.2"
},
"devDependencies": {
"@babel/core": "^7.4.4",
"babel-jest": "24.7.1",
"jest": "24.7.1",
"metro-react-native-babel-preset": "0.53.1",
"react-test-renderer": "16.8.6"
},
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|react-navigation-header-buttons|react-navigation-stack|@react-navigation)"
],
"setupFiles": [
"./jest.setup.js"
]
},
Since react-native itself is already mocking the NativeModules
, this setup just adds the mocks for the gesture handler.
import {
NativeModules,
} from 'react-native';
Object.assign(NativeModules, {
RNGestureHandlerModule: {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {}
},
PlatformConstants: {
forceTouchAvailable: false,
}}
);
Take a look at the newest changes in the new release,
I still get:
TypeError: Cannot read property 'Direction' of undefined
at Object.Direction (node_modules/react-native-gesture-handler/Directions.js:3:39)
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:20:1)
at Object.<anonymous> (node_modules/react-native-gesture-handler/Swipeable.js:10:1)
with RNGH 1.2.1
I can fix this by including the following in my test setup:
NativeModules.RNGestureHandlerModule = {}
Still have to use the jest.setup.js
posted by @AndreasEK above on newest RNGH 1.2.1 for jest to work. Getting TypeError: Cannot read property 'Direction' of undefined
otherwise. The one liner by @voxspox above, by itself, didn't work in my case.
Actually, the following works:
setupFiles: [
"./node_modules/react-native-gesture-handler/jestSetup.js"
]
Pretty hidden in the documentation, found it by looking at the commits. See https://kmagiera.github.io/react-native-gesture-handler/docs/getting-started.html#testing
I can confirm that issue still exists
I needed to modify my KeyboardObserver
mock as follows:
...
KeyboardObserver: {
addListener: jest.fn(),
getConstants: jest.fn(),
removeListeners: jest.fn(),
},
....
Confirm this is fixed from 1.2.1 onwards.
It turned out that our apps' jest-setup.js wasn't including react-native's, which includes all these mocks. Added this line to the top of our jest setup, and it fixed our issues:
import 'react-native/jest/setup';
@AndreasEK -- we're on 1.2.1 according to our yarn.lock, and unfortunately our jest.mock(
workaround is still necessary. Do you have any pointers on the correct configuration here?
@matthargett -- when I comment out our workaround jest.mock("react-native", () => {…
and just include import 'react-native/jest/setup';
many of my tests start failing, so that doesn't work for us :(
this worked for us.
In setup.ts:
jest.mock('react-native-gesture-handler', () => { return {} })
@osdnk Apparently this still won't work, workarounds are still necessary :/ could you please re open it?
I get
Test suite failed to run
Invariant Violation: __fbBatchedBridgeConfig is not set, cannot invoke native modules
Tried all the solutions above, but still getting this error
TypeError: Cannot read property 'Direction' of undefined
at Object.Direction (node_modules/react-native-gesture-handler/Directions.js:3:39)
at Object.<anonymous> (node_modules/react-native-gesture-handler/GestureHandler.js:2:1)
I just upgraded to react-navigation@3.0 which now makes me a consumer of react-native-gesture-handler! Wooo!
Unfortunately, when I run our jest snapshot tests, the global scope of react-native-gesture-handler expects certain native modules to exist!
https://github.com/kmagiera/react-native-gesture-handler/blob/77491194049b82f26f358a09abc662ef27265527/GestureHandler.js#L26-L56
This means that jest then crashes in any tests that import react-navigation which imports react-native-gesture-handler.
Workaround:
I embedded the above code near the top of file in my
node_modules/react-native-gesture-handler/GestureHandler.js
, and the problem went away. -- For the medium term, I'll put the following snippet in my jestbeforeAll.js
:I'm happy to help contribute to this repo, but I don't know what strategy you want to take when solving this.