Skip to content

Commit f9bd789

Browse files
bestanderFacebook Github Bot 9
authored andcommitted
E2e android
Summary:- converted shell script `scripts/e2e-test.sh` into JS script to have more programming flexibility - using appium execute 2 tests after a fresh React Native app installation: check HMR and that debugging mode does not crash the app - made sure tests can be stable on limited CI systems and added ways to debug any problems in the future Using appium we can now interact with Android app and test its state. As a follow up i am planning to write a blog post on how to use appium with android and ios for e2e testing. Closes facebook#6840 Differential Revision: D3173635 Pulled By: mkonicek fb-gh-sync-id: 3cf044bc9f64d1a842ae4589dd1bcab76de3d66a fbshipit-source-id: 3cf044bc9f64d1a842ae4589dd1bcab76de3d66a
1 parent c254d08 commit f9bd789

File tree

7 files changed

+317
-118
lines changed

7 files changed

+317
-118
lines changed

.travis.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,15 @@ install:
1616

1717
script:
1818
- if [[ "$TEST_TYPE" = objc ]]; then travis_retry ./scripts/objc-test.sh; fi
19-
- if [[ "$TEST_TYPE" = e2e-objc ]]; then travis_retry ./scripts/e2e-test.sh --ios; fi
19+
- if [[ "$TEST_TYPE" = e2e-objc ]]; then travis_retry node ./scripts/run-ci-e2e-tests.js --ios --js; fi
2020
- if [[ "$TEST_TYPE" = js ]]; then npm run flow check; fi
2121
- if [[ "$TEST_TYPE" = js ]]; then npm test -- --maxWorkers=1; fi
22-
- if [[ "$TEST_TYPE" = js ]]; then travis_retry ./scripts/e2e-test.sh --packager; fi
2322

2423
env:
2524
matrix:
2625
- TEST_TYPE=e2e-objc
27-
- TEST_TYPE=js
2826
- TEST_TYPE=objc
27+
- TEST_TYPE=js
2928

3029
branches:
3130
only:

ReactAndroid/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION_NAME=0.0.1-master
1+
VERSION_NAME=1000.0.0-master
22
GROUP=com.facebook.react
33

44
POM_NAME=ReactNative

circle.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,12 @@ test:
7171
# run installed apk with tests
7272
- source scripts/circle-ci-android-setup.sh && retry3 ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests
7373

74-
# Deprecated: run tests with Gradle, we keep them for a while to compare performance
7574
- ./gradlew :ReactAndroid:testDebugUnitTest
76-
- ./gradlew :ReactAndroid:installDebugAndroidTest
77-
- source scripts/circle-ci-android-setup.sh && retry3 ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests.gradle
75+
# Deprecated: these tests are executed using Buck above, while we support Gradle we just make sure the test code compiles
76+
- ./gradlew :ReactAndroid:assembleDebugAndroidTest
7877

79-
# JS and Android e2e test
80-
- source scripts/circle-ci-android-setup.sh && retry3 ./scripts/e2e-test.sh --packager --android
78+
# Android e2e test
79+
- source scripts/circle-ci-android-setup.sh && retry3 node ./scripts/run-ci-e2e-tests.js --android --js
8180

8281
# testing docs generation is not broken
8382
- cd website && node ./server/generate.js

local-cli/generator-android/templates/src/app/BUCK

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import re
55
# - install Buck
66
# - `npm start` - to start the packager
77
# - `cd android`
8-
# - `cp ~/.android/debug.keystore keystores/debug.keystore`
8+
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US`
99
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
1010
# - `buck install -r android/app` - compile, install and run application
1111
#

scripts/android-e2e-test.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
'use strict';
2+
3+
/**
4+
* Used in run-ci-e2e-test.js and executed in Travis and Circle CI.
5+
* E2e test that verifies that init app can be installed, compiled, started and Hot Module reloading and Chrome debugging work.
6+
* For other examples of appium refer to: https://github.com/appium/sample-code/tree/master/sample-code/examples/node and
7+
* https://www.npmjs.com/package/wd-android
8+
*
9+
*
10+
* To set up:
11+
12+
* - cp <this file> <to app installation path>
13+
* - keytool -genkey -v -keystore android/keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US
14+
*
15+
* To run this test:
16+
* - npm start
17+
* - node node_modules/.bin/appium
18+
* - (cd android && ./gradlew :app:copyDownloadableDepsToLibs)
19+
* - buck build android/app
20+
* - node ../node_modules/.bin/_mocha ../android-e2e-test.js
21+
*/
22+
23+
const wd = require('wd');
24+
const path = require('path');
25+
const fs = require('fs');
26+
const pd = require('pretty-data2').pd;
27+
require('colors');
28+
// value in ms to print out screen contents, set this value in CI to debug if tests are failing
29+
const appiumDebugInterval = process.env.APPIUM_DEBUG_INTERVAL;
30+
31+
describe('Android Test App', function () {
32+
this.timeout(600000);
33+
let driver;
34+
let debugIntervalId;
35+
36+
before(function () {
37+
driver = wd.promiseChainRemote({
38+
host: 'localhost',
39+
port: 4723
40+
});
41+
driver.on('status', function (info) {
42+
console.log(info.cyan);
43+
});
44+
driver.on('command', function (method, path, data) {
45+
if (path === 'source()' && data) {
46+
console.log(' > ' + method.yellow, 'Screen contents'.grey, '\n', pd.xml(data).yellow);
47+
} else {
48+
console.log(' > ' + method.yellow, path.grey, data || '');
49+
}
50+
});
51+
driver.on('http', function (method, path, data) {
52+
console.log(' > ' + method.magenta, path, (data || '').grey);
53+
});
54+
55+
// every interval print what is on the screen
56+
if (appiumDebugInterval) {
57+
debugIntervalId = setInterval(() => {
58+
// it driver.on('command') will log the screen contents
59+
driver.source();
60+
}, appiumDebugInterval);
61+
}
62+
63+
const desired = {
64+
platformName: 'Android',
65+
deviceName: 'Android Emulator',
66+
app: path.resolve('buck-out/gen/android/app/app.apk')
67+
};
68+
69+
// React Native in dev mode often starts with Red Box "Can't fibd variable __fbBatchedBridge..."
70+
// This is fixed by clicking Reload JS which will trigger a request to packager server
71+
return driver
72+
.init(desired)
73+
.setImplicitWaitTimeout(5000)
74+
.waitForElementByXPath('//android.widget.Button[@text="Reload JS"]').
75+
then((elem) => {
76+
elem.click();
77+
}, (err) => {
78+
// ignoring if Reload JS button can't be located
79+
})
80+
.setImplicitWaitTimeout(150000);
81+
});
82+
83+
after(function () {
84+
if (debugIntervalId) {
85+
clearInterval(debugIntervalId);
86+
}
87+
return driver.quit();
88+
});
89+
90+
it('should have Hot Module Reloading working', function () {
91+
const androidAppCode = fs.readFileSync('index.android.js', 'utf-8');
92+
let intervalToUpdate;
93+
return driver
94+
.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]')
95+
// http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU
96+
.pressDeviceKey(82)
97+
.elementByXPath('//android.widget.TextView[starts-with(@text, "Enable Hot Reloading")]')
98+
.click()
99+
.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]')
100+
.then(() => {
101+
let iteration = 0;
102+
// CI environment can be quite slow and we can't guarantee that it can consistently motice a file change
103+
// so we change the file every few seconds just in case
104+
intervalToUpdate = setInterval(() => {
105+
fs.writeFileSync('index.android.js', androidAppCode.replace('Welcome to React Native!', 'Welcome to React Native with HMR!' + iteration), 'utf-8');
106+
}, 3000);
107+
})
108+
.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Welcome to React Native with HMR!")]')
109+
.finally(() => {
110+
clearInterval(intervalToUpdate);
111+
fs.writeFileSync('index.android.js', androidAppCode, 'utf-8');
112+
});
113+
});
114+
115+
116+
it('should have Debug In Chrome working', function () {
117+
const androidAppCode = fs.readFileSync('index.android.js', 'utf-8');
118+
// http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU
119+
return driver
120+
.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]')
121+
.pressDeviceKey(82)
122+
.elementByXPath('//android.widget.TextView[starts-with(@text, "Debug")]')
123+
.click()
124+
.waitForElementByXPath('//android.widget.TextView[starts-with(@text, "Welcome to React Native!")]');
125+
});
126+
});

scripts/e2e-test.sh

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)