在 React-Native/Expo 移动应用程序上设置 Detox 时出错:“ReferenceError: element is not defined”

Posted

技术标签:

【中文标题】在 React-Native/Expo 移动应用程序上设置 Detox 时出错:“ReferenceError: element is not defined”【英文标题】:Error setting up Detox on React-Native/Expo mobile app: "ReferenceError: element is not defined" 【发布时间】:2019-09-16 00:32:27 【问题描述】:

我正在尝试在 React-Native/Expo 移动应用上使用 Detox 设置端到端测试。该应用程序和 Jest 目前运行良好,但排毒测试给出了 ReferenceError。我已按照此链接 https://blog.expo.io/testing-expo-apps-with-detox-and-react-native-testing-library-7fbdbb82ac87 以及 Detox 和 Jest 网站中的说明进行操作。 我已经通过一个笑话脚本 (yarn test) 和 detox test 运行了测试。

$ detox test --loglevel trace
detox[51199] INFO:  [test.js] configuration="ios.sim" loglevel="trace" artifactsLocation="artifacts/ios.sim.2019-04-26 12-31-53Z" recordLogs="none" takeScreenshots="manual" recordVideos="none" recordPerformance="none" node_modules/.bin/jest --config=e2e/config.json --maxWorkers=1 '--testNamePattern=^((?!:android:).)*$' "e2e"
● Validation Warning:

  Unknown option "setupFilesAfterEnv" with value ["./init.js"] was found.
  This is probably a typing mistake. Fixing it will remove this message.

  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

 FAIL  e2e/features/login/index.spec.js
  App
    ✕ should have login screen (272ms)
    ✕ should show hello screen after tap (104ms)
    ✕ should show world screen after tap (105ms)

  ● App › should have login screen

    ReferenceError: device is not defined

      at reloadApp (../node_modules/detox-expo-helpers/index.js:68:3)

  ● App › should have login screen

    ReferenceError: element is not defined
...

setupFilesAfterEnv 一个笑话。

下载的 Expo IPA 位于 bin/Exponent.app 目录中。

package.json


...
  "main": "node_modules/expo/AppEntry.js",
  "scripts": 
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "test": "jest --watchAll --notify",
    "lint": "eslint .",
    "ci": "yarn lint && jest"
  ,
  "dependencies": 
    "expo": "^32.0.0",
    "formik": "^1.5.1",
    "invariant": "^2.2.4",
    "prop-types": "^15.7.2",
    "react": "16.5.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
    "react-navigation": "^3.3.2",
    "react-redux": "^6.0.1",
    "redux": "^4.0.1",
    "redux-persist": "^5.10.0",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0"
  ,
  "devDependencies": 
    "@babel/core": "^7.3.4",
    "babel-eslint": "^10.0.1",
    "babel-plugin-module-resolver": "^3.2.0",
    "babel-preset-expo": "^5.0.0",
    "detox": "^12.4.1",
    "detox-expo-helpers": "^0.6.0",
    "eslint": "^5.15.0",
    "eslint-config-prettier": "^4.1.0",
    "eslint-plugin-prettier": "^3.0.1",
    "eslint-plugin-react": "^7.12.4",
    "expo-detox-hook": "^1.0.10",
    "jest-expo": "^32.0.0",
    "prettier": "^1.16.4",
    "react-native-testing-library": "^1.7.0",
    "react-test-renderer": "^16.8.6",
    "redux-devtools-extension": "^2.13.8",
    "redux-mock-store": "^1.5.3"
  ,
  "jest": 
    "preset": "jest-expo",
    "clearMocks": true
  ,
  "detox": 
    "test-runner": "jest",
    "runner-config": "e2e/config.json",
    "configurations": 
      "ios.sim": 
        "binaryPath": "bin/Exponent.app",
        "type": "ios.simulator",
        "name": "iPhone XR"
      
    
  

e2e 目录直接来自 Detox,对 Expo 进行了一些更改。

e2e/config.json


    "setupFilesAfterEnv": ["./init.js"],
    "testEnvironment": "node"

e2e/init.js

const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/jest/adapter');

jest.setTimeout(120000);
jasmine.getEnv().addReporter(adapter);

beforeAll(async () => 
    await detox.init(config);
);

beforeEach(async () => 
    await adapter.beforeEach();
);

afterAll(async () => 
    await adapter.afterAll();
    await detox.cleanup();
);

login.spec.js

import  reloadApp  from 'detox-expo-helpers';

describe('App', () => 
    beforeEach(async () => 
        await reloadApp();
    );

    it('should have login screen', async () => 
        await expect(element(by.id('login'))).toBeVisible();
    );

    it('should show hello screen after tap', async () => 
        await element(by.id('hello_button')).tap();
        await expect(element(by.text('Hello!!!'))).toBeVisible();
    );

    it('should show world screen after tap', async () => 
        await element(by.id('world_button')).tap();
        await expect(element(by.text('World!!!'))).toBeVisible();
    );
);

顺便说一句,我不知道为什么 init.js 中有 jasmine 引用。我猜这是因为 JestJS 基于 Jasmine。无论如何,它似乎与错误无关。

【问题讨论】:

【参考方案1】:

总结

这个问题有一个open pull-request。我引用Yaron Malim

ReferenceError: device is not defined

  at Object.reloadApp (../node_modules/detox-expo-helpers/index.js:68:3)

当我添加以下要求时:

const  device  = require('detox');

问题已解决。 为此,我必须添加 detox 作为依赖项。这是package.json


  "name": "detox-expo-helpers",
  "version": "0.6.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": ,
  "dependencies": 
    "child-process-promise": "^2.2.1",
    "detox": "^12.2.0",
    "semver": "^5.6.0",
    "xdl": "^51.5.0"
  

committed files in the pull request的详细信息

安装必要的依赖项

detox-expo-helpers github repo 包括an example app。添加expo-detox-hook to your package.json 并运行npm install


  "devDependencies": 
    "detox": "^9.0.6",
    "detox-expo-helpers": "^0.6.0",
    "expo-detox-hook": "^1.0.10",
    "mocha": "^3.5.0"
  ,
  "detox": 
    "configurations": 
      "ios.sim": 
        "binaryPath": "bin/Exponent.app",
        "type": "ios.simulator",
        "name": "iPhone 7"
      
    
  

正如official detox-expo-helpers page 中所述,您应该遵循to set up your detox project 的每一步,除了the package.json configurations included in this step,这在expo 中是不同的。

detox-expo-helpers 包含您的模拟器的官方配置at the step Download the Expo app to some directory in your project and configure in package.json

它还包括一个example of the Detox settings for your package.json

您的第二个测试失败了,因为Detox 没有在页面上找到该元素。 您需要将 testID 属性传递给值为 'hello_button' 的组件。

it('should show hello screen after tap', async () => 
    await element(by.id('hello_button')).tap();
    await expect(element(by.text('Hello!!!'))).toBeVisible();
);

documentation on by.id matcher

by.id 将匹配通过 testID 属性提供给视图的 id。

你的组件应该是这样的

<TouchableOpacity testID='hello_button'>

【讨论】:

添加了expo-detox-hooks,阅读了所有文档并用我的配置仔细检查了它们,转储并重新加载了node_modules,但我得到了完全相同的错误。 @PaulB 不幸的是我不知道如何解决这个问题。您是否尝试了其他方法或为我提供了更新?谢谢 我所做的一切都没有产生任何影响。如果您对如何解决问题有任何建议,我很乐意听到。 @PaulB 我找到了解决您问题的方法。您需要遵循此拉取请求中的说明github.com/expo/detox-expo-helpers/pull/12 你提到的 PR 肯定是针对问题的根源,但不幸的是,只会导致新的错误。我会继续接受答案,并希望有人(比我聪明)可以让 PR 工作。

以上是关于在 React-Native/Expo 移动应用程序上设置 Detox 时出错:“ReferenceError: element is not defined”的主要内容,如果未能解决你的问题,请参考以下文章

React-Native (expo) 检索初始主题(或任何初始化值)

react-native expo android macos问题

使用 react-native (expo) 切换手电筒

在React-Native Expo的App购买中?

react-native / expo / expo-google-app-auth vs expo-google-sign-in

React-Native Expo 应用程序突然无法运行,因为 Invariant Violation: 'main' has not been registered