Skip to content

Commit d4a7a3f

Browse files
committed
feat: Android detox tests
1 parent 13e7127 commit d4a7a3f

27 files changed

+424
-81
lines changed

.detoxrc.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// run iPhone 14 on local machine, iPhone 15 Pro on mac mini
22
const iOSDevice = process.env.MACMINI ? 'iPhone 15 Pro' : 'iPhone 14';
33

4+
const reversePorts = [3003, 8080, 8081, 9735, 10009, 28334, 28335, 28336, 39388, 43782, 60001];
5+
6+
/** @type {Detox.DetoxConfig} */
47
module.exports = {
58
testRunner: {
69
$0: 'jest',
@@ -25,15 +28,19 @@ module.exports = {
2528
},
2629
'android.debug': {
2730
type: 'android.apk',
28-
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
31+
testBinaryPath: 'android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk',
32+
binaryPath: 'android/app/build/outputs/apk/debug/app-universal-debug.apk',
2933
build:
3034
'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd .. ',
35+
reversePorts,
3136
},
3237
'android.release': {
3338
type: 'android.apk',
34-
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
39+
testBinaryPath: 'android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk',
40+
binaryPath: 'android/app/build/outputs/apk/release/app-universal-release.apk',
3541
build:
3642
'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..',
43+
reversePorts,
3744
},
3845
},
3946
devices: {
@@ -46,7 +53,7 @@ module.exports = {
4653
emulator: {
4754
type: 'android.emulator',
4855
device: {
49-
avdName: 'Pixel_API_29_AOSP',
56+
avdName: 'Pixel_API_31_AOSP',
5057
},
5158
},
5259
},

.env.test.template

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ BACKUPS_SERVER_PUBKEY=0319c4ff23820afec0c79ce3a42031d7fef1dff78b7bdd69b5560684f3
2121
WEB_RELAY=https://webrelay.slashtags.to
2222

2323
# Blocktank
24-
BLOCKTANK_HOST=https://api1.blocktank.to/api
24+
BLOCKTANK_HOST=https://api.stag.blocktank.to
2525

2626
# Network
2727
ELECTRUM_BITCOIN_HOST=35.187.18.233

.github/workflows/e2e-android.yml

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
name: e2e-android
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
env:
12+
E2E_TESTS: 1 # build without transform-remove-console babel plugin
13+
DEBUG: 'lnurl* lnurl server'
14+
15+
jobs:
16+
e2e:
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 1
24+
25+
- name: Enable KVM group perms
26+
run: |
27+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
28+
sudo udevadm control --reload-rules
29+
sudo udevadm trigger --name-match=kvm
30+
31+
- name: Free Disk Space
32+
uses: jlumbroso/free-disk-space@main
33+
with:
34+
# this might remove tools that are actually needed,
35+
# if set to "true" but frees about 6 GB
36+
tool-cache: false
37+
android: false
38+
dotnet: true
39+
haskell: true
40+
large-packages: true
41+
docker-images: true
42+
swap-storage: true
43+
44+
- name: yarn and gradle caches in /mnt
45+
run: |
46+
rm -rf ~/.yarn
47+
rm -rf ~/.gradle
48+
sudo mkdir -p /mnt/.yarn
49+
sudo mkdir -p /mnt/.gradle
50+
sudo chown -R runner /mnt/.yarn
51+
sudo chown -R runner /mnt/.gradle
52+
ln -s /mnt/.yarn /home/runner/
53+
ln -s /mnt/.gradle /home/runner/
54+
55+
- name: Create artifacts directory on /mnt
56+
run: |
57+
sudo mkdir -p /mnt/artifacts
58+
sudo chown -R runner /mnt/artifacts
59+
60+
- name: Specify node version
61+
uses: actions/setup-node@v4
62+
with:
63+
node-version: 20
64+
65+
- name: Use gradle caches
66+
uses: actions/cache@v4
67+
with:
68+
path: |
69+
~/.gradle/caches
70+
~/.gradle/wrapper
71+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
72+
restore-keys: |
73+
${{ runner.os }}-gradle-
74+
75+
- name: Use yarn caches
76+
uses: actions/cache@v4
77+
with:
78+
path: ~/.yarn
79+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/package-lock.json') }}
80+
restore-keys: |
81+
${{ runner.os }}-yarn-
82+
83+
- name: Activate enviroment variables
84+
run: cp .env.test.template .env
85+
86+
- name: Yarn Install
87+
run: yarn || yarn
88+
env:
89+
HUSKY: 0
90+
91+
- name: Activate Gradle variables
92+
run: |
93+
cp .github/workflows/gradle.properties ~/.gradle/gradle.properties
94+
patch -p1 -i ./.github/workflows/react-native-quick-crypto.patch
95+
96+
- name: Use specific Java version for sdkmanager to work
97+
uses: actions/setup-java@v4
98+
with:
99+
distribution: 'temurin'
100+
java-version: '17'
101+
102+
- name: Build
103+
run: yarn e2e:build:android-release || yarn e2e:build:android-release
104+
105+
- name: Show build outputs
106+
run: tree android/app/build/outputs/
107+
108+
- name: Kill java processes
109+
run: pkill -9 -f java || true
110+
111+
- name: Run regtest setup
112+
run: |
113+
cd docker
114+
mkdir lnd && chmod 777 lnd
115+
docker-compose pull --quiet
116+
docker compose up -d
117+
118+
- name: Wait for electrum server and LND
119+
timeout-minutes: 10
120+
run: |
121+
while ! nc -z '127.0.0.1' 60001; do sleep 1; done
122+
while ! nc -z '127.0.0.1' 10009; do sleep 1; done
123+
sudo chmod -R 777 docker/lnd
124+
125+
- name: Test attempt 1
126+
continue-on-error: true
127+
id: test1
128+
uses: reactivecircus/android-emulator-runner@v2
129+
with:
130+
profile: 5.4in FWVGA # devices list: avdmanager list device
131+
api-level: 31
132+
avd-name: Pixel_API_31_AOSP
133+
force-avd-creation: false
134+
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
135+
arch: x86_64
136+
script: yarn e2e:test:android-release --record-videos all --record-logs all --take-screenshots all --headless -d 200000 --artifacts-location /mnt/artifacts
137+
138+
- name: Test attempt 2
139+
continue-on-error: true
140+
id: test2
141+
if: steps.test1.outcome != 'success'
142+
uses: reactivecircus/android-emulator-runner@v2
143+
with:
144+
profile: 5.4in FWVGA # devices list: avdmanager list device
145+
api-level: 31
146+
avd-name: Pixel_API_31_AOSP
147+
force-avd-creation: false
148+
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
149+
arch: x86_64
150+
script: yarn e2e:test:android-release --record-videos all --record-logs all --take-screenshots all --headless -d 200000 --artifacts-location /mnt/artifacts
151+
152+
- name: Test attempt 3
153+
continue-on-error: true
154+
id: test3
155+
if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success'
156+
uses: reactivecircus/android-emulator-runner@v2
157+
with:
158+
profile: 5.4in FWVGA # devices list: avdmanager list device
159+
api-level: 31
160+
avd-name: Pixel_API_31_AOSP
161+
force-avd-creation: false
162+
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
163+
arch: x86_64
164+
script: yarn e2e:test:android-release --record-videos all --record-logs all --take-screenshots all --headless -d 200000 --artifacts-location /mnt/artifacts
165+
166+
- name: Restart docker before last attempt
167+
if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' && steps.test3.outcome != 'success'
168+
run: |
169+
cd docker && docker compose down -t 60 && docker compose up --quiet-pull -d && cd ..
170+
while ! nc -z '127.0.0.1' 60001; do sleep 1; done
171+
172+
- name: Test attempt 4
173+
if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' && steps.test3.outcome != 'success'
174+
uses: reactivecircus/android-emulator-runner@v2
175+
with:
176+
profile: 5.4in FWVGA # devices list: avdmanager list device
177+
api-level: 31
178+
avd-name: Pixel_API_31_AOSP
179+
force-avd-creation: false
180+
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
181+
arch: x86_64
182+
script: yarn e2e:test:android-release --record-videos all --record-logs all --take-screenshots all --headless -d 200000 --artifacts-location /mnt/artifacts
183+
184+
- uses: actions/upload-artifact@v4
185+
if: failure()
186+
with:
187+
name: e2e-test-videos
188+
path: /mnt/artifacts/
189+
190+
- name: Dump docker logs on failure
191+
if: failure()
192+
uses: jwalton/gh-docker-logs@v2

.github/workflows/e2e-ios-macmini.yml .github/workflows/e2e-ios.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: e2e-ios-macmini
1+
name: e2e-ios
22

33
on:
44
workflow_dispatch:

.github/workflows/gradle.properties

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
BITKIT_UPLOAD_STORE_FILE=debug.keystore
2+
BITKIT_UPLOAD_STORE_PASSWORD=android
3+
BITKIT_UPLOAD_KEY_ALIAS=androiddebugkey
4+
BITKIT_UPLOAD_KEY_PASSWORD=android
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
diff --git a/node_modules/react-native-quick-crypto/android/build.gradle b/node_modules/react-native-quick-crypto/android/build.gradle
2+
index 2ac6c0db..57afa566 100644
3+
--- a/node_modules/react-native-quick-crypto/android/build.gradle
4+
+++ b/node_modules/react-native-quick-crypto/android/build.gradle
5+
@@ -94,6 +94,8 @@ android {
6+
""
7+
]
8+
doNotStrip '**/*.so'
9+
+ pickFirst 'META-INF/com.android.tools/proguard/coroutines.pro'
10+
+ pickFirst 'META-INF/proguard/coroutines.pro'
11+
}
12+
13+
buildTypes {

android/app/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ android {
8484
versionName "1.0.1"
8585
multiDexEnabled true
8686
missingDimensionStrategy 'react-native-camera', 'general'
87+
testBuildType System.getProperty('testBuildType', 'debug')
88+
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
8789
}
8890

8991
signingConfigs {
@@ -112,6 +114,7 @@ android {
112114
signingConfig signingConfigs.release
113115
minifyEnabled enableProguardInReleaseBuilds
114116
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
117+
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
115118
}
116119
}
117120
splits {
@@ -139,6 +142,7 @@ android {
139142
}
140143

141144
dependencies {
145+
androidTestImplementation('com.wix:detox:+')
142146
// The version of react-native is set by the React Native Gradle Plugin
143147
implementation("com.facebook.react:react-android")
144148
implementation files("../../node_modules/@synonymdev/react-native-ldk/android/libs/LDK-release.aar")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.bitkit;
2+
3+
import com.wix.detox.Detox;
4+
import com.wix.detox.config.DetoxConfig;
5+
6+
import org.junit.Rule;
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import androidx.test.ext.junit.runners.AndroidJUnit4;
11+
import androidx.test.filters.LargeTest;
12+
import androidx.test.rule.ActivityTestRule;
13+
14+
@RunWith(AndroidJUnit4.class)
15+
@LargeTest
16+
public class DetoxTest {
17+
@Rule
18+
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
19+
20+
@Test
21+
public void runDetoxTests() {
22+
DetoxConfig detoxConfig = new DetoxConfig();
23+
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
24+
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
25+
detoxConfig.rnContextLoadTimeoutSec = (BuildConfig.DEBUG ? 180 : 60);
26+
27+
Detox.runTests(mActivityRule, detoxConfig);
28+
}
29+
}

android/app/src/main/AndroidManifest.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
android:roundIcon="@mipmap/ic_launcher_orange_round"
3131
android:allowBackup="false"
3232
android:usesCleartextTraffic="true"
33-
android:theme="@style/AppTheme">
33+
android:theme="@style/AppTheme"
34+
android:networkSecurityConfig="@xml/network_security_config">
3435
<activity
3536
android:name=".MainActivity"
3637
android:label="@string/app_name"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<network-security-config>
3+
<domain-config cleartextTrafficPermitted="true">
4+
<domain includeSubdomains="true">10.0.2.2</domain>
5+
<domain includeSubdomains="true">localhost</domain>
6+
<domain includeSubdomains="true">127.0.0.1</domain>
7+
</domain-config>
8+
</network-security-config>

android/build.gradle

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ buildscript {
77
compileSdkVersion = 34
88
targetSdkVersion = 34
99
kotlin_version = "1.8.0"
10+
kotlinVersion = "1.8.0"
1011
ndkVersion = "25.2.9519653"
1112
}
1213
repositories {
@@ -21,3 +22,9 @@ buildscript {
2122
}
2223

2324
apply plugin: "com.facebook.react.rootproject"
25+
26+
allprojects {
27+
repositories {
28+
maven { url("$rootDir/../node_modules/detox/Detox-android") }
29+
}
30+
}

0 commit comments

Comments
 (0)