Error setting up Detox on React-Native/Expo mobile app: "ReferenceError: element is not defined"
Error setting up Detox on React-Native/Expo mobile app: "ReferenceError: element is not defined"
我正在尝试在 React-Native/Expo 移动应用程序上使用 Detox 设置端到端测试。该应用程序和 Jest 目前运行良好,但 Detox 测试给出了 ReferenceError。我已按照 link、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 中有茉莉花参考。我猜是因为 JestJS 是基于 Jasmine 的。反正好像跟报错没有关系
总结
有个open pull-request for this issue. I quote Yaron Malim
ReferenceError: device is not defined
at Object.reloadApp (../node_modules/detox-expo-helpers/index.js:68:3)
When I added the following require:
const { device } = require('detox');
The issue was solved.
In order to do so, I had to add detox as a dependency. This is the 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 includes an example app. Add 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 you should follow every step to set up your detox
project, except for 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
will match an id that is given to the view via testID
prop.
你的组件应该看起来像
<TouchableOpacity testID={'hello_button'}>
我正在尝试在 React-Native/Expo 移动应用程序上使用 Detox 设置端到端测试。该应用程序和 Jest 目前运行良好,但 Detox 测试给出了 ReferenceError。我已按照 link、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 中有茉莉花参考。我猜是因为 JestJS 是基于 Jasmine 的。反正好像跟报错没有关系
总结
有个open pull-request for this issue. I quote Yaron Malim
ReferenceError: device is not defined
at Object.reloadApp (../node_modules/detox-expo-helpers/index.js:68:3)
When I added the following require:
const { device } = require('detox');
The issue was solved. In order to do so, I had to add detox as a dependency. This is the 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 includes an example app. Add 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 you should follow every step to set up your detox
project, except for 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
will match an id that is given to the view viatestID
prop.
你的组件应该看起来像
<TouchableOpacity testID={'hello_button'}>