Skip to content

Commit 7f0e7d8

Browse files
committed
ci: use detox for ui test, opt code
1 parent 1c62250 commit 7f0e7d8

File tree

24 files changed

+1692
-1034
lines changed

24 files changed

+1692
-1034
lines changed

example/.detoxrc.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/** @type {Detox.DetoxConfig} */
2+
module.exports = {
3+
testRunner: {
4+
args: {
5+
'$0': 'jest',
6+
config: 'e2e/jest.config.js'
7+
},
8+
jest: {
9+
setupTimeout: 120000
10+
}
11+
},
12+
apps: {
13+
'ios.debug': {
14+
type: 'ios.app',
15+
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/ImageMarkerExample.app',
16+
build: 'xcodebuild -workspace ios/ImageMarkerExample.xcworkspace -scheme ImageMarkerExample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build'
17+
},
18+
'ios.release': {
19+
type: 'ios.app',
20+
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/ImageMarkerExample.app',
21+
build: 'xcodebuild -workspace ios/ImageMarkerExample.xcworkspace -scheme ImageMarkerExample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
22+
},
23+
'android.debug': {
24+
type: 'android.apk',
25+
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
26+
build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
27+
reversePorts: [
28+
8081
29+
]
30+
},
31+
'android.release': {
32+
type: 'android.apk',
33+
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
34+
build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release'
35+
}
36+
},
37+
devices: {
38+
simulator: {
39+
type: 'ios.simulator',
40+
device: {
41+
type: 'iPhone 15'
42+
}
43+
},
44+
attached: {
45+
type: 'android.attached',
46+
device: {
47+
adbName: '.*'
48+
}
49+
},
50+
emulator: {
51+
type: 'android.emulator',
52+
device: {
53+
avdName: 'Pixel_XL_API_34'
54+
}
55+
}
56+
},
57+
configurations: {
58+
'ios.sim.debug': {
59+
device: 'simulator',
60+
app: 'ios.debug'
61+
},
62+
'ios.sim.release': {
63+
device: 'simulator',
64+
app: 'ios.release'
65+
},
66+
'android.att.debug': {
67+
device: 'attached',
68+
app: 'android.debug'
69+
},
70+
'android.att.release': {
71+
device: 'attached',
72+
app: 'android.release'
73+
},
74+
'android.emu.debug': {
75+
device: 'emulator',
76+
app: 'android.debug'
77+
},
78+
'android.emu.release': {
79+
device: 'emulator',
80+
app: 'android.release'
81+
}
82+
}
83+
};

example/android/app/build.gradle

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: "com.android.application"
22
apply plugin: "com.facebook.react"
33
apply plugin: 'kotlin-android'
44

5-
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["kotlin_version"]
5+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["ImageMarkerExample_kotlinVersion"]
66

77
import com.android.build.OutputFile
88

@@ -103,6 +103,8 @@ android {
103103
targetSdkVersion rootProject.ext.targetSdkVersion
104104
versionCode 1
105105
versionName "1.0"
106+
testBuildType System.getProperty('testBuildType', 'debug')
107+
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
106108
}
107109

108110
splits {
@@ -137,6 +139,7 @@ android {
137139
signingConfig signingConfigs.release
138140
minifyEnabled enableProguardInReleaseBuilds
139141
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
142+
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
140143
}
141144
}
142145

@@ -171,6 +174,10 @@ dependencies {
171174
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
172175
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
173176
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
177+
androidTestImplementation('com.wix:detox:+')
178+
implementation 'androidx.appcompat:appcompat:1.1.0'
179+
implementation project(':react-native-vector-icons')
174180
}
175181

176182
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
183+
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.imagemarkerexample;
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 // (2)
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+
}

example/android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
android:icon="@mipmap/ic_launcher"
99
android:roundIcon="@mipmap/ic_launcher_round"
1010
android:allowBackup="false"
11+
android:networkSecurityConfig="@xml/network_security_config"
12+
android:usesCleartextTraffic="true"
1113
android:theme="@style/AppTheme">
1214
<activity
1315
android:name=".MainActivity"
Lines changed: 7 additions & 0 deletions
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>

example/android/build.gradle

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["kotlin_version"]
4+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["ImageMarkerExample_kotlinVersion"]
55

66
ext {
77
buildToolsVersion = "34.0.0"
@@ -21,6 +21,9 @@ buildscript {
2121
maven { url "https://repository.jboss.org/maven2" }
2222
maven { url 'https://maven.google.com' }
2323
maven { url 'https://maven.fabric.io/public' }
24+
maven {
25+
url("$rootDir/../node_modules/detox/Detox-android")
26+
}
2427
}
2528
dependencies {
2629
classpath("com.android.tools.build:gradle")
@@ -29,4 +32,19 @@ buildscript {
2932
}
3033
}
3134

35+
allprojects {
36+
repositories {
37+
google()
38+
mavenCentral()
39+
jcenter()
40+
maven { url 'https://dl.google.com/dl/android/maven2' }
41+
maven { url "https://repository.jboss.org/maven2" }
42+
maven { url 'https://maven.google.com' }
43+
maven { url 'https://maven.fabric.io/public' }
44+
maven {
45+
url("$rootDir/../node_modules/detox/Detox-android")
46+
}
47+
}
48+
}
49+
3250
apply plugin: "com.facebook.react.rootproject"

example/android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ newArchEnabled=false
4040
# If set to false, you will be using JSC instead.
4141
hermesEnabled=true
4242

43-
kotlin_version=1.8.0
43+
ImageMarkerExample_kotlinVersion=1.8.0

example/android/settings.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
rootProject.name = 'ImageMarkerExample'
22
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
33
include ':app'
4-
includeBuild('../node_modules/@react-native/gradle-plugin')
4+
includeBuild('../node_modules/react-native-gradle-plugin')
5+
include ':react-native-vector-icons'
6+
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')

example/babel.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@ module.exports = {
1414
},
1515
],
1616
],
17+
env: {
18+
production: {
19+
plugins: ['react-native-paper/babel'],
20+
},
21+
},
1722
};

example/e2e/App.test.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { device, element, by, waitFor } from 'detox';
2+
import assert from 'power-assert';
3+
4+
describe('e2e/App.test.js', () => {
5+
beforeAll(async () => {
6+
await device.launchApp();
7+
});
8+
9+
beforeEach(async () => {
10+
await device.reloadReactNative();
11+
});
12+
13+
it('should display correctly', async () => {
14+
await expect(element(by.id('backgroundImageFormatLabel'))).toBeVisible();
15+
await expect(element(by.id('backgroundImageFormatLabel'))).toHaveText(
16+
'background image format:'
17+
);
18+
19+
await expect(element(by.id('backgroundImageFormatBtn'))).toBeVisible();
20+
await expect(element(by.id('backgroundImageFormatBtn'))).toHaveLabel(
21+
'image'
22+
);
23+
24+
await expect(element(by.id('watermarkTypeLabel'))).toBeVisible();
25+
await expect(element(by.id('watermarkTypeLabel'))).toHaveText(
26+
'watermark type:'
27+
);
28+
29+
await expect(element(by.id('watermarkTypeBtn'))).toBeVisible();
30+
await expect(element(by.id('watermarkTypeBtn'))).toHaveLabel('text');
31+
32+
await expect(element(by.id('exportResultFormatLabel'))).toBeVisible();
33+
await expect(element(by.id('exportResultFormatLabel'))).toHaveText(
34+
'export result format:'
35+
);
36+
37+
await expect(element(by.id('exportResultFormatBtn'))).toBeVisible();
38+
await expect(element(by.id('exportResultFormatBtn'))).toHaveLabel('png');
39+
40+
await expect(element(by.id('selectBgBtn'))).toBeVisible();
41+
await expect(element(by.id('selectBgBtn'))).toHaveLabel('select bg');
42+
43+
// await expect(element(by.id('selectWatermarkBtn'))).toBeVisible();
44+
// await expect(element(by.id('selectWatermarkBtn'))).toHaveLabel(
45+
// 'select watermark'
46+
// );
47+
48+
await expect(element(by.id('resultFileSizeLabel'))).toBeVisible();
49+
await expect(element(by.id('resultFilePathLabel'))).toBeVisible();
50+
if (device.getPlatform() === 'ios') {
51+
const resultFileSizeLabel = await element(
52+
by.id('resultFileSizeLabel')
53+
).getAttributes('text');
54+
55+
assert.ok(
56+
/^result file size:\d+(.\d+)?\s(KB|MB)$/.test(resultFileSizeLabel.text)
57+
);
58+
const resultFilePathLabel = await element(
59+
by.id('resultFilePathLabel')
60+
).getAttributes('text');
61+
assert.ok(/^file path:.*\.png$/.test(resultFilePathLabel.text));
62+
} else {
63+
await expect(element(by.id('resultFileSizeLabel'))).toHaveLabel(
64+
/^result file size:\d+(\.\d+)?\s(KB|MB)$/
65+
);
66+
await expect(element(by.id('resultFilePathLabel'))).toBeVisible();
67+
await expect(element(by.id('resultFilePathLabel'))).toHaveText(
68+
/^file path:.*\.png$/
69+
);
70+
}
71+
72+
await expect(element(by.id('resultImage'))).toBeVisible();
73+
});
74+
75+
describe('when click backgroundImageFormatBtn', () => {
76+
it('should display correctly', async () => {
77+
await expect(element(by.id('backgroundImageFormatBtn'))).toHaveLabel(
78+
'image'
79+
);
80+
await element(by.id('backgroundImageFormatBtn')).tap();
81+
await waitFor(element(by.type('RCTModalHostView')))
82+
.toBeVisible()
83+
.withTimeout(2000);
84+
await element(by.label('base64')).tap();
85+
await expect(element(by.id('backgroundImageFormatBtn'))).toHaveLabel(
86+
'base64'
87+
);
88+
});
89+
});
90+
});

0 commit comments

Comments
 (0)