detox 20.14.2-smoke.0 → 20.14.3
Sign up to get free protection for your applications and to get access to all the features.
- package/Detox-android/com/wix/detox/{20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar → 20.14.3/detox-20.14.3-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar → 20.14.3/detox-20.14.3-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.aar +0 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.14.2-smoke.0/detox-20.14.2-smoke.0.pom → 20.14.3/detox-20.14.3.pom} +4 -4
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.14.3/detox-20.14.3.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/detox/build.gradle +4 -4
- package/android/detox/proguard-rules-app.pro +3 -0
- package/android/detox/src/full/java/com/wix/detox/Detox.java +70 -8
- package/android/detox/src/full/java/com/wix/detox/DetoxMain.kt +44 -69
- package/android/detox/src/full/java/com/wix/detox/LaunchIntentsFactory.kt +1 -1
- package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxActionHandlers.kt +4 -0
- package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxActionsDispatcher.kt +6 -16
- package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxServerAdapter.kt +2 -0
- package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxServerInfo.kt +2 -4
- package/android/detox/src/full/java/com/wix/detox/espresso/assertion/ViewAssertions.java +2 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +32 -25
- package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +3 -0
- package/package.json +3 -4
- package/runners/jest/testEnvironment/index.js +9 -23
- package/src/android/espressoapi/Detox.js +11 -0
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0.pom.sha512 +0 -1
- package/android/detox/src/full/java/com/wix/detox/ActivityLaunchHelper.kt +0 -76
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactMarkersLogger.kt +0 -44
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
3b1d7b9d4af2ad509d1e2986540f5208
|
@@ -0,0 +1 @@
|
|
1
|
+
4e8792170dfbac074d9e5fc88548c9e85b05dd67
|
@@ -0,0 +1 @@
|
|
1
|
+
57e41d5affbdcb771d08c680235f5ed17534420bfee9c6489c0baf2c4550d857
|
@@ -0,0 +1 @@
|
|
1
|
+
fb2650ae7ae4e56953fcfc7579bdf99bebedeed3cc575413bf56b6251362853fe5c16f17a490d031742b16e4735f009513d93a89636f8c069f06bc34f5a2b205
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
16eebdb32005b5bc0474d0426e92a7ef
|
@@ -0,0 +1 @@
|
|
1
|
+
858e7440d43d7dd6155435c778dc20cddde0eac9
|
@@ -0,0 +1 @@
|
|
1
|
+
be627415e355baea1337b7efd541614ba258290227b23f11b943c774fffeafa8
|
@@ -0,0 +1 @@
|
|
1
|
+
e489a68066a5e07dbaed4b780e81453755e5ef9f31cb0fe1125cbf156e3ccef0a34cc00abdb84f4788a864ac9c1a4b8c1d8bef1d30ce2eaec8903758c211873c
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
070f7c4048400fe1d6b1599414f5c7f1
|
@@ -0,0 +1 @@
|
|
1
|
+
52ebf8f7cd97ab4d28216ce8504635be1f74b57c
|
@@ -0,0 +1 @@
|
|
1
|
+
42299d1835b5db9fe3b7523d2d656a8834fff583ae82521ff69b9e050814ce3a
|
@@ -0,0 +1 @@
|
|
1
|
+
aeecbc2448822395dc7d9674c0a30f5cffd9cacd8361bd55a1a4f0bb8cafe82cb812fbe1da890395cfcc65439dcb4666e119a356a054c582cb7dfe225fb9d858
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
4
4
|
<groupId>com.wix</groupId>
|
5
5
|
<artifactId>detox</artifactId>
|
6
|
-
<version>20.14.
|
6
|
+
<version>20.14.3</version>
|
7
7
|
<packaging>aar</packaging>
|
8
8
|
<name>Detox</name>
|
9
9
|
<description>Gray box end-to-end testing and automation library for mobile apps</description>
|
@@ -33,19 +33,19 @@
|
|
33
33
|
<dependency>
|
34
34
|
<groupId>androidx.test.espresso</groupId>
|
35
35
|
<artifactId>espresso-core</artifactId>
|
36
|
-
<version>3.
|
36
|
+
<version>3.5.1</version>
|
37
37
|
<scope>compile</scope>
|
38
38
|
</dependency>
|
39
39
|
<dependency>
|
40
40
|
<groupId>androidx.test.espresso</groupId>
|
41
41
|
<artifactId>espresso-web</artifactId>
|
42
|
-
<version>3.
|
42
|
+
<version>3.5.1</version>
|
43
43
|
<scope>compile</scope>
|
44
44
|
</dependency>
|
45
45
|
<dependency>
|
46
46
|
<groupId>androidx.test.espresso</groupId>
|
47
47
|
<artifactId>espresso-contrib</artifactId>
|
48
|
-
<version>3.
|
48
|
+
<version>3.5.1</version>
|
49
49
|
<scope>compile</scope>
|
50
50
|
<exclusions>
|
51
51
|
<exclusion>
|
@@ -0,0 +1 @@
|
|
1
|
+
a69ee7399f34d05477dad353196d10ce
|
@@ -0,0 +1 @@
|
|
1
|
+
fdd3056e3977c32501d0aba7e0b71fa9cc706384
|
@@ -0,0 +1 @@
|
|
1
|
+
6ff96bda411d85d30d6075a8485e8a463c807e4673d4b038ef331bb67b31a577
|
@@ -0,0 +1 @@
|
|
1
|
+
ea6781750ec935a59476e178814f6d5b0eb3f5a3559e6f19a69b86c321a21641dd49f103adcd6843b68c27f530bdbb24eb838e35e933e931c30a2e567a8c9996
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<groupId>com.wix</groupId>
|
4
4
|
<artifactId>detox</artifactId>
|
5
5
|
<versioning>
|
6
|
-
<latest>20.14.
|
7
|
-
<release>20.14.
|
6
|
+
<latest>20.14.3</latest>
|
7
|
+
<release>20.14.3</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.14.
|
9
|
+
<version>20.14.3</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20231219153636</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
fc0fd4a19cec1d107b1bd9fd90013cf4
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
6d3386088773329bf556fbe64b844403f2b8f037
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
7e9f03941de1513d09d0e46256c9545fb517e0a1736ef1dc38590f347ff4c515
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
05bb3d2da873b14e798fdf91cf1e41976b36bdbb1dbc1713ff0e9d28010b2856146dff2146f145c7e928eb678939be02b7d9e5c413ad52296951468284daaf85
|
package/Detox-ios-src.tbz
CHANGED
Binary file
|
package/Detox-ios.tbz
CHANGED
Binary file
|
@@ -101,13 +101,13 @@ dependencies {
|
|
101
101
|
// Versions are in-sync with the 'androidx-test-1.4.0' release/tag of the android-test github repo,
|
102
102
|
// used by the Detox generator. See https://github.com/android/android-test/releases/tag/androidx-test-1.4.0
|
103
103
|
// Important: Should remain so when generator tag is replaced!
|
104
|
-
api('androidx.test.espresso:espresso-core:3.
|
104
|
+
api('androidx.test.espresso:espresso-core:3.5.1') {
|
105
105
|
because 'Needed all across Detox but also makes Espresso seamlessly provided to Detox users with hybrid apps/E2E-tests.'
|
106
106
|
}
|
107
|
-
api('androidx.test.espresso:espresso-web:3.
|
107
|
+
api('androidx.test.espresso:espresso-web:3.5.1') {
|
108
108
|
because 'Web-View testing'
|
109
109
|
}
|
110
|
-
api('androidx.test.espresso:espresso-contrib:3.
|
110
|
+
api('androidx.test.espresso:espresso-contrib:3.5.1') {
|
111
111
|
because 'Android datepicker support'
|
112
112
|
exclude group: "org.checkerframework", module: "checker"
|
113
113
|
}
|
@@ -150,7 +150,7 @@ dependencies {
|
|
150
150
|
testImplementation "org.jetbrains.kotlin:kotlin-test:$_kotlinVersion"
|
151
151
|
testImplementation 'org.apache.commons:commons-io:1.3.2'
|
152
152
|
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.0.0'
|
153
|
-
testImplementation 'org.robolectric:robolectric:4.
|
153
|
+
testImplementation 'org.robolectric:robolectric:4.11.1'
|
154
154
|
|
155
155
|
testImplementation("com.google.android.material:material:$_materialMinVersion") {
|
156
156
|
because 'Material components are mentioned explicitly (e.g. Slider in get-attributes handler)'
|
@@ -1,13 +1,18 @@
|
|
1
1
|
package com.wix.detox;
|
2
2
|
|
3
|
+
import android.app.Activity;
|
4
|
+
import android.app.Instrumentation;
|
3
5
|
import android.content.Context;
|
6
|
+
import android.content.Intent;
|
7
|
+
import android.os.Bundle;
|
8
|
+
|
9
|
+
import com.wix.detox.config.DetoxConfig;
|
10
|
+
import com.wix.detox.espresso.UiControllerSpy;
|
4
11
|
|
5
12
|
import androidx.annotation.NonNull;
|
6
13
|
import androidx.test.platform.app.InstrumentationRegistry;
|
7
14
|
import androidx.test.rule.ActivityTestRule;
|
8
15
|
|
9
|
-
import com.wix.detox.config.DetoxConfig;
|
10
|
-
|
11
16
|
/**
|
12
17
|
* <p>Static class.</p>
|
13
18
|
*
|
@@ -62,7 +67,12 @@ import com.wix.detox.config.DetoxConfig;
|
|
62
67
|
* <p>If not set, then Detox tests are no ops. So it's safe to mix it with other tests.</p>
|
63
68
|
*/
|
64
69
|
public final class Detox {
|
65
|
-
private static
|
70
|
+
private static final String INTENT_LAUNCH_ARGS_KEY = "launchArgs";
|
71
|
+
private static final long ACTIVITY_LAUNCH_TIMEOUT = 10000L;
|
72
|
+
|
73
|
+
private static final LaunchArgs sLaunchArgs = new LaunchArgs();
|
74
|
+
private static final LaunchIntentsFactory sIntentsFactory = new LaunchIntentsFactory();
|
75
|
+
private static ActivityTestRule sActivityTestRule;
|
66
76
|
|
67
77
|
private Detox() {
|
68
78
|
}
|
@@ -122,20 +132,72 @@ public final class Detox {
|
|
122
132
|
DetoxConfig.CONFIG = detoxConfig;
|
123
133
|
DetoxConfig.CONFIG.apply();
|
124
134
|
|
125
|
-
|
126
|
-
|
135
|
+
sActivityTestRule = activityTestRule;
|
136
|
+
|
137
|
+
UiControllerSpy.attachThroughProxy();
|
138
|
+
|
139
|
+
Intent intent = extractInitialIntent();
|
140
|
+
sActivityTestRule.launchActivity(intent);
|
141
|
+
|
142
|
+
try {
|
143
|
+
DetoxMain.run(context);
|
144
|
+
} catch (Exception e) {
|
145
|
+
Thread.currentThread().interrupt();
|
146
|
+
throw new RuntimeException("Detox got interrupted prematurely", e);
|
147
|
+
}
|
127
148
|
}
|
128
149
|
|
129
150
|
public static void launchMainActivity() {
|
130
|
-
|
151
|
+
final Activity activity = sActivityTestRule.getActivity();
|
152
|
+
launchActivitySync(sIntentsFactory.activityLaunchIntent(activity));
|
131
153
|
}
|
132
154
|
|
133
155
|
public static void startActivityFromUrl(String url) {
|
134
|
-
|
156
|
+
launchActivitySync(sIntentsFactory.intentWithUrl(url, false));
|
135
157
|
}
|
136
158
|
|
137
159
|
public static void startActivityFromNotification(String dataFilePath) {
|
138
|
-
|
160
|
+
Bundle notificationData = new NotificationDataParser(dataFilePath).toBundle();
|
161
|
+
Intent intent = sIntentsFactory.intentWithNotificationData(getAppContext(), notificationData, false);
|
162
|
+
launchActivitySync(intent);
|
163
|
+
}
|
164
|
+
|
165
|
+
private static Intent extractInitialIntent() {
|
166
|
+
Intent intent;
|
167
|
+
|
168
|
+
if (sLaunchArgs.hasUrlOverride()) {
|
169
|
+
intent = sIntentsFactory.intentWithUrl(sLaunchArgs.getUrlOverride(), true);
|
170
|
+
} else if (sLaunchArgs.hasNotificationPath()) {
|
171
|
+
Bundle notificationData = new NotificationDataParser(sLaunchArgs.getNotificationPath()).toBundle();
|
172
|
+
intent = sIntentsFactory.intentWithNotificationData(getAppContext(), notificationData, true);
|
173
|
+
} else {
|
174
|
+
intent = sIntentsFactory.cleanIntent();
|
175
|
+
}
|
176
|
+
intent.putExtra(INTENT_LAUNCH_ARGS_KEY, sLaunchArgs.asIntentBundle());
|
177
|
+
return intent;
|
178
|
+
}
|
179
|
+
|
180
|
+
private static void launchActivitySync(Intent intent) {
|
181
|
+
// Ideally, we would just call sActivityTestRule.launchActivity(intent) and get it over with.
|
182
|
+
// BUT!!! as it turns out, Espresso has an issue where doing this for an activity running in the background
|
183
|
+
// would have Espresso set up an ActivityMonitor which will spend its time waiting for the activity to load, *without
|
184
|
+
// ever being released*. It will finally fail after a 45 seconds timeout.
|
185
|
+
// Without going into full details, it seems that activity test rules were not meant to be used this way. However,
|
186
|
+
// the all-new ActivityScenario implementation introduced in androidx could probably support this (e.g. by using
|
187
|
+
// dedicated methods such as moveToState(), which give better control over the lifecycle).
|
188
|
+
// In any case, this is the core reason for this issue: https://github.com/wix/Detox/issues/1125
|
189
|
+
// What it forces us to do, then, is this -
|
190
|
+
// 1. Launch the activity by "ourselves" from the OS (i.e. using context.startActivity()).
|
191
|
+
// 2. Set up an activity monitor by ourselves -- such that it would block until the activity is ready.
|
192
|
+
// ^ Hence the code below.
|
193
|
+
|
194
|
+
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
195
|
+
final Activity activity = sActivityTestRule.getActivity();
|
196
|
+
final Instrumentation.ActivityMonitor activityMonitor = new Instrumentation.ActivityMonitor(activity.getClass().getName(), null, true);
|
197
|
+
|
198
|
+
activity.startActivity(intent);
|
199
|
+
instrumentation.addMonitor(activityMonitor);
|
200
|
+
instrumentation.waitForMonitorWithTimeout(activityMonitor, ACTIVITY_LAUNCH_TIMEOUT);
|
139
201
|
}
|
140
202
|
|
141
203
|
private static Context getAppContext() {
|
@@ -3,62 +3,35 @@ package com.wix.detox
|
|
3
3
|
import android.content.Context
|
4
4
|
import android.util.Log
|
5
5
|
import com.wix.detox.adapters.server.*
|
6
|
-
import com.wix.detox.common.DetoxLog
|
7
|
-
import com.wix.detox.espresso.UiControllerSpy
|
6
|
+
import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
|
8
7
|
import com.wix.detox.instruments.DetoxInstrumentsManager
|
9
8
|
import com.wix.detox.reactnative.ReactNativeExtension
|
10
9
|
import com.wix.invoke.MethodInvocation
|
11
|
-
import java.util.concurrent.CountDownLatch
|
12
10
|
|
11
|
+
private const val INIT_ACTION = "_init"
|
12
|
+
private const val IS_READY_ACTION = "isReady"
|
13
13
|
private const val TERMINATION_ACTION = "_terminate"
|
14
14
|
|
15
15
|
object DetoxMain {
|
16
|
-
private val handshakeLock = CountDownLatch(1)
|
17
|
-
|
18
16
|
@JvmStatic
|
19
|
-
fun run(rnHostHolder: Context
|
17
|
+
fun run(rnHostHolder: Context) {
|
20
18
|
val detoxServerInfo = DetoxServerInfo()
|
19
|
+
Log.i(LOG_TAG, "Detox server connection details: $detoxServerInfo")
|
20
|
+
|
21
21
|
val testEngineFacade = TestEngineFacade()
|
22
22
|
val actionsDispatcher = DetoxActionsDispatcher()
|
23
|
-
val
|
24
|
-
|
25
|
-
|
26
|
-
initANRListener(serverAdapter)
|
27
|
-
initEspresso()
|
28
|
-
initReactNative()
|
29
|
-
|
30
|
-
setupActionHandlers(actionsDispatcher, serverAdapter, testEngineFacade, rnHostHolder)
|
31
|
-
serverAdapter.connect()
|
32
|
-
|
33
|
-
launchActivityOnCue(rnHostHolder, activityLaunchHelper)
|
23
|
+
val externalAdapter = DetoxServerAdapter(actionsDispatcher, detoxServerInfo, IS_READY_ACTION, TERMINATION_ACTION)
|
24
|
+
initActionHandlers(actionsDispatcher, externalAdapter, testEngineFacade, rnHostHolder)
|
25
|
+
actionsDispatcher.dispatchAction(INIT_ACTION, "", 0)
|
34
26
|
actionsDispatcher.join()
|
35
27
|
}
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
* completes successfully.
|
40
|
-
*
|
41
|
-
* This has to be synchronized so that an `isReady` isn't handled *before* the activity is launched (albeit not fully
|
42
|
-
* initialized - all native modules and everything) and a react context is available.
|
43
|
-
*
|
44
|
-
* As a better alternative, it would make sense to execute this as a simple action from within the actions
|
45
|
-
* dispatcher (i.e. handler of `loginSuccess`), in which case, no inter-thread locking would be required
|
46
|
-
* thanks to the usage of Handlers. However, in this type of a solution, errors / crashes would be reported
|
47
|
-
* not by instrumentation itself, but based on the `AppWillTerminateWithError` message; In it's own, it is a good
|
48
|
-
* thing, but for a reason we're not sure of yet, it is ignored by the test runner at this point in the flow.
|
49
|
-
*/
|
50
|
-
@Synchronized
|
51
|
-
private fun launchActivityOnCue(rnHostHolder: Context, activityLaunchHelper: ActivityLaunchHelper) {
|
52
|
-
awaitHandshake()
|
53
|
-
launchActivity(rnHostHolder, activityLaunchHelper)
|
54
|
-
}
|
55
|
-
|
56
|
-
private fun awaitHandshake() {
|
57
|
-
handshakeLock.await()
|
58
|
-
}
|
29
|
+
private fun doInit(externalAdapter: DetoxServerAdapter, rnHostHolder: Context) {
|
30
|
+
externalAdapter.connect()
|
59
31
|
|
60
|
-
|
61
|
-
|
32
|
+
initCrashHandler(externalAdapter)
|
33
|
+
initANRListener(externalAdapter)
|
34
|
+
initReactNativeIfNeeded(rnHostHolder)
|
62
35
|
}
|
63
36
|
|
64
37
|
private fun doTeardown(serverAdapter: DetoxServerAdapter, actionsDispatcher: DetoxActionsDispatcher, testEngineFacade: TestEngineFacade) {
|
@@ -68,28 +41,35 @@ object DetoxMain {
|
|
68
41
|
actionsDispatcher.teardown()
|
69
42
|
}
|
70
43
|
|
71
|
-
private fun
|
72
|
-
class SynchronizedActionHandler(private val actionHandler: DetoxActionHandler): DetoxActionHandler {
|
73
|
-
override fun handle(params: String, messageId: Long) {
|
74
|
-
synchronized(this@DetoxMain) {
|
75
|
-
actionHandler.handle(params, messageId)
|
76
|
-
}
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
44
|
+
private fun initActionHandlers(actionsDispatcher: DetoxActionsDispatcher, serverAdapter: DetoxServerAdapter, testEngineFacade: TestEngineFacade, rnHostHolder: Context) {
|
80
45
|
// Primary actions
|
81
46
|
with(actionsDispatcher) {
|
82
|
-
val
|
83
|
-
val rnReloadHandler = SynchronizedActionHandler( ReactNativeReloadActionHandler(rnHostHolder, serverAdapter, testEngineFacade) )
|
47
|
+
val rnReloadHandler = ReactNativeReloadActionHandler(rnHostHolder, serverAdapter, testEngineFacade)
|
84
48
|
|
85
|
-
associateActionHandler(
|
86
|
-
|
87
|
-
|
49
|
+
associateActionHandler(INIT_ACTION, object : DetoxActionHandler {
|
50
|
+
override fun handle(params: String, messageId: Long) =
|
51
|
+
synchronized(this@DetoxMain) {
|
52
|
+
this@DetoxMain.doInit(serverAdapter, rnHostHolder)
|
53
|
+
}
|
54
|
+
})
|
55
|
+
associateActionHandler(IS_READY_ACTION, ReadyActionHandler(serverAdapter, testEngineFacade))
|
56
|
+
|
57
|
+
associateActionHandler("loginSuccess", ScarceActionHandler())
|
58
|
+
associateActionHandler("reactNativeReload", object: DetoxActionHandler {
|
59
|
+
override fun handle(params: String, messageId: Long) =
|
60
|
+
synchronized(this@DetoxMain) {
|
61
|
+
rnReloadHandler.handle(params, messageId)
|
62
|
+
}
|
63
|
+
})
|
88
64
|
associateActionHandler("invoke", InvokeActionHandler(MethodInvocation(), serverAdapter))
|
89
65
|
associateActionHandler("cleanup", CleanupActionHandler(serverAdapter, testEngineFacade) {
|
90
66
|
dispatchAction(TERMINATION_ACTION, "", 0)
|
91
67
|
})
|
92
|
-
associateActionHandler(TERMINATION_ACTION
|
68
|
+
associateActionHandler(TERMINATION_ACTION, object: DetoxActionHandler {
|
69
|
+
override fun handle(params: String, messageId: Long) {
|
70
|
+
this@DetoxMain.doTeardown(serverAdapter, actionsDispatcher, testEngineFacade)
|
71
|
+
}
|
72
|
+
})
|
93
73
|
|
94
74
|
if (DetoxInstrumentsManager.supports()) {
|
95
75
|
val instrumentsManager = DetoxInstrumentsManager(rnHostHolder)
|
@@ -100,8 +80,13 @@ object DetoxMain {
|
|
100
80
|
|
101
81
|
// Secondary actions
|
102
82
|
with(actionsDispatcher) {
|
103
|
-
val queryStatusHandler =
|
104
|
-
|
83
|
+
val queryStatusHandler = QueryStatusActionHandler(serverAdapter, testEngineFacade)
|
84
|
+
associateActionHandler("currentStatus", object: DetoxActionHandler {
|
85
|
+
override fun handle(params: String, messageId: Long) =
|
86
|
+
synchronized(this@DetoxMain) {
|
87
|
+
queryStatusHandler.handle(params, messageId)
|
88
|
+
}
|
89
|
+
}, false)
|
105
90
|
}
|
106
91
|
}
|
107
92
|
|
@@ -113,17 +98,7 @@ object DetoxMain {
|
|
113
98
|
DetoxANRHandler(outboundServerAdapter).attach()
|
114
99
|
}
|
115
100
|
|
116
|
-
private fun
|
117
|
-
UiControllerSpy.attachThroughProxy()
|
118
|
-
}
|
119
|
-
|
120
|
-
private fun initReactNative() {
|
121
|
-
ReactNativeExtension.initIfNeeded()
|
122
|
-
}
|
123
|
-
|
124
|
-
private fun launchActivity(rnHostHolder: Context, activityLaunchHelper: ActivityLaunchHelper) {
|
125
|
-
Log.i(DetoxLog.LOG_TAG, "Launching the tested activity!")
|
126
|
-
activityLaunchHelper.launchActivityUnderTest()
|
101
|
+
private fun initReactNativeIfNeeded(rnHostHolder: Context) {
|
127
102
|
ReactNativeExtension.waitForRNBootstrap(rnHostHolder)
|
128
103
|
}
|
129
104
|
}
|
@@ -11,18 +11,11 @@ class DetoxActionsDispatcher {
|
|
11
11
|
private val primaryExec = ActionsExecutor("detox.primary")
|
12
12
|
private val secondaryExec = ActionsExecutor("detox.secondary")
|
13
13
|
|
14
|
-
fun associateActionHandler(type: String, actionHandler: DetoxActionHandler)
|
15
|
-
|
16
|
-
|
17
|
-
fun associateActionHandler(type: String, handlerFunc: () -> Unit) {
|
18
|
-
associateActionHandler(type, object: DetoxActionHandler {
|
19
|
-
override fun handle(params: String, messageId: Long) = handlerFunc()
|
20
|
-
})
|
14
|
+
fun associateActionHandler(type: String, actionHandler: DetoxActionHandler, isPrimary: Boolean = true) {
|
15
|
+
val actionsExecutor = (if (isPrimary) primaryExec else secondaryExec)
|
16
|
+
actionsExecutor.associateHandler(type, actionHandler)
|
21
17
|
}
|
22
18
|
|
23
|
-
fun associateSecondaryActionHandler(type: String, actionHandler: DetoxActionHandler) =
|
24
|
-
associateActionHandler(type, actionHandler, false)
|
25
|
-
|
26
19
|
fun dispatchAction(type: String, params: String, messageId: Long) {
|
27
20
|
(primaryExec.executeAction(type, params, messageId) ||
|
28
21
|
secondaryExec.executeAction(type, params, messageId))
|
@@ -40,11 +33,6 @@ class DetoxActionsDispatcher {
|
|
40
33
|
primaryExec.join()
|
41
34
|
secondaryExec.join()
|
42
35
|
}
|
43
|
-
|
44
|
-
private fun associateActionHandler(type: String, actionHandler: DetoxActionHandler, isPrimary: Boolean = true) {
|
45
|
-
val actionsExecutor = (if (isPrimary) primaryExec else secondaryExec)
|
46
|
-
actionsExecutor.associateHandler(type, actionHandler)
|
47
|
-
}
|
48
36
|
}
|
49
37
|
|
50
38
|
private class ActionsExecutor(name: String) {
|
@@ -86,5 +74,7 @@ private class ActionsExecutor(name: String) {
|
|
86
74
|
handler.looper.quit()
|
87
75
|
}
|
88
76
|
|
89
|
-
fun join()
|
77
|
+
fun join() {
|
78
|
+
thread.join()
|
79
|
+
}
|
90
80
|
}
|
@@ -10,6 +10,7 @@ interface OutboundServerAdapter {
|
|
10
10
|
class DetoxServerAdapter(
|
11
11
|
private val actionsDispatcher: DetoxActionsDispatcher,
|
12
12
|
private val detoxServerInfo: DetoxServerInfo,
|
13
|
+
private val readyActionType: String,
|
13
14
|
private val terminationActionType: String)
|
14
15
|
: WebSocketClient.WSEventsHandler, OutboundServerAdapter {
|
15
16
|
|
@@ -26,6 +27,7 @@ class DetoxServerAdapter(
|
|
26
27
|
|
27
28
|
override fun onConnect() {
|
28
29
|
Log.i(DetoxLog.LOG_TAG, "Connected to server!")
|
30
|
+
actionsDispatcher.dispatchAction(readyActionType, "", -1000L)
|
29
31
|
}
|
30
32
|
|
31
33
|
override fun onClosed() {
|
@@ -1,9 +1,7 @@
|
|
1
1
|
package com.wix.detox.adapters.server
|
2
2
|
|
3
|
-
import android.util.Log
|
4
3
|
import androidx.test.platform.app.InstrumentationRegistry
|
5
4
|
import com.wix.detox.LaunchArgs
|
6
|
-
import com.wix.detox.common.DetoxLog
|
7
5
|
|
8
6
|
private const val DEFAULT_URL = "ws://localhost:8099"
|
9
7
|
|
@@ -11,7 +9,7 @@ class DetoxServerInfo internal constructor(launchArgs: LaunchArgs = LaunchArgs()
|
|
11
9
|
val serverUrl: String = launchArgs.detoxServerUrl ?: DEFAULT_URL
|
12
10
|
val sessionId: String = launchArgs.detoxSessionId ?: InstrumentationRegistry.getInstrumentation().targetContext.applicationInfo.packageName
|
13
11
|
|
14
|
-
|
15
|
-
|
12
|
+
override fun toString(): String {
|
13
|
+
return "url=$serverUrl, sessionId=$sessionId"
|
16
14
|
}
|
17
15
|
}
|
@@ -24,8 +24,9 @@ public class ViewAssertions {
|
|
24
24
|
* which is more suitable for Detox' separated interaction-matcher architecture.
|
25
25
|
* See {@link MatchesViewAssertion} for more details.
|
26
26
|
*/
|
27
|
+
@SuppressWarnings("unchecked")
|
27
28
|
public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {
|
28
|
-
return new MatchesViewAssertion(checkNotNull(viewMatcher));
|
29
|
+
return new MatchesViewAssertion((Matcher<? super View>) checkNotNull(viewMatcher));
|
29
30
|
}
|
30
31
|
|
31
32
|
/**
|
@@ -14,31 +14,6 @@ private const val LOG_TAG = "DetoxRNExt"
|
|
14
14
|
object ReactNativeExtension {
|
15
15
|
private var rnIdlingResources: ReactNativeIdlingResources? = null
|
16
16
|
|
17
|
-
fun initIfNeeded() {
|
18
|
-
if (!ReactNativeInfo.isReactNativeApp()) {
|
19
|
-
return
|
20
|
-
}
|
21
|
-
|
22
|
-
ReactMarkersLogger.attach()
|
23
|
-
}
|
24
|
-
|
25
|
-
/**
|
26
|
-
* Wait for React-Native to finish loading (i.e. make RN context available).
|
27
|
-
*
|
28
|
-
* @param applicationContext The app context, implicitly assumed to be a [ReactApplication] instance.
|
29
|
-
*/
|
30
|
-
fun waitForRNBootstrap(applicationContext: Context) {
|
31
|
-
if (!ReactNativeInfo.isReactNativeApp()) {
|
32
|
-
return
|
33
|
-
}
|
34
|
-
|
35
|
-
(applicationContext as ReactApplication).let {
|
36
|
-
val reactContext = awaitNewReactNativeContext(it, null)
|
37
|
-
|
38
|
-
enableOrDisableSynchronization(reactContext)
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
17
|
/**
|
43
18
|
* Reloads the React Native context and thus all javascript code.
|
44
19
|
*
|
@@ -65,6 +40,26 @@ object ReactNativeExtension {
|
|
65
40
|
val reactContext = awaitNewReactNativeContext(it, previousReactContext)
|
66
41
|
|
67
42
|
enableOrDisableSynchronization(reactContext, networkSyncEnabled)
|
43
|
+
hackRN50OrHigherWaitForReady()
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Wait for React-Native to finish loading (i.e. make RN context available).
|
49
|
+
*
|
50
|
+
* @param applicationContext The app context, implicitly assumed to be a [ReactApplication] instance.
|
51
|
+
*/
|
52
|
+
@JvmStatic
|
53
|
+
fun waitForRNBootstrap(applicationContext: Context) {
|
54
|
+
if (!ReactNativeInfo.isReactNativeApp()) {
|
55
|
+
return
|
56
|
+
}
|
57
|
+
|
58
|
+
(applicationContext as ReactApplication).let {
|
59
|
+
val reactContext = awaitNewReactNativeContext(it, null)
|
60
|
+
|
61
|
+
enableOrDisableSynchronization(reactContext)
|
62
|
+
hackRN50OrHigherWaitForReady()
|
68
63
|
}
|
69
64
|
}
|
70
65
|
|
@@ -150,6 +145,18 @@ object ReactNativeExtension {
|
|
150
145
|
}
|
151
146
|
}
|
152
147
|
|
148
|
+
private fun hackRN50OrHigherWaitForReady() {
|
149
|
+
if (ReactNativeInfo.rnVersion().minor in 50..62) {
|
150
|
+
try {
|
151
|
+
//TODO- Temp hack to make Detox usable for RN>=50 till we find a better sync solution.
|
152
|
+
Thread.sleep(1000)
|
153
|
+
} catch (e: InterruptedException) {
|
154
|
+
e.printStackTrace()
|
155
|
+
}
|
156
|
+
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
153
160
|
private fun clearIdlingResources() {
|
154
161
|
rnIdlingResources?.unregisterAll()
|
155
162
|
rnIdlingResources = null
|
@@ -11,8 +11,11 @@ class UiControllerSpy: MethodsSpy("uiController") {
|
|
11
11
|
fun eventInjectionsIterator(): Iterator<CallInfo?> = historyOf("injectMotionEvent").iterator()
|
12
12
|
|
13
13
|
companion object {
|
14
|
+
@JvmStatic
|
14
15
|
val instance = UiControllerSpy()
|
15
16
|
|
17
|
+
@JvmStatic
|
18
|
+
@JvmOverloads
|
16
19
|
fun attachThroughProxy(spy: UiControllerSpy = instance) {
|
17
20
|
val eventsInjectorReflected = EventsInjectorReflected(getUiController())
|
18
21
|
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "detox",
|
3
3
|
"description": "E2E tests and automation for mobile",
|
4
|
-
"version": "20.14.
|
4
|
+
"version": "20.14.3",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -51,7 +51,7 @@
|
|
51
51
|
"eslint-plugin-node": "^11.1.0",
|
52
52
|
"eslint-plugin-unicorn": "^47.0.0",
|
53
53
|
"jest": "^28.1.3",
|
54
|
-
"jest-allure2-reporter": "
|
54
|
+
"jest-allure2-reporter": "2.0.0-alpha.11",
|
55
55
|
"mockdate": "^2.0.1",
|
56
56
|
"prettier": "^2.4.1",
|
57
57
|
"react-native": "0.71.10",
|
@@ -72,7 +72,6 @@
|
|
72
72
|
"funpermaproxy": "^1.1.0",
|
73
73
|
"glob": "^8.0.3",
|
74
74
|
"ini": "^1.3.4",
|
75
|
-
"jest-environment-emit": "^1.0.3",
|
76
75
|
"json-cycle": "^1.3.0",
|
77
76
|
"lodash": "^4.17.11",
|
78
77
|
"multi-sort-stream": "^1.0.3",
|
@@ -110,5 +109,5 @@
|
|
110
109
|
"browserslist": [
|
111
110
|
"node 14"
|
112
111
|
],
|
113
|
-
"gitHead": "
|
112
|
+
"gitHead": "a7bbc444bab6fbce3d561cd110c40ba1b2b84a6b"
|
114
113
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
const path = require('path');
|
2
2
|
|
3
|
-
const WithEmitter = require('jest-environment-emit');
|
4
3
|
const resolveFrom = require('resolve-from');
|
5
4
|
const maybeNodeEnvironment = require(resolveFrom(process.cwd(), 'jest-environment-node'));
|
6
5
|
/** @type {typeof import('@jest/environment').JestEnvironment} */
|
@@ -32,7 +31,7 @@ const log = detox.log.child({ cat: 'lifecycle,jest-environment' });
|
|
32
31
|
/**
|
33
32
|
* @see https://www.npmjs.com/package/jest-circus#overview
|
34
33
|
*/
|
35
|
-
class DetoxCircusEnvironment extends
|
34
|
+
class DetoxCircusEnvironment extends NodeEnvironment {
|
36
35
|
constructor(config, context) {
|
37
36
|
super(assertJestCircus27(config), assertExistingContext(context));
|
38
37
|
|
@@ -63,8 +62,6 @@ class DetoxCircusEnvironment extends WithEmitter(NodeEnvironment) {
|
|
63
62
|
SpecReporter,
|
64
63
|
WorkerAssignReporter,
|
65
64
|
});
|
66
|
-
|
67
|
-
this.testEvents.on('*', this._onTestEvent.bind(this));
|
68
65
|
}
|
69
66
|
|
70
67
|
/** @override */
|
@@ -75,13 +72,19 @@ class DetoxCircusEnvironment extends WithEmitter(NodeEnvironment) {
|
|
75
72
|
|
76
73
|
// @ts-expect-error TS2425
|
77
74
|
async handleTestEvent(event, state) {
|
78
|
-
await super.handleTestEvent(event, state);
|
79
|
-
|
80
75
|
if (detox.session.unsafe_earlyTeardown) {
|
81
76
|
if (event.name === 'test_fn_start' || event.name === 'hook_start') {
|
82
77
|
throw new Error('Detox halted test execution due to an early teardown request');
|
83
78
|
}
|
84
79
|
}
|
80
|
+
|
81
|
+
this._timer.schedule(state.testTimeout != null ? state.testTimeout : this.setupTimeout);
|
82
|
+
|
83
|
+
if (SYNC_CIRCUS_EVENTS.has(event.name)) {
|
84
|
+
this._handleTestEventSync(event, state);
|
85
|
+
} else {
|
86
|
+
await this._handleTestEventAsync(event, state);
|
87
|
+
}
|
85
88
|
}
|
86
89
|
|
87
90
|
/** @override */
|
@@ -144,23 +147,6 @@ class DetoxCircusEnvironment extends WithEmitter(NodeEnvironment) {
|
|
144
147
|
}
|
145
148
|
}
|
146
149
|
|
147
|
-
/** @private */
|
148
|
-
_onTestEvent({ type, event, state }) {
|
149
|
-
const timeout = state && state.testTimeout != null ? state.testTimeout : this.setupTimeout;
|
150
|
-
|
151
|
-
this._timer.schedule(timeout);
|
152
|
-
|
153
|
-
if (event) {
|
154
|
-
if (SYNC_CIRCUS_EVENTS.has(event.name)) {
|
155
|
-
this._handleTestEventSync(event, state);
|
156
|
-
} else {
|
157
|
-
return this._handleTestEventAsync(event, state);
|
158
|
-
}
|
159
|
-
} else {
|
160
|
-
return this._handleTestEventAsync({ name: type }, null);
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
150
|
/** @private */
|
165
151
|
async _handleTestEventAsync(event, state = null) {
|
166
152
|
const description = `handling ${state ? 'jest-circus' : 'jest-environment'} "${event.name}" event`;
|
@@ -58,6 +58,17 @@ class Detox {
|
|
58
58
|
};
|
59
59
|
}
|
60
60
|
|
61
|
+
static extractInitialIntent() {
|
62
|
+
return {
|
63
|
+
target: {
|
64
|
+
type: "Class",
|
65
|
+
value: "com.wix.detox.Detox"
|
66
|
+
},
|
67
|
+
method: "extractInitialIntent",
|
68
|
+
args: []
|
69
|
+
};
|
70
|
+
}
|
71
|
+
|
61
72
|
static getAppContext() {
|
62
73
|
return {
|
63
74
|
target: {
|
@@ -1 +0,0 @@
|
|
1
|
-
b56512e0fe84eed91885c40b9aeb1876
|
@@ -1 +0,0 @@
|
|
1
|
-
35b1fdd0c5d23f76c0c9f5b3cfd91edff4abe0e7
|
package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.sha256
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
c7f59ec60f1b4f10cdffcf0023da66681cbc787929a75b8e6b6a24771c83ea92
|
package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-javadoc.jar.sha512
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
367d068f6412036503c944851d086943ff52953fe697f112c5362fbb881dbcb5384ef22a6ce6dbd4aa6021895c44405fc00f9c4adeb8152d80a0489e9747a16c
|
@@ -1 +0,0 @@
|
|
1
|
-
1a7792aba643e970a9831def1edd4cb8
|
@@ -1 +0,0 @@
|
|
1
|
-
0761d159eead3b546306dc46201a56ee80d49ef0
|
package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.sha256
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
687425ea260c9a25cd6f45b03058f5b8ef436bab936ec5f2641ef7c63036259d
|
package/Detox-android/com/wix/detox/20.14.2-smoke.0/detox-20.14.2-smoke.0-sources.jar.sha512
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
fc38bb0856a2003cf511612ef7a767fc922e1c6866ff7973af3aea2ddab0fac1245927ab9395e326f52a455350509cc46548224c15f6da38f76b3e6880d84a22
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
5802af204da6a4e44339eb5b544e816d
|
@@ -1 +0,0 @@
|
|
1
|
-
530bd1ee5be0479b9d48b33722b521ef408d82b7
|
@@ -1 +0,0 @@
|
|
1
|
-
4efd5d50625590c576c69a3a722d8df776fa213cff6e1fa254ec429d4db6fb58
|
@@ -1 +0,0 @@
|
|
1
|
-
19b779508bf7d9059f23fd638114bb817eee061bf018fcf793b451f63b3c5d8519e20f85fceffa61863d59244f168692d1e4e8d861be979200a2130c4486b9e8
|
@@ -1 +0,0 @@
|
|
1
|
-
2be5b0e9390f3a95a5a4a3e08e449160
|
@@ -1 +0,0 @@
|
|
1
|
-
f3d0dd33a7576500c24955498672bf821c0356a4
|
@@ -1 +0,0 @@
|
|
1
|
-
159d6ddf1818aed4ce463a366bec120cf29a98110d4dce5a8ce120479c34b188
|
@@ -1 +0,0 @@
|
|
1
|
-
f55587e2b9d8a7c61150d09bbf674e69ee7cb69bb31343072d85e4e31b66ba0609458fb2f2962a85c1697d3681852d03613c5d0327fdc6de881287d837f3a9fd
|
@@ -1,76 +0,0 @@
|
|
1
|
-
package com.wix.detox
|
2
|
-
|
3
|
-
import android.app.Instrumentation.ActivityMonitor
|
4
|
-
import android.content.Context
|
5
|
-
import android.content.Intent
|
6
|
-
import androidx.test.platform.app.InstrumentationRegistry
|
7
|
-
import androidx.test.rule.ActivityTestRule
|
8
|
-
|
9
|
-
class ActivityLaunchHelper(private val activityTestRule: ActivityTestRule<*>) {
|
10
|
-
|
11
|
-
private val launchArgs = LaunchArgs()
|
12
|
-
private val intentsFactory = LaunchIntentsFactory()
|
13
|
-
|
14
|
-
fun launchActivityUnderTest() {
|
15
|
-
val intent = extractInitialIntent()
|
16
|
-
activityTestRule.launchActivity(intent)
|
17
|
-
}
|
18
|
-
|
19
|
-
fun launchMainActivity() {
|
20
|
-
val activity = activityTestRule.activity
|
21
|
-
launchActivitySync(intentsFactory.activityLaunchIntent(activity))
|
22
|
-
}
|
23
|
-
|
24
|
-
fun startActivityFromUrl(url: String) {
|
25
|
-
launchActivitySync(intentsFactory.intentWithUrl(url, false))
|
26
|
-
}
|
27
|
-
|
28
|
-
fun startActivityFromNotification(dataFilePath: String) {
|
29
|
-
val notificationData = NotificationDataParser(dataFilePath!!).toBundle()
|
30
|
-
val intent = intentsFactory.intentWithNotificationData(appContext, notificationData, false)
|
31
|
-
launchActivitySync(intent)
|
32
|
-
}
|
33
|
-
|
34
|
-
private fun extractInitialIntent(): Intent =
|
35
|
-
if (launchArgs.hasUrlOverride()) {
|
36
|
-
intentsFactory.intentWithUrl(launchArgs.urlOverride, true)
|
37
|
-
} else if (launchArgs.hasNotificationPath()) {
|
38
|
-
val notificationData = NotificationDataParser(launchArgs.notificationPath).toBundle()
|
39
|
-
intentsFactory.intentWithNotificationData(appContext, notificationData, true)
|
40
|
-
} else {
|
41
|
-
intentsFactory.cleanIntent()
|
42
|
-
}.also {
|
43
|
-
it.putExtra(INTENT_LAUNCH_ARGS_KEY, launchArgs.asIntentBundle())
|
44
|
-
}
|
45
|
-
|
46
|
-
private fun launchActivitySync(intent: Intent) {
|
47
|
-
// Ideally, we would just call sActivityTestRule.launchActivity(intent) and get it over with.
|
48
|
-
// BUT!!! as it turns out, Espresso has an issue where doing this for an activity running in the background
|
49
|
-
// would have Espresso set up an ActivityMonitor which will spend its time waiting for the activity to load, *without
|
50
|
-
// ever being released*. It will finally fail after a 45 seconds timeout.
|
51
|
-
// Without going into full details, it seems that activity test rules were not meant to be used this way. However,
|
52
|
-
// the all-new ActivityScenario implementation introduced in androidx could probably support this (e.g. by using
|
53
|
-
// dedicated methods such as moveToState(), which give better control over the lifecycle).
|
54
|
-
// In any case, this is the core reason for this issue: https://github.com/wix/Detox/issues/1125
|
55
|
-
// What it forces us to do, then, is this -
|
56
|
-
// 1. Launch the activity by "ourselves" from the OS (i.e. using context.startActivity()).
|
57
|
-
// 2. Set up an activity monitor by ourselves -- such that it would block until the activity is ready.
|
58
|
-
// ^ Hence the code below.
|
59
|
-
val activity = activityTestRule.activity
|
60
|
-
val activityMonitor = ActivityMonitor(activity.javaClass.name, null, true)
|
61
|
-
activity.startActivity(intent)
|
62
|
-
|
63
|
-
InstrumentationRegistry.getInstrumentation().run {
|
64
|
-
addMonitor(activityMonitor)
|
65
|
-
waitForMonitorWithTimeout(activityMonitor, ACTIVITY_LAUNCH_TIMEOUT)
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
private val appContext: Context
|
70
|
-
get() = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
71
|
-
|
72
|
-
companion object {
|
73
|
-
private const val INTENT_LAUNCH_ARGS_KEY = "launchArgs"
|
74
|
-
private const val ACTIVITY_LAUNCH_TIMEOUT = 10000L
|
75
|
-
}
|
76
|
-
}
|
@@ -1,44 +0,0 @@
|
|
1
|
-
package com.wix.detox.reactnative
|
2
|
-
|
3
|
-
import android.util.Log
|
4
|
-
import com.facebook.react.bridge.ReactMarker
|
5
|
-
import com.facebook.react.bridge.ReactMarkerConstants
|
6
|
-
import com.facebook.react.bridge.ReactMarkerConstants.*
|
7
|
-
|
8
|
-
object ReactMarkersLogger : ReactMarker.MarkerListener {
|
9
|
-
|
10
|
-
fun attach() {
|
11
|
-
ReactMarker.addListener(this)
|
12
|
-
}
|
13
|
-
|
14
|
-
override fun logMarker(marker: ReactMarkerConstants, p1: String?, p2: Int) {
|
15
|
-
when {
|
16
|
-
marker == DOWNLOAD_START ||
|
17
|
-
marker == DOWNLOAD_END ||
|
18
|
-
marker == BUILD_REACT_INSTANCE_MANAGER_START ||
|
19
|
-
marker == BUILD_REACT_INSTANCE_MANAGER_END ||
|
20
|
-
marker == REACT_BRIDGE_LOADING_START ||
|
21
|
-
marker == REACT_BRIDGE_LOADING_END ||
|
22
|
-
marker == REACT_BRIDGELESS_LOADING_START ||
|
23
|
-
marker == REACT_BRIDGELESS_LOADING_END ||
|
24
|
-
marker == CREATE_MODULE_START ||
|
25
|
-
marker == CREATE_MODULE_END ||
|
26
|
-
marker == NATIVE_MODULE_SETUP_START ||
|
27
|
-
marker == NATIVE_MODULE_SETUP_END ||
|
28
|
-
marker == PRE_RUN_JS_BUNDLE_START ||
|
29
|
-
marker == RUN_JS_BUNDLE_START ||
|
30
|
-
marker == RUN_JS_BUNDLE_END ||
|
31
|
-
marker == CONTENT_APPEARED ||
|
32
|
-
marker == CREATE_CATALYST_INSTANCE_START ||
|
33
|
-
marker == CREATE_CATALYST_INSTANCE_END ||
|
34
|
-
marker == DESTROY_CATALYST_INSTANCE_START ||
|
35
|
-
marker == DESTROY_CATALYST_INSTANCE_END ||
|
36
|
-
marker == CREATE_REACT_CONTEXT_START ||
|
37
|
-
marker == CREATE_REACT_CONTEXT_END ||
|
38
|
-
marker == PROCESS_PACKAGES_START ||
|
39
|
-
marker == PROCESS_PACKAGES_END ||
|
40
|
-
false ->
|
41
|
-
Log.d("Detox.RNMarker", "$marker ($p1)")
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|