React Native Expo App:如何让它运行 Jest 测试

Posted

技术标签:

【中文标题】React Native Expo App:如何让它运行 Jest 测试【英文标题】:React Native Expo App: How to get it to run Jest tests 【发布时间】:2019-07-07 15:53:23 【问题描述】:

因此,当使用 Expo 创建 React Native 应用程序时,Jest 似乎现在是开箱即用的。

重现步骤:

    `expo init' 选择标签。 cd 进入您的应用。 运行npm test ???????? 失败

我用谷歌搜索并尝试了以下修复:

A) 添加jest.config.js:

module.exports = 
  preset: 'jest-expo',
  transform: 
    '\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
  
;

B) 将 react-natives 预处理器复制到您自己的 `jest.preprcessor.js' 文件中:

 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) 更改“测试”脚本部分

来自:

"test": "node_modules/.bin/jest"

到:

"test": "node ./node_modules/jest/bin/jest.js"

所以没有任何效果????所有方法都会导致部分或全部测试失败。

有谁知道如何在 Expo 32 上开个玩笑?

编辑: Bruno's answer 有效。此外,请确保在运行yarn 之前删除您的node_modulespackage-lock.json。此外,您不需要jest.config.js。而且你也不需要布鲁诺的babel.config.js。这是我的:

module.exports = function(api) 
    api.cache(true);
    return 
        presets: ['babel-preset-expo'],
    ;
;

这太奇怪了,它对npm 不起作用。

PS,这里是预处理器代码,所以你不必搜索它:

/**
 * 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'),
  ]),
;

我的依赖:

"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"
  ,

【问题讨论】:

遇到了同样的问题,请查看此链接***.com/questions/54524017/…。我会试着用几个写一个答案(atm 有点太忙了),但不要使用'&lt;rootDir&gt;/node_modules/react-native/jest/preprocessor.js' 解决方法,它不起作用。也可以使用 yarn 来下载你的包,而不是 npm。 感谢您的帮助,但在对您的链接问题的接受答案中,受访者只是要求创建一个新项目,我做了但没有工作。 您是否创建了一个新的示例项目 (expo init) 并使用 yarn install 下载了您的模块?因为在我切换到 yarn 之前,我的 Jest 测试无法正常工作。另外,请将您的dependenciesdevDependencies 添加到您的问题中。 为我解决的问题是摆脱大多数额外的依赖项(正在下载一堆不必要的东西)并使用 yarn 安装它们。您可以尝试通过npm install -g yarn 安装纱线,但这不是推荐的方式(虽然对我有用)。这是他们的文档:yarnpkg.com/en 您不需要将babel-jest 添加到您的依赖项中,因为jest-expo 会打包它自己的dist。 【参考方案1】:

您的dependeciesdevDependencies 看起来不错。

首先,安装yarn。按照此link 获取说明。 其次,您必须更改package.json 中的一些内容。像这样:
"scripts": 
    "test": "jest",
    ...
  ,
"jest": 
    "preset": "jest-expo",
    "transform": 
      "^.+\\.js$": "babel-jest"
  ,

第三,确保您的babel.config.js 设置正确。这是我运行 Expo 的 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 安装您的软件包yarn install 并运行您的测试yarn test

【讨论】:

这行得通,非常感谢。我不需要你的babel.config.js。我修改了我的帖子以供未来的主要读者阅读。

以上是关于React Native Expo App:如何让它运行 Jest 测试的主要内容,如果未能解决你的问题,请参考以下文章

如何为 create-react-native-app 生成 apk 文件(使用 EXPO.IO 组件)

React Native expo-location:如何让后台位置服务更新更频繁?

Expo - 网络响应超时错误 (create-react-native-app) (Windows 10)

如何在expo react native App中将api级别29更改为30

尝试在 create-react-native-app 项目 (expo) 中使用 react-native-fs

使用 Relay Modern 创建-react-native-app / expo