Skip to content

Commit 5b60019

Browse files
authored
Add e2e tests (detox)
1 parent 0f5c5dc commit 5b60019

File tree

20 files changed

+1399
-273
lines changed

20 files changed

+1399
-273
lines changed

.circleci/config.yml

Lines changed: 265 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,307 @@
11
version: 2
22

3-
# Defaults
3+
# ==============================
4+
# DEFAULTS FOR JOBS
5+
# ==============================
6+
47
default job config: &defaults
58
working_directory: ~/async_storage
9+
10+
checkout step for each job: &addWorkspace
11+
attach_workspace:
12+
at: ~/async_storage
13+
14+
# ==============================
15+
# ENVIRONMENT VARIABLES
16+
# ==============================
17+
18+
default config for js: &js_defaults
19+
<<: *defaults
620
docker:
721
- image: circleci/node:8
822

9-
checkout step for each job: &addWorkspace
10-
attach_workspace:
11-
at: ~/
23+
default config for macOS: &macos_defaults
24+
<<: *defaults
25+
resource_class: 'medium'
26+
macos:
27+
xcode: '10.1.0'
28+
29+
default config for android apk builds: &android_defaults
30+
<<: *defaults
31+
docker:
32+
- image: reactnativecommunity/react-native-android
33+
resource_class: 'medium'
34+
working_directory: ~/async_storage
35+
environment:
36+
- _JAVA_OPTIONS: '-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xmx2048m'
37+
- GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError -Xmx2048m"'
38+
- BUILD_THREADS: 2
39+
40+
# ==============================
41+
# CACHE CONFIG
42+
# ==============================
43+
44+
# brew
45+
save brew cache: &cache_save_brew
46+
name: Saving Brew cache
47+
paths:
48+
- /usr/local/Homebrew
49+
- ~/Library/Caches/Homebrew
50+
key: v1-brew-cache-{{ arch }}
51+
52+
restore brew cache: &cache_restore_brew
53+
name: Restoring Brew cache
54+
keys:
55+
- v1-brew-cache-{{ arch }}
56+
57+
save brew cache for android: &cache_save_brew_android
58+
name: Saving Brew cache for android
59+
paths:
60+
- /usr/local/Homebrew
61+
- ~/Library/Caches/Homebrew
62+
key: v1-brew-cache-{{ arch }}-android
63+
64+
restore brew cache for android: &cache_restore_brew_android
65+
name: Restoring Brew cache for android
66+
keys:
67+
- v1-brew-cache-{{ arch }}-android
68+
69+
# yarn
70+
save yarn cache: &cache_save_yarn
71+
name: Saving Yarn cache
72+
paths:
73+
- ~/.cache/yarn
74+
- ~/Library/Detox
75+
key: v1-yarn-cache-{{ checksum "package.json" }}-{{ arch }}
76+
77+
restore yarn cache: &cache_restore_yarn
78+
name: Restoring Yarn cache
79+
keys:
80+
- v1-yarn-cache-{{ checksum "package.json" }}-{{ arch }}
1281

82+
# gradle
83+
save gradle wrapper cache: &cache_save_gradle_wrapper
84+
name: Saving Gradle Wrapper cache
85+
paths:
86+
- ~/.gradle/wrapper
87+
key: gradle-wrapper-v1-{{ checksum "example/android/gradle/wrapper/gradle-wrapper.properties" }}
88+
89+
save gradle build cache: &cache_save_gradle_build
90+
name: Saving Gradle app/build cache
91+
paths:
92+
- ~/.gradle/caches
93+
key: app-build-gradle-v1-{{ checksum "example/android/app/build.gradle" }}
94+
95+
restore gradle wrapper cache: &cache_restore_gradle_wrapper
96+
name: Restoring Gradle Wrapper cache
97+
keys:
98+
- gradle-wrapper-v1-{{ checksum "example/android/gradle/wrapper/gradle-wrapper.properties" }}
99+
100+
restore gradle build cache: &cache_restore_gradle_build
101+
name: Restoring Gradle app/build cache
102+
keys:
103+
- app-build-gradle-v1-{{ checksum "example/android/app/build.gradle" }}
104+
105+
106+
# ==============================
107+
# JOBS
108+
# ==============================
13109

14110
jobs:
15111
"Setup environment":
16-
<<: *defaults
112+
<<: *js_defaults
17113
steps:
18114
- checkout
19-
- restore_cache:
20-
name: Restore node modules
21-
keys:
22-
- node_modules-{{ checksum "yarn.lock" }}-{{ checksum "package.json" }}-{{ arch }}
115+
- restore-cache: *cache_restore_yarn
23116
- run:
24117
name: Install dependencies
25-
command: yarn --pure-lockfile --non-interactive
26-
- save_cache:
27-
name: Save node modules
28-
key: node_modules-{{ checksum "yarn.lock" }}-{{ checksum "package.json" }}-{{ arch }}
29-
paths:
30-
- node_modules
118+
command: yarn --pure-lockfile --non-interactive --cache-folder ~/.cache/yarn
119+
- save-cache: *cache_save_yarn
31120
- persist_to_workspace:
32121
root: .
33122
paths: .
34123

35124
"Test: lint":
36-
<<: *defaults
125+
<<: *js_defaults
37126
steps:
38127
- *addWorkspace
39128
- run:
40129
name: Lint check
41130
command: yarn test:lint
42131

43132
"Test: flow":
44-
<<: *defaults
133+
<<: *js_defaults
45134
steps:
46135
- *addWorkspace
47136
- run:
48137
name: Flow check
49138
command: yarn test:flow
50139

140+
"Test: iOS e2e":
141+
<<: *macos_defaults
142+
steps:
143+
- *addWorkspace
144+
- restore-cache: *cache_restore_brew
145+
- run:
146+
name: Configure OSX Environment
147+
command: |
148+
HOMEBREW_NO_AUTO_UPDATE=1 brew install node@8 >/dev/null
149+
HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null
150+
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null
151+
touch .watchmanconfig
152+
node -v
153+
- save-cache: *cache_save_brew
154+
- restore-cache: *cache_restore_yarn
155+
- run:
156+
name: Installing Yarn dependencies
157+
command: yarn --pure-lockfile --non-interactive --cache-folder ~/.cache/yarn
158+
- save-cache: *cache_save_yarn
159+
- run:
160+
name: Build iOS app
161+
command: yarn build:e2e:ios
162+
163+
- run:
164+
name: Run e2e tests
165+
command: yarn test:e2e:ios
166+
167+
"Build: Android release apk":
168+
<<: *android_defaults
169+
steps:
170+
- *addWorkspace
171+
- restore-cache: *cache_restore_yarn
172+
- run:
173+
name: Installing Yarn dependencies
174+
command: yarn --pure-lockfile --non-interactive --cache-folder ~/.cache/yarn
175+
- save-cache: *cache_save_yarn
176+
177+
# Gradle
178+
- restore-cache: *cache_restore_gradle_wrapper
179+
- restore-cache: *cache_restore_gradle_build
180+
- run:
181+
name: Downloading Gradle dependencies
182+
command: cd example/android && ./gradlew --max-workers 2 fetchDependencies
183+
- save-cache: *cache_save_gradle_wrapper
184+
- save-cache: *cache_save_gradle_build
185+
186+
# Build and test
187+
- run:
188+
name: Build Android apk
189+
command: cd example/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release --max-workers 2
190+
191+
- persist_to_workspace:
192+
root: ~/async_storage
193+
paths:
194+
- example/android/app/build/outputs/apk/*
195+
196+
"Test: Android e2e":
197+
<<: *macos_defaults
198+
steps:
199+
- *addWorkspace
200+
- run:
201+
name: Configure env variables
202+
command: |
203+
echo 'export ANDROID_HOME="/usr/local/share/android-sdk"' >> $BASH_ENV
204+
echo 'export ANDROID_SDK_ROOT="/usr/local/share/android-sdk"' >> $BASH_ENV
205+
echo 'export PATH="$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/tools/bin:$PATH"' >> $BASH_ENV
206+
echo 'export QEMU_AUDIO_DRV=none' >> $BASH_ENV
207+
echo 'export JAVA_HOME=/Library/Java/Home' >> $BASH_ENV
208+
source $BASH_ENV
209+
210+
# Android tools
211+
- restore-cache: *cache_restore_brew_android
212+
- run:
213+
name: Install Android SDK tools
214+
command: |
215+
HOMEBREW_NO_AUTO_UPDATE=1 brew tap homebrew/cask >/dev/null
216+
HOMEBREW_NO_AUTO_UPDATE=1 brew cask install android-sdk >/dev/null
217+
HOMEBREW_NO_AUTO_UPDATE=1 brew cask install intel-haxm >/dev/null
218+
HOMEBREW_NO_AUTO_UPDATE=1 brew install node@8 >/dev/null >/dev/null
219+
- save-cache: *cache_save_brew_android
220+
221+
- run:
222+
name: Install Android emulator
223+
shell: /bin/bash -e
224+
command: |
225+
yes | sdkmanager "platform-tools" "tools" >/dev/null
226+
yes | sdkmanager "platforms;android-28" "system-images;android-21;google_apis;x86" >/dev/null
227+
yes | sdkmanager "emulator" --channel=3 >/dev/null
228+
yes | sdkmanager "build-tools;28.0.3" >/dev/null
229+
yes | sdkmanager --licenses >/dev/null
230+
yes | sdkmanager --list
231+
232+
- run:
233+
name: ADB start/stop
234+
command: |
235+
adb start-server
236+
adb devices
237+
adb kill-server
238+
ls -la ~/.android
239+
240+
- run:
241+
name: Create emulator
242+
command: |
243+
avdmanager create avd \
244+
--force \
245+
-n "Emu_E2E" \
246+
-k "system-images;android-21;google_apis;x86" \
247+
-g "google_apis" \
248+
-d "Nexus 4"
249+
250+
251+
252+
- run:
253+
name: Start emulator in background
254+
background: true
255+
command: |
256+
emulator -avd "Emu_E2E" \
257+
-cores 1 \
258+
-gpu auto \
259+
-accel on \
260+
-memory 1024 \
261+
-no-audio \
262+
-no-snapshot \
263+
-no-boot-anim \
264+
-no-window \
265+
-logcat '*:W' | grep -i "ReactNative"
266+
267+
- run:
268+
name: Wait for emulator to boot
269+
command: yarn build:e2e:android
270+
271+
- run:
272+
name: Wake device
273+
command: |
274+
adb shell input keyevent
275+
adb shell input keyevent 82 &
276+
277+
- run:
278+
name: Run e2e tests
279+
command: yarn test:e2e:android
280+
281+
# ==============================
282+
# WORK FLOWS
283+
# ==============================
51284
workflows:
52285
version: 2
53-
"Basic check":
286+
"Testing":
54287
jobs:
55288
- "Setup environment"
56289
- "Test: lint":
57290
requires:
58291
- "Setup environment"
59292
- "Test: flow":
60293
requires:
61-
- "Setup environment"
294+
- "Setup environment"
295+
- "Test: iOS e2e":
296+
requires:
297+
- "Test: lint"
298+
- "Test: flow"
299+
- "Build: Android release apk":
300+
requires:
301+
- "Test: lint"
302+
- "Test: flow"
303+
- "Test: Android e2e":
304+
requires:
305+
- "Test: lint"
306+
- "Test: flow"
307+
- "Build: Android release apk"

.circleci/scripts/run_android_e2e.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/bash
2+
3+
# On CI, waits for emu to be booted
4+
# Locally, builds apk
5+
6+
ROOT_DIR=$PWD
7+
8+
INTERVAL=5 # 5 secs between each check
9+
MAX_RETRIES=60 # wait max 5 minutes for emu to boot
10+
11+
build_apk() {
12+
echo
13+
echo "[Detox e2e] Building APK"
14+
cd "example/android"
15+
eval "./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release"
16+
cd ${ROOT_DIR}
17+
}
18+
19+
wait_for_emulator_to_boot() {
20+
isBooted=$(adb shell getprop sys.boot_completed 2>&1 | tr -d '\r')
21+
retriesLeft=${MAX_RETRIES}
22+
23+
echo
24+
echo "[Detox e2e] Checking if emulator is booted up."
25+
26+
while [[ "$isBooted" != "1" ]]; do
27+
28+
if [[ ${retriesLeft} -eq 0 ]]; then
29+
echo "[Detox e2e] Seems like emulator could not be booted." 1>&2
30+
exit 125
31+
fi
32+
33+
isBooted=$(adb shell getprop sys.boot_completed 2>&1 | tr -d '\r')
34+
35+
retriesLeft=$((retriesLeft - 1))
36+
echo "[Detox e2e] $retriesLeft checks left."
37+
sleep ${INTERVAL}
38+
done
39+
40+
echo "[Detox e2e] Emulator booted."
41+
}
42+
43+
if [[ -n $CIRCLECI ]]; then
44+
wait_for_emulator_to_boot # Run it on CI
45+
else
46+
build_apk # Run locally
47+
fi

0 commit comments

Comments
 (0)