Skip to content

Commit ee5b263

Browse files
committed
feat: andoid e2e tests
1 parent 47f0b1e commit ee5b263

18 files changed

+375
-98
lines changed

.detoxrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module.exports = {
4242
emulator: {
4343
type: 'android.emulator',
4444
device: {
45-
avdName: 'Pixel_API_29_AOSP',
45+
avdName: 'Pixel_API_31_AOSP',
4646
},
4747
},
4848
},

.github/workflows/e2e-android.yml

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
name: e2e-android
2+
3+
on: pull_request
4+
5+
env:
6+
E2E_TESTS: 1 # build without transform-remove-console babel plugin
7+
DEBUG: 'lnurl* lnurl server'
8+
9+
jobs:
10+
e2e:
11+
runs-on: macos-12
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v3
16+
with:
17+
fetch-depth: 1
18+
19+
- name: Setup Docker Colima 1
20+
uses: douglascamata/setup-docker-macos-action@v1-alpha
21+
id: docker1
22+
continue-on-error: true
23+
24+
- name: Setup Docker Colima 2
25+
if: steps.docker1.outcome != 'success'
26+
uses: douglascamata/setup-docker-macos-action@v1-alpha
27+
id: docker2
28+
continue-on-error: true
29+
30+
- name: Setup Docker Default
31+
if: steps.docker1.outcome != 'success' && steps.docker2.outcome != 'success'
32+
uses: docker-practice/[email protected]
33+
timeout-minutes: 30
34+
35+
- name: Run regtest setup
36+
run: cd docker && mkdir lnd && chmod 777 lnd && docker-compose up -d
37+
38+
- name: Wait for bitcoind
39+
timeout-minutes: 2
40+
run: while ! nc -z '127.0.0.1' 43782; do sleep 1; done
41+
42+
- name: Wait for electrum server
43+
timeout-minutes: 2
44+
run: while ! nc -z '127.0.0.1' 60001; do sleep 1; done
45+
46+
- name: Setup Node
47+
uses: actions/setup-node@v3
48+
with:
49+
node-version: 18.17
50+
cache: 'yarn' # cache packages, but not node_modules
51+
52+
- name: Activate enviroment variables
53+
run: cp .env.test.template .env
54+
55+
- name: Activate react-native-skia-stub
56+
run: patch -p1 < .github/workflows/react-native-skia-stub.patch
57+
58+
- name: Activate Gradle variables
59+
run: cp .github/workflows/gradle.properties ~/.gradle/gradle.properties
60+
61+
- name: Use specific Java version for sdkmanager to work
62+
uses: actions/setup-java@v2
63+
with:
64+
distribution: 'temurin'
65+
java-version: '11'
66+
67+
- name: Yarn Install
68+
run: yarn --no-audit --prefer-offline || yarn --no-audit --prefer-offline
69+
env:
70+
HUSKY: 0
71+
72+
- name: Build
73+
run: yarn e2e:build:android-release || yarn e2e:build:android-release
74+
75+
- name: Test attempt 1
76+
uses: reactivecircus/android-emulator-runner@v2
77+
# continue-on-error: true
78+
id: test1
79+
with:
80+
api-level: 31
81+
avd-name: Pixel_API_31_AOSP
82+
force-avd-creation: false
83+
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
84+
arch: x86_64
85+
script: |
86+
adb root
87+
adb reverse tcp:80 tcp:80
88+
adb reverse tcp:8080 tcp:8080
89+
adb reverse tcp:9735 tcp:9735
90+
adb reverse tcp:10009 tcp:10009
91+
adb reverse tcp:28334 tcp:28334
92+
adb reverse tcp:28335 tcp:28335
93+
adb reverse tcp:28336 tcp:28336
94+
adb reverse tcp:39388 tcp:39388
95+
adb reverse tcp:43782 tcp:43782
96+
adb reverse tcp:60001 tcp:60001
97+
yarn e2e:test:android-release --record-videos all --take-screenshots all --record-logs all
98+
99+
# - name: Test attempt 2
100+
# uses: reactivecircus/android-emulator-runner@v2
101+
# continue-on-error: true
102+
# id: test2
103+
# if: steps.test1.outcome != 'success'
104+
# with:
105+
# api-level: 31
106+
# avd-name: Pixel_API_31_AOSP
107+
# force-avd-creation: false
108+
# emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
109+
# arch: x86_64
110+
# script: |
111+
# adb root
112+
# adb reverse tcp:80 tcp:80
113+
# adb reverse tcp:8080 tcp:8080
114+
# adb reverse tcp:9735 tcp:9735
115+
# adb reverse tcp:10009 tcp:10009
116+
# adb reverse tcp:28334 tcp:28334
117+
# adb reverse tcp:28335 tcp:28335
118+
# adb reverse tcp:28336 tcp:28336
119+
# adb reverse tcp:39388 tcp:39388
120+
# adb reverse tcp:43782 tcp:43782
121+
# adb reverse tcp:60001 tcp:60001
122+
# yarn e2e:test:android-release --record-videos all --take-screenshots all --record-logs all
123+
124+
# - name: Test attempt 3
125+
# uses: reactivecircus/android-emulator-runner@v2
126+
# continue-on-error: true
127+
# id: test3
128+
# if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success'
129+
# with:
130+
# api-level: 31
131+
# avd-name: Pixel_API_31_AOSP
132+
# force-avd-creation: false
133+
# emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
134+
# arch: x86_64
135+
# script: |
136+
# adb root
137+
# adb reverse tcp:80 tcp:80
138+
# adb reverse tcp:8080 tcp:8080
139+
# adb reverse tcp:9735 tcp:9735
140+
# adb reverse tcp:10009 tcp:10009
141+
# adb reverse tcp:28334 tcp:28334
142+
# adb reverse tcp:28335 tcp:28335
143+
# adb reverse tcp:28336 tcp:28336
144+
# adb reverse tcp:39388 tcp:39388
145+
# adb reverse tcp:43782 tcp:43782
146+
# adb reverse tcp:60001 tcp:60001
147+
# yarn e2e:test:android-release --record-videos all --take-screenshots all --record-logs all
148+
149+
# - name: Test attempt 4
150+
# uses: reactivecircus/android-emulator-runner@v2
151+
# if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' && steps.test3.outcome != 'success'
152+
# with:
153+
# api-level: 31
154+
# avd-name: Pixel_API_31_AOSP
155+
# force-avd-creation: false
156+
# emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
157+
# arch: x86_64
158+
# script: |
159+
# adb root
160+
# adb reverse tcp:80 tcp:80
161+
# adb reverse tcp:8080 tcp:8080
162+
# adb reverse tcp:9735 tcp:9735
163+
# adb reverse tcp:10009 tcp:10009
164+
# adb reverse tcp:28334 tcp:28334
165+
# adb reverse tcp:28335 tcp:28335
166+
# adb reverse tcp:28336 tcp:28336
167+
# adb reverse tcp:39388 tcp:39388
168+
# adb reverse tcp:43782 tcp:43782
169+
# adb reverse tcp:60001 tcp:60001
170+
# yarn e2e:test:android-release --record-videos all --take-screenshots all --record-logs all
171+
172+
- uses: actions/upload-artifact@v3
173+
if: failure()
174+
with:
175+
name: e2e-test-videos
176+
path: ./artifacts/
177+
178+
- name: Dump docker logs on failure
179+
if: failure()
180+
uses: jwalton/gh-docker-logs@v2

.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

android/app/build.gradle

+14
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ android {
102102
versionName "1.0"
103103
multiDexEnabled true
104104
missingDimensionStrategy 'react-native-camera', 'general'
105+
testBuildType System.getProperty('testBuildType', 'debug')
106+
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
105107
}
106108

107109
splits {
@@ -138,6 +140,7 @@ android {
138140
signingConfig signingConfigs.release
139141
minifyEnabled enableProguardInReleaseBuilds
140142
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
143+
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
141144
}
142145
}
143146

@@ -159,6 +162,9 @@ android {
159162
}
160163

161164
dependencies {
165+
androidTestImplementation('com.wix:detox:+')
166+
implementation 'com.google.android.material:material:1.3.0' // FIXME https://github.com/wix/Detox/issues/2846
167+
implementation 'androidx.appcompat:appcompat:1.1.0'
162168
// The version of react-native is set by the React Native Gradle Plugin
163169
implementation("com.facebook.react:react-android")
164170
implementation files("../../node_modules/@synonymdev/react-native-ldk/android/libs/LDK-release.aar")
@@ -180,3 +186,11 @@ dependencies {
180186
}
181187

182188
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
189+
190+
// DETOX workaround
191+
// https://github.com/wix/Detox/issues/3867#issuecomment-1540477784
192+
configurations.all {
193+
resolutionStrategy {
194+
force 'androidx.test:core:1.5.0'
195+
}
196+
}
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
@@ -27,7 +27,8 @@
2727
android:roundIcon="@mipmap/ic_launcher_round"
2828
android:allowBackup="false"
2929
android:usesCleartextTraffic="true"
30-
android:theme="@style/AppTheme">
30+
android:theme="@style/AppTheme"
31+
android:networkSecurityConfig="@xml/network_security_config">
3132
<activity
3233
android:name=".MainActivity"
3334
android:label="@string/app_name"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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-config>
7+
</network-security-config>

android/build.gradle

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ buildscript {
66
minSdkVersion = 24
77
compileSdkVersion = 33
88
targetSdkVersion = 33
9-
kotlin_version = '1.8.0'
9+
kotlin_version = "1.8.21"
1010
ndkVersion = "25.1.8937393"
1111
}
1212
repositories {
@@ -20,3 +20,9 @@ buildscript {
2020
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
2121
}
2222
}
23+
24+
allprojects {
25+
repositories {
26+
maven { url("$rootDir/../node_modules/detox/Detox-android") }
27+
}
28+
}

e2e/channels.e2e.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import BitcoinJsonRpc from 'bitcoin-json-rpc';
22
import jestExpect from 'expect';
3+
import { device } from 'detox';
34

45
import initWaitForElectrumToSync from '../__tests__/utils/wait-for-electrum';
56
import {
@@ -126,7 +127,7 @@ d('LN Channel Onboarding', () => {
126127
await expect(element(by.text('200 000'))).toBeVisible();
127128

128129
// Swipe to confirm (set x offset to avoid navigating back)
129-
await element(by.id('GRAB')).swipe('right', 'slow', NaN, 0.8);
130+
await element(by.id('GRAB')).swipe('right', 'slow', 0.9);
130131
await waitFor(element(by.id('LightningSettingUp')))
131132
.toBeVisible()
132133
.withTimeout(10000);
@@ -156,7 +157,11 @@ d('LN Channel Onboarding', () => {
156157
jestExpect(buttonEnabled2).toBe(false);
157158

158159
// go back and change to 2nd card
159-
await element(by.id('NavigationBack')).atIndex(1).tap();
160+
if (device.getPlatform() === 'ios') {
161+
await element(by.id('NavigationBack')).atIndex(1).tap(); // ios
162+
} else {
163+
await element(by.id('NavigationBack')).atIndex(0).tap(); // android
164+
}
160165
await element(by.id('Barrel-medium')).tap();
161166
await element(by.id('CustomSetupContinue')).tap();
162167
await element(by.id('Barrel-medium')).tap();
@@ -178,7 +183,7 @@ d('LN Channel Onboarding', () => {
178183
// await expect(element(by.text('1 week'))).toBeVisible();
179184

180185
// Swipe to confirm (set x offset to avoid navigating back)
181-
await element(by.id('GRAB')).swipe('right', 'slow', NaN, 0.8);
186+
await element(by.id('GRAB')).swipe('right', 'slow', 0.9);
182187
await waitFor(element(by.id('LightningSettingUp')))
183188
.toBeVisible()
184189
.withTimeout(10000);

0 commit comments

Comments
 (0)