The testing section of the docs for React Native suggest that Jest is the official way to do unit tests. However, they don't explain how to get it setup. Running Jest without any setup gives syntax errors (with no line numbers :( ) because it doesn't apply the transforms (eg ES6 features, JSX and Flow) that React Native code tends to use. There's a jestSupport folder in the React Native source try that contains a env.js and scriptPrerocess.js, the latter has code for apply the transforms. So I've copied those into my project and added the following section to my package.json:
"jest": {
"scriptPreprocessor": "jestSupport/scriptPreprocess.js",
"setupEnvScriptFile": "jestSupport/env.js"
},
This fixes the first error but I still get the following error:
Using Jest CLI v0.4.0
FAIL js/sync/__tests__/SynchronisedStorage-tests.js
SyntaxError: /Users/tom/my-project/js/sync/__tests__/SynchronisedStorage-tests.js: /Users/tom/my-project/js/sync/SynchronisedStorage.js: /Users/tom/my-project/node_modules/react-native/Libraries/react-native/react-native.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/browser/ui/React.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/utils/ReactChildren.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/addons/ReactFragment.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/classic/element/ReactElement.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/core/ReactContext.js: /Users/tom/my-project/node_modules/react-native/node_modules/react-tools/src/vendor/core/warning.js: Unexpected token .
1 test failed, 0 tests passed (1 total)
Run time: 0.456s
Is there more I need to do to make Jest understand React Native? Are there any examples of Jest setup to test React Native?
EDIT:
There was a check in scriptPreprocess that stopped it from running over any file in node_modules which of course included the whole of React Native. Removing that fixes the error above. However, I'm now getting more errors from the React Native source, it definitely seems like it isn't meant to be run within Jest.
EDIT2:
Explicitly setting the mock for the react-native module works:
jest.setMock('react-native', {});
That seems like it's going to be very manual and not very useful for testing code that interacts with the React Native API a lot. I definitely still feel like I'm missing something!
I got Jest to work for my React Native application, and it is running tests without any problem on files with ES6 and ES7 transforms.
To get Jest to work, I followed these steps:
Copied the jestSupport folder from the React Native master repo to my react-native folder in node_modules.
Edited the "jest" line in my packages.json to points to the files in the jestSupport folder
The "jest" line in my packages.json now looks lke this:
"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/react-native/jestSupport/scriptPreprocess.js",
"setupEnvScriptFile": "<rootDir>/node_modules/react-native/jestSupport/env.js",
"testFileExtensions": [
"js"
],
"unmockedModulePathPatterns": [
"source-map"
]
},
As of React Native v0.37.0, Jest is part of the new app template.
In a new app you can run tests right away:
$ react-native init MyAwesomeApp
$ cd MyAwesomeApp
$ npm test
...
Tests: 2 passed
For newer versions of jest, setting it up for react-native is very easy.
Install jest using
npm install --save-dev jest-cli babel-jest
In package.json, add this
"scripts": {
"start": "babel-node ./server/server.js",
"import-data": "babel-node ./scripts/import-data-from-parse.js",
"update-schema": "babel-node ./server/schema/updateSchema.js",
"test": "jest",
"lint": "eslint ."
},
"jest": {
"haste": {
"defaultPlatform": "ios",
"platforms": [
"ios",
"android"
],
"providesModuleNodeModules": [
"react-native"
]
}
},
You might only need to add lines related to jest
Now you can use
npm test
to run jest.
Refer to f8app's github repo to find more about this.
Related
I tried with putting
GENERATE_SOURCEMAP=false
in .env file, running command
set \"GENERATE_SOURCEMAP=false\" && expo build:web
and
"build": "GENERATE_SOURCEMAP=false expo build:web"
in scripts inside package.json
nothing works. Devtools show my everything.
How can I protect my source from being exposed with expo:build?
Working with this for a while...
You can just build your web app like
GENERATE_SOURCEMAP=false expo build:web
Or edit your package.json as
"scripts": {
"custom-web-build": "GENERATE_SOURCEMAP=false expo build:web",
"...": "..."
}
Then
yarn custom-web-build
Note that you might have to clean your browser cookies or use a private window to see the changes.
Expo react-native app does not load on connected iphone
When I start my app using the command below:
expo start --tunnel
I get the following error:
Logs for your project will appear below. Press Ctrl+C to exit.
Unable to resolve "react-native-vector-icons/AntDesign" from
"node_modules/react-native-elements/src/helpers/getIconType.js"
Building JavaScript bundle [=================================================================================================== ] 99%
I am using ios 10.13.6 High Sierra.
Anybody have seen this issue before? any suggestions to debug or resolve this issue?
it looks like you are not using the babel preset which is set up when you initialize a project in expo. this preset remaps react-native-vector-icons to #expo/vector-icons, so you would not see this error if you were using it.
if you are using sdk32, you can fix that by creating babel.config.js in your project (and removing .babelrc if there is one) and adding this to babel.config.js:
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
now close the packager and run expo start -c.
if you are using an older sdk version than sdk32, you can just edit .babelrc (or create it if it doesn't exist) and change it to this:
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}
I removed react-native-elements from package.json. I then ran the following command:
rm -rf node_modules package-lock.json; npm install
then issued the following command:
expo start -c --tunnel
This seemed to have fixed the issue. I need the native-react-elements package so the next thing is that I am going to add it back and try to test with different versions of react-native-elements package.
I have created a React Native Project and I was trying to open that project in Expo XDE. It throws the following error:
Cannot find module ...\node_modules\expo\tools\LogReporter
Firstly I created a React Native project by cloning a KitchenSink Project.
Link:
NativeBase-KitchenSink
When I started the project by issuing series of commands inside the project root directory:
npm install and then expo start
I saw that the app.json was also not proper, which was the following:
{
"name": "NativebaseKitchenSink",
"displayName": "NativebaseKitchenSink"
}
After issuing expo start react-native reported that the app.json is not to be found in the current directory.
[17:05:08] Starting project at
D:\Projects\ReactNativeProjects\AwesomeProject [17:05:10] Error:
Missing app.json. See https://docs.expo.io/ [17:05:10] Couldn't start
project. Please fix the errors and restart the project. [17:05:10]
Error: Couldn't start project. Please fix the errors and restart the
project.
at C:\xdl#51.4.0\src\Project.js:1565:11
at Generator.next ()
at step (C:\Users\hp\AppData\Roaming\npm\node_modules\expo-cli\node_modules\xdl\build\Project.js:2033:191)
at C:\Users\hp\AppData\Roaming\npm\node_modules\expo-cli\node_modules\xdl\build\Project.js:2033:361
at process._tickCallback (internal/process/next_tick.js:68:7)
I changed app.json to:
{
"expo": {
"name": "AwesomeProject",
"description": "A Kitchen Sink project.",
"slug": "AwesomeProject",
"privacy": "public",
"sdkVersion": "30.0.0",
"platforms": [
"ios",
"android"
],
"ios": {
"supportsTablet": true
},
"android": {
"package": "com.abhsax.first"
},
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/logo.png",
"splash": {
"image": "./assets/splashscreen.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
]
}
}
There were some updates in the project when I issued npm install again. Then I issued:
expo start
This error came:
(node:2044) UnhandledPromiseRejectionWarning: Error: Cannot find
module
'D:\Projects\ReactNativeProjects\AwesomeProject\node_modules\expo\tools\LogReporter'
Why am I getting this error, and how can I fix it?
check your package.json if it contains all needed dependencies and run npm install in the home directory of the project
if a package is missing you can add it with
npm install <package_name> --save
if you are using yarn run:
yarn add expo
I did:
yarn add expo
and it worked for me =)
See docs:
introducing-button-yarn-and-a-public-roadmap
and
npm-vs-yarn-in-react-native
These documents say that since the project configured using Yarn, you have to follow Yarn way. [Note: There is a file yarn.lock inside the root directory of the project, you have posted]
Therefore such projects are dealt by following the instructions in the documentation.
Please see How do I create a React Native project using Yarn? to actually create a react-native project using Yarn.
And please be sure to remove node_modules folder and issue command npm install before adding react native CLI using yarn. You have to remove package-lock.json from your project root. This will be to prevent mixing different package managers : npm and yarn.
Instead, it will be a good idea not to use npm, and in order to generate node_modules, just issue command:
yarn
Last link recommends to install every package you need using yarn, and not to use any other package manager:
yarn global add react-native-cli
to add react-native:
yarn add react-native
to add missing packages:
yarn add react-base --save
and to install expo using yarn:
yarn add expo
install expo-cli
yarn add expo-cli
It is possible that you can do without Expo. Just focus on react-native and yarn.
Generate android and ios folders:
react-native eject
Start yarn:
yarn start
run build of your choice, and make sure the SDKs are installed.
react-native run-android
Please also see: Uncaught TypeError: Cannot read property 'forEach' of undefined, on a KitchenSink demo
Happy Coding :-)
Install the Expo modules
npm install --save
i.e.
npm install expo --save
rollback with npm install -g expo-cli#2.4.3
I'm getting a weird import error when I try to test my react-native app with jest. I have babel-jest, babel-preset-react-native, jest, jest-react-native and react-test-render all installed but get this error message when I run npm test.
● Test suite failed to run
/Users/maftalion/www/stars20/kiosk/node_modules/native-base/index.js:4
import Drawer from './Components/vendor/react-native-drawer';
^^^^^^
**SyntaxError: Unexpected token import**
at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:316:10)
at Object.<anonymous> (src/routes/Identification.js:3:17)
at Object.<anonymous> (src/routes/router.js:4:21)
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 passed, 1 total
Snapshots: 1 passed, 1 total
Time: 1.011s
Figured it out, basically throw any node modules that use es6 syntax in transformIgnorePatterns.
"transformIgnorePatterns": [
"node_modules/(?!react-native|native-base|react-clone-referenced-element)"
],
Try adding transformIgnorePatterns to your package.json:
{
"name": "MyAwesomeApp",
...
"jest": {
"transformIgnorePatterns": ["/node_modules/"]
}
}
For me Jest works out of the box, however:
$ react-native init MyAwesomeApp
$ cd MyAwesomeApp
$ npm test
...
Tests: 2 passed
I'm using React Native v0.37.0.
I found the answers given earlier didn't solve Unexpected token import errors in the tests itself, if they are written in ES6 (like the boilerplate tests created by the Ignite CLI after ignite new MyProject).
I finally managed to remove ES6-related errors by adding to the test task in package.json:
"test": "NODE_ENV=test jest --no-cache"
I am using RN 0.45.1, Node 7.10.1 (and 8.1.2), Yarn 0.24.6 and Jest 20.0.4
PS: Don't always see this in the console, but in VS Code v1.13.1 setting --no-cache makes the difference.
You configured Babel in your webpack config and this will only apply to webpack. When other tools, like Jest, use Babel, they won't see that configuration because they don't look at the webpack config. You can use a .babelrc file to configure Babel and that will apply to anything that runs Babel (not just webpack).
Using a .babelrc is usually preferred as you want to have a general babel config, and if you need to override a setting, you can still do that in the specific application like in the webpack config.
Create the following .babelrc:
{
"presets": ["es2015", "react"]
}
With that, you can remove the presets option in your webpack config because it will use the .babelrc. Note that the [cacheDirectory option][3] is specific to babel-loader and is not used to configure the underlying Babel.
You also have a typo in your test, toMatchSnapShot() should be toMatchSnapshot().
expect(rendered.toJSON()).toMatchSnapshot();
I needed to add .babelrc with:
{
"presets": ["#babel/env","#babel/react"]
}
I also needed to install this module
npm install add --dev react-test-renderer
Given the following directory structure:
my-project
|
|-- node_modules
|
|-- react
|-- module-x
|
|--node_modules
|
|--react
You can see both my-project and module-x require React. I have the same problem as described on this question, but the suggestion is to remove react from the package.json dependencies. I do that and it works fine, as long as no node_modules are installed in module-x, because Webpack will use React from my-project. But if I'm in the process of developing module-x and the node_modules are installed, Webpack uses React from both my-project and module-x.
Is there a way I could have Webpack make sure only one instance of React is used, even though it's required on two separate levels?
I know I could keep module-x in a separate directory when developing, but it seems like I'd have to publish it and then install it in my-project to test it, and that's not very efficient. I thought about npm link, but had no luck with it since it still has node_modules installed in module-x.
This here sounds a lot like the same challenge I'm having, but it doesn't seem like npm dedupe or Webpack's dedupe option would work. I'm probably not understanding some important detail.
This issue usually arises when using npm link. A linked module will resolve its dependencies in its own module tree, which is different from the one of the module that required it. As such, the npm link command installs peerDependencies as well as dependencies.
You can use resolve.alias to force require('react') to resolve to your local version of React.
resolve: {
alias: {
react: path.resolve('./node_modules/react'),
},
},
If you don’t want to (or can’t) modify the project configuration, there is a more straightforward solution: just npm link React itself back to your project:
# link the component
cd my-app
npm link ../my-react-component
# link its copy of React back to the app's React
cd ../my-react-component
npm link ../my-app/node_modules/react
Just in case it's useful for others, the solutions suggested above didn't work for me, I had to perform the following steps to solve it:
In the library:
Setup the libraries that are generating issues as peerDependencies in the package.json instead of dependencies or devDependencies, e.g. in my case react:
"peerDependencies": {
"react": "^16.8.6",
...
}
run npm install
build the library (in my case, with a rollup -c npm script
In my main app:
change the version of my library to point to my local project with a relative path in package.json, e.g.
"dependencies": {
"my-library": "file:../../libraries/my-library",
...
}
Add resolve.symlinks = false to my main app's webpack configuration
Add --preserve-symlinks-main and --preserve-symlinks to my package.json start script, e.g:
"scripts": {
"build": "set WEBPACK_CONFIG_FILE=all&& webpack",
"start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
run npm install
run npm run start
In the same vein as the accepted answer here's how you can achieve the desired outcome with Craco:
const path = require('path')
module.exports = {
webpack: {
configure: config => {
config = {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'react': path.resolve('./node_modules/react'),
},
},
}
// console.log(config)
return config
},
},
}
It's important to note you can't just pass resolve as a key, you have to do your own deep merge using the configure callback.