react-native/scripts/android-e2e-test.js

164 lines
5.3 KiB
JavaScript
Raw Normal View History

/**
* 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.
*
* Used in run-ci-e2e-test.js and executed in Circle CI.
* E2e test that verifies that init app can be installed, compiled, started and Hot Module reloading and Chrome debugging work.
* For other examples of appium refer to: https://github.com/appium/sample-code/tree/master/sample-code/examples/node and
* https://www.npmjs.com/package/wd-android
*
*
* To set up:
* - npm install --save-dev appium@1.5.1 mocha@2.4.5 wd@0.3.11 colors@1.0.3 pretty-data2@0.40.1
* - cp <this file> <to app installation path>
* - keytool -genkey -v -keystore android/keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US
*
* To run this test:
* - npm start
* - node node_modules/.bin/appium
* - (cd android && ./gradlew :app:copyDownloadableDepsToLibs)
* - buck build android/app
* - node ../node_modules/.bin/_mocha ../android-e2e-test.js
*
* @format
*/
/* eslint-env mocha */
'use strict';
const wd = require('wd');
const path = require('path');
const fs = require('fs');
const pd = require('pretty-data2').pd;
require('colors');
// value in ms to print out screen contents, set this value in CI to debug if tests are failing
const appiumDebugInterval = process.env.APPIUM_DEBUG_INTERVAL;
describe('Android Test App', function() {
this.timeout(600000);
let driver;
let debugIntervalId;
before(function() {
driver = wd.promiseChainRemote({
host: 'localhost',
port: 4723,
});
driver.on('status', function(info) {
console.log(info.cyan);
});
driver.on('command', function(method, path, data) {
if (path === 'source()' && data) {
console.log(
' > ' + method.yellow,
'Screen contents'.grey,
'\n',
pd.xml(data).yellow,
);
} else {
console.log(' > ' + method.yellow, path.grey, data || '');
}
});
driver.on('http', function(method, path, data) {
console.log(' > ' + method.magenta, path, (data || '').grey);
});
// every interval print what is on the screen
if (appiumDebugInterval) {
debugIntervalId = setInterval(() => {
// it driver.on('command') will log the screen contents
driver.source();
}, appiumDebugInterval);
}
const desired = {
platformName: 'Android',
deviceName: 'Android Emulator',
app: path.resolve('buck-out/gen/android/app/app.apk'),
};
// React Native in dev mode often starts with Red Box "Can't fibd variable __fbBatchedBridge..."
// This is fixed by clicking Reload JS which will trigger a request to packager server
return driver
.init(desired)
.setImplicitWaitTimeout(5000)
.waitForElementByXPath('//android.widget.Button[@text="Reload JS"]')
.then(
elem => {
elem.click();
},
err => {
// ignoring if Reload JS button can't be located
},
)
.setImplicitWaitTimeout(150000);
});
after(function() {
if (debugIntervalId) {
clearInterval(debugIntervalId);
}
return driver.quit();
});
it('should have Hot Module Reloading working', function() {
Move HelloWorld template to a single index.js entry point Summary: This change (initially discussed in https://github.com/react-community/create-react-native-app/issues/26) moves the HelloWorld project template from two nearly identical entry points (`index.android.js` and `index.ios.js`) to a single, minimal `index.js` entry point. The root component is created in `App.js`. This unifies the project structure between `react-native init` and Create React Native App and allows CRNA's eject to use the entry point from the HelloWorld template without any hacks to customize it. Also examples in the docs can be just copy-pasted to `App.js` the same way in both HelloWorld and CRNA apps without having to first learn about `AppRegistry.registerComponent`. * Created a new project from the template using `./scripts/test-manual-e2e.sh` and verified that: * The app builds, starts and runs both on Android and iOS. * Editing and reloading changes works. * The new files (`index.js`, `App.js`, `__tests__/App.js`) get created in the project folder. <img width="559" alt="screen shot 2017-08-01 at 19 10 51" src="https://user-images.githubusercontent.com/497214/28835171-300a12b6-76ed-11e7-81b2-623639c3b8f6.png"> <img width="467" alt="screen shot 2017-08-01 at 19 09 12" src="https://user-images.githubusercontent.com/497214/28835180-33d285e0-76ed-11e7-8d68-2b3bc44bf585.png"> <!-- Thank you for sending the PR! If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos! Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native. Happy contributing! --> Closes https://github.com/facebook/react-native/pull/15312 Differential Revision: D5556276 Pulled By: hramos fbshipit-source-id: 068fdf7e51381c2bc50321522f2be0db47296c5e
2017-08-03 20:52:06 +00:00
const androidAppCode = fs.readFileSync('index.js', 'utf-8');
let intervalToUpdate;
return (
driver
.waitForElementByXPath(
'//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]',
)
// http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU
.pressDeviceKey(82)
.elementByXPath(
'//android.widget.TextView[starts-with(@text, "Enable Hot Reloading")]',
)
.click()
.waitForElementByXPath(
'//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]',
)
.then(() => {
let iteration = 0;
// CI environment can be quite slow and we can't guarantee that it can consistently motice a file change
// so we change the file every few seconds just in case
intervalToUpdate = setInterval(() => {
fs.writeFileSync(
'index.js',
androidAppCode.replace(
'Welcome to React Native!',
'Welcome to React Native with HMR!' + iteration,
),
'utf-8',
);
}, 3000);
})
.waitForElementByXPath(
'//android.widget.TextView[starts-with(@text, "Welcome to React Native with HMR!")]',
)
.finally(() => {
clearInterval(intervalToUpdate);
fs.writeFileSync('index.js', androidAppCode, 'utf-8');
})
);
});
it('should have Debug In Chrome working', function() {
Move HelloWorld template to a single index.js entry point Summary: This change (initially discussed in https://github.com/react-community/create-react-native-app/issues/26) moves the HelloWorld project template from two nearly identical entry points (`index.android.js` and `index.ios.js`) to a single, minimal `index.js` entry point. The root component is created in `App.js`. This unifies the project structure between `react-native init` and Create React Native App and allows CRNA's eject to use the entry point from the HelloWorld template without any hacks to customize it. Also examples in the docs can be just copy-pasted to `App.js` the same way in both HelloWorld and CRNA apps without having to first learn about `AppRegistry.registerComponent`. * Created a new project from the template using `./scripts/test-manual-e2e.sh` and verified that: * The app builds, starts and runs both on Android and iOS. * Editing and reloading changes works. * The new files (`index.js`, `App.js`, `__tests__/App.js`) get created in the project folder. <img width="559" alt="screen shot 2017-08-01 at 19 10 51" src="https://user-images.githubusercontent.com/497214/28835171-300a12b6-76ed-11e7-81b2-623639c3b8f6.png"> <img width="467" alt="screen shot 2017-08-01 at 19 09 12" src="https://user-images.githubusercontent.com/497214/28835180-33d285e0-76ed-11e7-8d68-2b3bc44bf585.png"> <!-- Thank you for sending the PR! If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos! Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native. Happy contributing! --> Closes https://github.com/facebook/react-native/pull/15312 Differential Revision: D5556276 Pulled By: hramos fbshipit-source-id: 068fdf7e51381c2bc50321522f2be0db47296c5e
2017-08-03 20:52:06 +00:00
const androidAppCode = fs.readFileSync('index.js', 'utf-8');
// http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU
return driver
.waitForElementByXPath(
'//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]',
)
.pressDeviceKey(82)
.elementByXPath('//android.widget.TextView[starts-with(@text, "Debug")]')
.click()
.waitForElementByXPath(
'//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]',
);
});
});