So Jest seems to be broken out of the box right now, when creating a React Native App with Expo.
Steps to reproduce:
cd
into your app.npm test
👉🏻 Fails
I googled and tried out the following fixes:
A) Add jest.config.js
:
module.exports = {
preset: 'jest-expo',
transform: {
'\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
}
};
B) Copy react-natives preprocessor in your own `jest.preprcessor.js' file:
transform: {
/*
* Stop jest from falling over on its face.
* cf. https://github.com/expo/expo/issues/2595#issuecomment-440966998
* cf. https://github.com/facebook/react-native/issues/22175#issuecomment-436959462
*/
'\\.js$': '<rootDir>/jest.preprocessor.js',
},
C) Changing the "test" scripts section
from:
"test": "node_modules/.bin/jest"
to:
"test": "node ./node_modules/jest/bin/jest.js"
So nothing works 😓 All approaches result in some or all tests failing.
Does anyone know how to get jest to work with Expo 32?
Edit: Bruno's answer works. Additionally, make sure to delete your node_modules
and package-lock.json
before running yarn
. Furthermore, you don't need a jest.config.js
. And you also don't need Bruno's babel.config.js
. Here is mine:
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
It's so weird that it doesn't work for npm
.
PS, here is the preprocessor code so you don't have to search it:
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
/* eslint-env node */
'use strict';
const {transformSync: babelTransformSync} = require('@babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const babelRegisterOnly = require('metro-babel-register');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('@babel/generator').default;
const nodeFiles = RegExp(
[
'/local-cli/',
'/metro(?:-[^/]*)?/', // metro, metro-core, metro-source-map, metro-etc
].join('|'),
);
const nodeOptions = babelRegisterOnly.config([nodeFiles]);
babelRegisterOnly([]);
/* $FlowFixMe(site=react_native_oss) */
const transformer = require('metro/src/reactNativeTransformer');
module.exports = {
process(src /*: string */, file /*: string */) {
if (nodeFiles.test(file)) {
// node specific transforms only
return babelTransformSync(src, {
filename: file,
sourceType: 'script',
...nodeOptions,
ast: false,
}).code;
}
const {ast} = transformer.transform({
filename: file,
localPath: file,
options: {
ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044
dev: true,
inlineRequires: true,
minify: false,
platform: '',
projectRoot: '',
retainLines: true,
sourceType: 'unambiguous', // b7 required. detects module vs script mode
},
src,
plugins: [
[require('@babel/plugin-transform-block-scoping')],
// the flow strip types plugin must go BEFORE class properties!
// there'll be a test case that fails if you don't.
[require('@babel/plugin-transform-flow-strip-types')],
[
require('@babel/plugin-proposal-class-properties'),
// use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
{loose: true},
],
[require('@babel/plugin-transform-computed-properties')],
[require('@babel/plugin-transform-destructuring')],
[require('@babel/plugin-transform-function-name')],
[require('@babel/plugin-transform-literals')],
[require('@babel/plugin-transform-parameters')],
[require('@babel/plugin-transform-shorthand-properties')],
[require('@babel/plugin-transform-react-jsx')],
[require('@babel/plugin-transform-regenerator')],
[require('@babel/plugin-transform-sticky-regex')],
[require('@babel/plugin-transform-unicode-regex')],
[
require('@babel/plugin-transform-modules-commonjs'),
{strict: false, allowTopLevelThis: true},
],
[require('@babel/plugin-transform-classes')],
[require('@babel/plugin-transform-arrow-functions')],
[require('@babel/plugin-transform-spread')],
[require('@babel/plugin-proposal-object-rest-spread')],
[
require('@babel/plugin-transform-template-literals'),
{loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
],
[require('@babel/plugin-transform-exponentiation-operator')],
[require('@babel/plugin-transform-object-assign')],
[require('@babel/plugin-transform-for-of'), {loose: true}],
[require('@babel/plugin-transform-react-display-name')],
[require('@babel/plugin-transform-react-jsx-source')],
],
});
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/src/reactNativeTransformer'),
require.resolve('@babel/core/package.json'),
]),
};
My dependencies:
"dependencies": {
"@expo/samples": "2.1.1",
"expo": "^32.0.0",
"formik": "^1.5.0",
"i18n-js": "^3.2.1",
"prop-types": "^15.7.1",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-navigation": "^3.0.9",
"yup": "^0.26.10"
},
"devDependencies": {
"babel-eslint": "^10.0.1",
"babel-preset-expo": "^5.0.0",
"eslint": "^5.13.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.12.4",
"eslint-plugin-react-native": "^3.6.0",
"eslint-plugin-react-native-a11y": "^1.2.0",
"eslint-plugin-simple-import-sort": "^3.0.0",
"jest-expo": "^32.0.0",
"react-native-elements": "^1.0.0",
"react-native-testing-library": "^1.5.0"
},
To do so, run yarn add jest-expo --dev or npm i jest-expo --save-dev depending on which package manager you prefer. Then, install the test renderer library: yarn add react-test-renderer --dev or npm i react-test-renderer --save-dev . That's it! ?
Setup Run yarn test to run tests with Jest. If you are upgrading your react-native application and previously used the jest-react-native preset, remove the dependency from your package. json file and change the preset to react-native instead.
Mocking native modulesMake sure that the path to the file in setupFiles is correct. Jest will run these files before running your tests, so it's the best place to put your global mocks. If you're not using Jest, then you'll need to mock these modules according to the test framework you are using.
Your dependecies
and devDependencies
seem fine.
yarn
. Follow this link for instructions.package.json
. Like this:"scripts": {
"test": "jest",
...
},
"jest": {
"preset": "jest-expo",
"transform": {
"^.+\\.js$": "babel-jest"
},
}
babel.config.js
is setup correctly. Here's the one from my project running Expo's SDK 32:module.exports = function (api) {
api.cache(true);
return {
presets: [
'babel-preset-expo',
'module:react-native-dotenv',
],
sourceMaps: true,
plugins: [
'@babel/transform-react-jsx-source',
],
};
};
yarn
to install your packages yarn install
and to run your tests yarn test
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With