detox 20.28.0 → 20.32.0
Sign up to get free protection for your applications and to get access to all the features.
- package/Detox-android/com/wix/detox/{20.28.0/detox-20.28.0-sources.jar → 20.32.0/detox-20.32.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.28.0/detox-20.28.0.pom → 20.32.0/detox-20.32.0.pom} +2 -2
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.32.0/detox-20.32.0.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-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/android/build.gradle +5 -5
- package/android/detox/proguard-rules-app.pro +3 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +1 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java +3 -3
- package/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java +0 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java +33 -8
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +6 -11
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeInfo.kt +4 -11
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxIdlingResource.kt +42 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/ReactNativeIdlingResources.kt +145 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/animations/AnimatedModuleIdlingResource.kt +61 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/bridge/BridgeIdlingResource.kt +72 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/DetoxIdlingResourceFactory.kt +32 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/IdlingResourcesName.kt +10 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/LooperName.kt +6 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/looper/MQThreadsReflector.kt +47 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/network/NetworkIdlingResource.kt +105 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{NetworkingModuleReflected.kt → network/NetworkingModuleReflected.kt} +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{AsyncStorageIdlingResource.kt → storage/AsyncStorageIdlingResource.kt} +33 -35
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{SerialExecutorReflected.kt → storage/SerialExecutorReflected.kt} +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt +21 -19
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIManagerModuleReflected.kt +19 -27
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIModuleIdlingResource.kt +5 -17
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceTest.kt +248 -0
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResourcesTest.kt +5 -1
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt +1 -0
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceTest.kt +212 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/android/rninfo.gradle +31 -24
- package/android/settings.gradle +11 -6
- package/package.json +11 -8
- package/scripts/postinstall.js +2 -2
- package/scripts/updateGradle.js +41 -8
- package/src/DetoxWorker.js +11 -6
- package/src/copilot/DetoxCopilot.js +3 -15
- package/src/devices/allocation/drivers/android/genycloud/exec/GenyCloudExec.js +14 -8
- package/src/devices/validation/android/GenycloudEnvValidator.js +20 -3
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom +0 -100
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +0 -13
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +0 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +0 -229
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java +0 -215
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java +0 -94
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java +0 -29
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java +0 -134
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt +0 -23
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt +0 -16
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +0 -71
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt +0 -227
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt +0 -47
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt +0 -189
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
eee5ef30145285d5cb57b7a09afb8304
|
@@ -0,0 +1 @@
|
|
1
|
+
f454322216a38a2a565504eeeee3097cdf210dd0
|
@@ -0,0 +1 @@
|
|
1
|
+
bde47b3d7df6f70cc9812e1232aa5781a4dbfbd923ca52c6097ab9ea880eb207
|
@@ -0,0 +1 @@
|
|
1
|
+
175ce023c440c5903a33af31f0ce39e603c6c930fa05ddf5a38f070cd99b29fc6ee2e82b816bc60507c7c4729e9c0b1d8d1247ecc4b6b75455e0924d397dfe37
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
c5f3daffcbc4e0f545784d563efc793c
|
@@ -0,0 +1 @@
|
|
1
|
+
fd392c76debf7d9afdbfd9f7eb0c48766395bd82
|
@@ -0,0 +1 @@
|
|
1
|
+
f6623de89efe2e0b49241ef2c9ec3fee79cf3d84e7dbf5d2f00d762427a32cab
|
@@ -0,0 +1 @@
|
|
1
|
+
92906ac80969295c0ca21b3428801173fa48bb93ffc0ff2450f2d74af4a6c2b6c9afdcb07c49bd46f2bb791317b8dd43bd30ff5801839fa3c7deafd6c8348548
|
@@ -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.
|
6
|
+
<version>20.32.0</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,7 +33,7 @@
|
|
33
33
|
<dependency>
|
34
34
|
<groupId>org.jetbrains.kotlin</groupId>
|
35
35
|
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
36
|
-
<version>1.
|
36
|
+
<version>1.9.24</version>
|
37
37
|
<scope>compile</scope>
|
38
38
|
</dependency>
|
39
39
|
<dependency>
|
@@ -0,0 +1 @@
|
|
1
|
+
8a89efbe63dd0bb5e8263bd728b2a6ce
|
@@ -0,0 +1 @@
|
|
1
|
+
73079f2074231a904b98113f686c7b7f8df79ad7
|
@@ -0,0 +1 @@
|
|
1
|
+
4c76f2991c6d5bb6fd4a883542bac697c8e3e49d1816e59f36b5b3678c6ae6ab
|
@@ -0,0 +1 @@
|
|
1
|
+
b856a9916b7e864eeb2226d29b56c5bea595545c7cb82e8c33619357fdfbf9a942201f1ecd70b57fb5499c5b59d38a1e4fc13bee6a84eaf2b75e2b630faeb6f7
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<groupId>com.wix</groupId>
|
4
4
|
<artifactId>detox</artifactId>
|
5
5
|
<versioning>
|
6
|
-
<latest>20.
|
7
|
-
<release>20.
|
6
|
+
<latest>20.32.0</latest>
|
7
|
+
<release>20.32.0</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.
|
9
|
+
<version>20.32.0</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20250106191456</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
a21a21f5f33f0521ea5b27a6b7c9a53d
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3c0a9c339f4d397ac37a6779311c1c121ab01863
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
fa21aff43ff2f349f95760a2467987cef206152f4277db7d005193124667457b
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
91de105f632722548240b0ce79abfa9758dfb44827badc8828bdb09404f917038e5e2157757003141f2d676cf641b9734f063ea0f950e01842d491d3eb8f04fc
|
package/Detox-ios-framework.tbz
CHANGED
Binary file
|
package/Detox-ios-src.tbz
CHANGED
Binary file
|
package/Detox-ios-xcuitest.tbz
CHANGED
Binary file
|
package/android/build.gradle
CHANGED
@@ -3,12 +3,12 @@ buildscript {
|
|
3
3
|
|
4
4
|
ext {
|
5
5
|
isOfficialDetoxLib = true
|
6
|
-
kotlinVersion = '1.
|
6
|
+
kotlinVersion = '1.9.24'
|
7
7
|
dokkaVersion = '1.9.10'
|
8
|
-
buildToolsVersion = '
|
9
|
-
compileSdkVersion =
|
10
|
-
targetSdkVersion =
|
11
|
-
minSdkVersion =
|
8
|
+
buildToolsVersion = '35.0.0'
|
9
|
+
compileSdkVersion = 35
|
10
|
+
targetSdkVersion = 35
|
11
|
+
minSdkVersion = 24
|
12
12
|
}
|
13
13
|
ext.detoxKotlinVersion = ext.kotlinVersion
|
14
14
|
|
@@ -8,6 +8,9 @@
|
|
8
8
|
-keep class com.facebook.react.ReactInstanceManager { *; }
|
9
9
|
-keep class com.facebook.react.ReactInstanceManager** { *; }
|
10
10
|
-keep class com.facebook.react.ReactInstanceEventListener { *; }
|
11
|
+
-keep class com.facebook.react.soloader.OpenSourceMergedSoMapping { *; }
|
12
|
+
-keep class com.facebook.soloader.SoLoader { *; }
|
13
|
+
-keep class com.facebook.soloader.ExternalSoMapping { *; }
|
11
14
|
|
12
15
|
-keep class com.facebook.react.views.slider.** { *; }
|
13
16
|
-keep class com.google.android.material.slider.** { *; }
|
@@ -13,7 +13,7 @@ import android.view.ViewGroup;
|
|
13
13
|
import com.facebook.react.ReactApplication;
|
14
14
|
import com.wix.detox.common.UIThread;
|
15
15
|
import com.wix.detox.reactnative.ReactNativeExtension;
|
16
|
-
import com.wix.detox.reactnative.idlingresources.NetworkIdlingResource;
|
16
|
+
import com.wix.detox.reactnative.idlingresources.network.NetworkIdlingResource;
|
17
17
|
|
18
18
|
import org.hamcrest.Matcher;
|
19
19
|
|
@@ -1,14 +1,14 @@
|
|
1
1
|
package com.wix.detox.espresso.web;
|
2
2
|
|
3
3
|
|
4
|
+
import static androidx.test.espresso.web.webdriver.DriverAtoms.findMultipleElements;
|
5
|
+
|
4
6
|
import androidx.test.espresso.web.model.Atom;
|
5
7
|
import androidx.test.espresso.web.model.ElementReference;
|
6
8
|
import androidx.test.espresso.web.webdriver.Locator;
|
7
9
|
|
8
10
|
import java.util.List;
|
9
11
|
|
10
|
-
import static androidx.test.espresso.web.webdriver.DriverAtoms.findMultipleElements;
|
11
|
-
|
12
12
|
public class DetoxWebAtomMatcher {
|
13
13
|
|
14
14
|
private DetoxWebAtomMatcher() {
|
@@ -46,4 +46,4 @@ public class DetoxWebAtomMatcher {
|
|
46
46
|
public static Atom<List<ElementReference>> matcherForTagName(String tag) {
|
47
47
|
return findMultipleElements(Locator.TAG_NAME, tag);
|
48
48
|
}
|
49
|
-
}
|
49
|
+
}
|
@@ -3,7 +3,6 @@ package com.wix.detox.espresso.web;
|
|
3
3
|
import androidx.test.espresso.web.model.Atom;
|
4
4
|
import androidx.test.espresso.web.model.Atoms;
|
5
5
|
import androidx.test.espresso.web.model.ElementReference;
|
6
|
-
import androidx.test.espresso.web.model.Evaluation;
|
7
6
|
import androidx.test.espresso.web.model.SimpleAtom;
|
8
7
|
import androidx.test.espresso.web.sugar.Web;
|
9
8
|
import androidx.test.espresso.web.webdriver.DriverAtoms;
|
@@ -1,5 +1,7 @@
|
|
1
1
|
package com.wix.detox.espresso.web;
|
2
2
|
|
3
|
+
import static androidx.test.espresso.web.sugar.Web.onWebView;
|
4
|
+
|
3
5
|
import android.view.View;
|
4
6
|
import android.webkit.WebView;
|
5
7
|
|
@@ -7,24 +9,47 @@ import androidx.test.espresso.web.model.Atom;
|
|
7
9
|
import androidx.test.espresso.web.model.ElementReference;
|
8
10
|
import androidx.test.espresso.web.sugar.Web;
|
9
11
|
|
10
|
-
import org.hamcrest.
|
12
|
+
import org.hamcrest.Description;
|
11
13
|
import org.hamcrest.Matcher;
|
14
|
+
import org.hamcrest.TypeSafeMatcher;
|
12
15
|
|
13
16
|
import java.util.List;
|
14
17
|
|
15
18
|
import javax.annotation.Nullable;
|
16
19
|
|
17
|
-
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
18
|
-
import static androidx.test.espresso.web.sugar.Web.onWebView;
|
19
|
-
import static org.hamcrest.CoreMatchers.allOf;
|
20
|
-
|
21
20
|
public class WebViewElement {
|
22
21
|
|
23
|
-
final
|
22
|
+
private final static String WRAPPER_WEBVIEW_CLASS_NAME = "RNCWebViewWrapper";
|
23
|
+
|
24
24
|
final Web.WebInteraction<Void> webViewInteraction;
|
25
25
|
|
26
|
-
WebViewElement(@Nullable Matcher<View>
|
27
|
-
|
26
|
+
WebViewElement(@Nullable Matcher<View> userMatcher) {
|
27
|
+
Matcher<View> matcher = null;
|
28
|
+
|
29
|
+
if (userMatcher != null) {
|
30
|
+
matcher = new TypeSafeMatcher<>() {
|
31
|
+
|
32
|
+
@Override
|
33
|
+
protected boolean matchesSafely(View item) {
|
34
|
+
// Support for react-native-webview >= 13.0.0
|
35
|
+
if (item instanceof WebView && item.getParent().getClass().getSimpleName().equals(WRAPPER_WEBVIEW_CLASS_NAME)) {
|
36
|
+
return userMatcher.matches(item.getParent());
|
37
|
+
}
|
38
|
+
|
39
|
+
if (item.getClass().getSimpleName().equals("RNCWebViewWrapper")) {
|
40
|
+
// We never want to match the wrapper of the webview
|
41
|
+
return false;
|
42
|
+
}
|
43
|
+
|
44
|
+
return userMatcher.matches(item);
|
45
|
+
}
|
46
|
+
|
47
|
+
@Override
|
48
|
+
public void describeTo(Description description) {
|
49
|
+
userMatcher.describeTo(description);
|
50
|
+
}
|
51
|
+
};
|
52
|
+
}
|
28
53
|
this.webViewInteraction = matcher != null ? onWebView(matcher) : onWebView();
|
29
54
|
}
|
30
55
|
|
@@ -8,6 +8,7 @@ import com.facebook.react.ReactApplication
|
|
8
8
|
import com.facebook.react.ReactInstanceManager
|
9
9
|
import com.facebook.react.bridge.ReactContext
|
10
10
|
import com.wix.detox.LaunchArgs
|
11
|
+
import com.wix.detox.reactnative.idlingresources.ReactNativeIdlingResources
|
11
12
|
|
12
13
|
private const val LOG_TAG = "DetoxRNExt"
|
13
14
|
|
@@ -56,7 +57,6 @@ object ReactNativeExtension {
|
|
56
57
|
Log.i(LOG_TAG, "Reloading React Native")
|
57
58
|
|
58
59
|
(applicationContext as ReactApplication).let {
|
59
|
-
val networkSyncEnabled = rnIdlingResources?.networkSyncEnabled ?: true
|
60
60
|
clearIdlingResources()
|
61
61
|
|
62
62
|
val previousReactContext = getCurrentReactContextSafe(it)
|
@@ -64,7 +64,7 @@ object ReactNativeExtension {
|
|
64
64
|
reloadReactNativeInBackground(it)
|
65
65
|
val reactContext = awaitNewReactNativeContext(it, previousReactContext)
|
66
66
|
|
67
|
-
enableOrDisableSynchronization(reactContext
|
67
|
+
enableOrDisableSynchronization(reactContext)
|
68
68
|
}
|
69
69
|
}
|
70
70
|
|
@@ -93,11 +93,6 @@ object ReactNativeExtension {
|
|
93
93
|
return null
|
94
94
|
}
|
95
95
|
|
96
|
-
@JvmStatic
|
97
|
-
fun setNetworkSynchronization(enable: Boolean) {
|
98
|
-
rnIdlingResources?.setNetworkSynchronization(enable)
|
99
|
-
}
|
100
|
-
|
101
96
|
@JvmStatic
|
102
97
|
fun toggleNetworkSynchronization(enable: Boolean) {
|
103
98
|
rnIdlingResources?.let {
|
@@ -129,11 +124,11 @@ object ReactNativeExtension {
|
|
129
124
|
return rnLoadingMonitor.getNewContext()!!
|
130
125
|
}
|
131
126
|
|
132
|
-
private fun enableOrDisableSynchronization(reactContext: ReactContext
|
127
|
+
private fun enableOrDisableSynchronization(reactContext: ReactContext) {
|
133
128
|
if (shouldDisableSynchronization()) {
|
134
129
|
clearAllSynchronization()
|
135
130
|
} else {
|
136
|
-
setupIdlingResources(reactContext
|
131
|
+
setupIdlingResources(reactContext)
|
137
132
|
}
|
138
133
|
}
|
139
134
|
|
@@ -142,10 +137,10 @@ object ReactNativeExtension {
|
|
142
137
|
return launchArgs.hasEnableSynchronization() && launchArgs.enableSynchronization.equals("0")
|
143
138
|
}
|
144
139
|
|
145
|
-
private fun setupIdlingResources(reactContext: ReactContext
|
140
|
+
private fun setupIdlingResources(reactContext: ReactContext) {
|
146
141
|
val launchArgs = LaunchArgs()
|
147
142
|
|
148
|
-
rnIdlingResources = ReactNativeIdlingResources(reactContext, launchArgs
|
143
|
+
rnIdlingResources = ReactNativeIdlingResources(reactContext, launchArgs).apply {
|
149
144
|
registerAll()
|
150
145
|
}
|
151
146
|
}
|
@@ -1,20 +1,13 @@
|
|
1
1
|
package com.wix.detox.reactnative
|
2
2
|
|
3
|
-
import
|
4
|
-
import java.util.Map
|
3
|
+
import com.facebook.react.modules.systeminfo.ReactNativeVersion
|
5
4
|
|
6
5
|
data class RNVersion(val major: Int, val minor: Int, val patch: Int)
|
7
6
|
|
8
7
|
object ReactNativeInfo {
|
9
|
-
private var rnVersion: RNVersion =
|
10
|
-
|
11
|
-
|
12
|
-
val versionMap: Map<String, Int> = Reflect.on(versionClass).field("VERSION").get()
|
13
|
-
RNVersion(versionMap.get("major")!!, versionMap.get("minor")!!, versionMap.get("patch")!!)
|
14
|
-
} catch (e: ClassNotFoundException) {
|
15
|
-
// ReactNativeVersion was introduced in RN50, default to latest previous version.
|
16
|
-
RNVersion(0, 49, 0)
|
17
|
-
}
|
8
|
+
private var rnVersion: RNVersion = ReactNativeVersion.VERSION.run {
|
9
|
+
RNVersion(get("major") as Int, get("minor") as Int, get("patch") as Int)
|
10
|
+
}
|
18
11
|
|
19
12
|
@JvmStatic
|
20
13
|
fun rnVersion() = rnVersion
|
package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxIdlingResource.kt
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
package com.wix.detox.reactnative.idlingresources
|
2
|
+
|
3
|
+
import androidx.test.espresso.IdlingResource
|
4
|
+
import com.wix.detox.espresso.idlingresources.DescriptiveIdlingResource
|
5
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
6
|
+
|
7
|
+
abstract class DetoxIdlingResource : DescriptiveIdlingResource {
|
8
|
+
private var callback: IdlingResource.ResourceCallback? = null
|
9
|
+
private var paused: AtomicBoolean = AtomicBoolean(false)
|
10
|
+
|
11
|
+
fun pause() {
|
12
|
+
paused.set(true)
|
13
|
+
notifyIdle()
|
14
|
+
}
|
15
|
+
|
16
|
+
fun resume() {
|
17
|
+
paused.set(false)
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
|
22
|
+
this.callback = callback
|
23
|
+
}
|
24
|
+
|
25
|
+
final override fun isIdleNow(): Boolean {
|
26
|
+
if (paused.get()) {
|
27
|
+
return true
|
28
|
+
}
|
29
|
+
return checkIdle()
|
30
|
+
}
|
31
|
+
|
32
|
+
open fun onUnregistered() {
|
33
|
+
// no-op
|
34
|
+
}
|
35
|
+
|
36
|
+
protected abstract fun checkIdle(): Boolean
|
37
|
+
|
38
|
+
|
39
|
+
fun notifyIdle() {
|
40
|
+
callback?.onTransitionToIdle()
|
41
|
+
}
|
42
|
+
}
|
@@ -0,0 +1,145 @@
|
|
1
|
+
package com.wix.detox.reactnative.idlingresources
|
2
|
+
|
3
|
+
import android.os.Looper
|
4
|
+
import android.util.Log
|
5
|
+
import androidx.test.espresso.Espresso
|
6
|
+
import androidx.test.espresso.IdlingRegistry
|
7
|
+
import androidx.test.espresso.base.IdlingResourceRegistry
|
8
|
+
import com.facebook.react.bridge.ReactContext
|
9
|
+
import com.wix.detox.LaunchArgs
|
10
|
+
import com.wix.detox.reactnative.idlingresources.factory.DetoxIdlingResourceFactory
|
11
|
+
import com.wix.detox.reactnative.idlingresources.factory.IdlingResourcesName
|
12
|
+
import com.wix.detox.reactnative.idlingresources.factory.LooperName
|
13
|
+
import com.wix.detox.reactnative.idlingresources.looper.MQThreadsReflector
|
14
|
+
import com.wix.detox.reactnative.idlingresources.network.NetworkIdlingResource
|
15
|
+
import kotlinx.coroutines.runBlocking
|
16
|
+
import org.joor.Reflect
|
17
|
+
|
18
|
+
|
19
|
+
private const val LOG_TAG = "DetoxRNIdleRes"
|
20
|
+
|
21
|
+
class ReactNativeIdlingResources(
|
22
|
+
private val reactContext: ReactContext,
|
23
|
+
private var launchArgs: LaunchArgs,
|
24
|
+
private val idlingResourcesFactory: DetoxIdlingResourceFactory = DetoxIdlingResourceFactory(reactContext)
|
25
|
+
) {
|
26
|
+
|
27
|
+
private val idlingResources = mutableMapOf<IdlingResourcesName, DetoxIdlingResource>()
|
28
|
+
private val loopers = mutableMapOf<LooperName, Looper>()
|
29
|
+
|
30
|
+
fun registerAll() {
|
31
|
+
runBlocking {
|
32
|
+
Log.i(LOG_TAG, "Setting up Espresso Idling Resources for React Native")
|
33
|
+
unregisterAll()
|
34
|
+
|
35
|
+
setupUrlBlacklist()
|
36
|
+
setupMQThreadsInterrogators()
|
37
|
+
syncIdlingResources()
|
38
|
+
setupIdlingResources()
|
39
|
+
syncIdlingResources()
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
fun unregisterAll() {
|
44
|
+
unregisterMQThreadsInterrogators()
|
45
|
+
unregisterIdlingResources()
|
46
|
+
}
|
47
|
+
|
48
|
+
fun pauseNetworkSynchronization() = pauseIdlingResource(IdlingResourcesName.Network)
|
49
|
+
fun resumeNetworkSynchronization() {
|
50
|
+
resumeIdlingResource(IdlingResourcesName.Network)
|
51
|
+
}
|
52
|
+
|
53
|
+
fun pauseRNTimersIdlingResource() = pauseIdlingResource(IdlingResourcesName.Timers)
|
54
|
+
fun resumeRNTimersIdlingResource() = resumeIdlingResource(IdlingResourcesName.Timers)
|
55
|
+
fun pauseUIIdlingResource() = pauseIdlingResource(IdlingResourcesName.UIModule)
|
56
|
+
fun resumeUIIdlingResource() = resumeIdlingResource(IdlingResourcesName.UIModule)
|
57
|
+
|
58
|
+
fun setBlacklistUrls(urlList: String) {
|
59
|
+
setIdlingResourceBlacklist(urlList)
|
60
|
+
}
|
61
|
+
|
62
|
+
private fun setIdlingResourceBlacklist(urlList: String) {
|
63
|
+
val urlArray = toFormattedUrlArray(urlList)
|
64
|
+
NetworkIdlingResource.setURLBlacklist(urlArray)
|
65
|
+
}
|
66
|
+
|
67
|
+
private fun setupMQThreadsInterrogators() {
|
68
|
+
setupMQThreadsInterrogator(LooperName.JS)
|
69
|
+
setupMQThreadsInterrogator(LooperName.NativeModules)
|
70
|
+
}
|
71
|
+
|
72
|
+
private fun setupUrlBlacklist() {
|
73
|
+
if (launchArgs.hasURLBlacklist()) {
|
74
|
+
val blacklistUrls = launchArgs.urlBlacklist
|
75
|
+
setIdlingResourceBlacklist(blacklistUrls)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
private fun setupMQThreadsInterrogator(looperName: LooperName) {
|
80
|
+
val mqThreadsReflector = MQThreadsReflector(reactContext)
|
81
|
+
val looper = when (looperName) {
|
82
|
+
LooperName.JS -> mqThreadsReflector.getJSMQueue()?.getLooper()
|
83
|
+
LooperName.NativeModules -> mqThreadsReflector.getNativeModulesQueue()?.getLooper()
|
84
|
+
}
|
85
|
+
|
86
|
+
looper?.let {
|
87
|
+
IdlingRegistry.getInstance().registerLooperAsIdlingResource(it)
|
88
|
+
loopers[looperName] = it
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
private suspend fun setupIdlingResources() {
|
93
|
+
idlingResources.putAll(idlingResourcesFactory.create())
|
94
|
+
idlingResources.forEach { (_, idlingResource) ->
|
95
|
+
IdlingRegistry.getInstance().register(idlingResource)
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
private fun syncIdlingResources() {
|
100
|
+
IdlingRegistry.getInstance().apply {
|
101
|
+
val irr: IdlingResourceRegistry =
|
102
|
+
Reflect.on(Espresso::class.java).field("baseRegistry").get()
|
103
|
+
irr.sync(this.resources, this.loopers)
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
private fun unregisterMQThreadsInterrogators() {
|
108
|
+
loopers.values.forEach {
|
109
|
+
IdlingRegistry.getInstance().unregisterLooperAsIdlingResource(it)
|
110
|
+
}
|
111
|
+
loopers.clear()
|
112
|
+
}
|
113
|
+
|
114
|
+
private fun unregisterIdlingResources() {
|
115
|
+
IdlingResourcesName.entries.forEach {
|
116
|
+
removeIdlingResource(it)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
private fun pauseIdlingResource(idlingResourcesName: IdlingResourcesName) {
|
121
|
+
val idlingResource = idlingResources[idlingResourcesName]
|
122
|
+
idlingResource?.pause()
|
123
|
+
}
|
124
|
+
|
125
|
+
private fun resumeIdlingResource(idlingResourcesName: IdlingResourcesName) {
|
126
|
+
val idlingResource = idlingResources[idlingResourcesName]
|
127
|
+
idlingResource?.resume()
|
128
|
+
}
|
129
|
+
|
130
|
+
private fun removeIdlingResource(idlingResourcesName: IdlingResourcesName) {
|
131
|
+
val idlingResource = idlingResources[idlingResourcesName]
|
132
|
+
idlingResource?.let {
|
133
|
+
IdlingRegistry.getInstance().unregister(it)
|
134
|
+
idlingResource.onUnregistered()
|
135
|
+
idlingResources.remove(idlingResourcesName)
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
private fun toFormattedUrlArray(urlList: String): List<String> {
|
140
|
+
var formattedUrls = urlList
|
141
|
+
formattedUrls = formattedUrls.replace(Regex("""[()"]"""), "")
|
142
|
+
formattedUrls = formattedUrls.trim()
|
143
|
+
return formattedUrls.split(',')
|
144
|
+
}
|
145
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
package com.wix.detox.reactnative.idlingresources.animations
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import android.view.Choreographer
|
5
|
+
import androidx.test.espresso.IdlingResource.ResourceCallback
|
6
|
+
import com.facebook.react.animated.NativeAnimatedModule
|
7
|
+
import com.facebook.react.bridge.ReactContext
|
8
|
+
import com.wix.detox.reactnative.idlingresources.DetoxIdlingResource
|
9
|
+
|
10
|
+
private const val LOG_TAG = "Detox"
|
11
|
+
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Created by simonracz on 25/08/2017.
|
15
|
+
*/
|
16
|
+
/**
|
17
|
+
*
|
18
|
+
* Espresso IdlingResource for React Native's Animated Module.
|
19
|
+
*
|
20
|
+
*
|
21
|
+
* Hooks up to React Native internals to monitor the state of the animations.
|
22
|
+
*
|
23
|
+
*/
|
24
|
+
class AnimatedModuleIdlingResource(private val reactContext: ReactContext) : DetoxIdlingResource(),
|
25
|
+
Choreographer.FrameCallback {
|
26
|
+
|
27
|
+
override fun getName() = AnimatedModuleIdlingResource::class.java.name
|
28
|
+
|
29
|
+
override fun getDebugName(): String {
|
30
|
+
return "AnimatedModule"
|
31
|
+
}
|
32
|
+
|
33
|
+
override fun getBusyHint(): Map<String, Any> {
|
34
|
+
return mapOf("reason" to "Animations running on screen")
|
35
|
+
}
|
36
|
+
|
37
|
+
override fun checkIdle(): Boolean {
|
38
|
+
val animatedModule = reactContext.getNativeModule(NativeAnimatedModule::class.java)
|
39
|
+
val hasAnimations = animatedModule?.nodesManager?.hasActiveAnimations() ?: false
|
40
|
+
|
41
|
+
if (hasAnimations) {
|
42
|
+
Log.i(LOG_TAG, "AnimatedModule is busy.")
|
43
|
+
Choreographer.getInstance().postFrameCallback(this)
|
44
|
+
return false
|
45
|
+
}
|
46
|
+
|
47
|
+
notifyIdle()
|
48
|
+
return true
|
49
|
+
}
|
50
|
+
|
51
|
+
override fun registerIdleTransitionCallback(callback: ResourceCallback?) {
|
52
|
+
super.registerIdleTransitionCallback(callback)
|
53
|
+
Choreographer.getInstance().postFrameCallback(this)
|
54
|
+
}
|
55
|
+
|
56
|
+
override fun doFrame(frameTimeNanos: Long) {
|
57
|
+
isIdleNow
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
package com.wix.detox.reactnative.idlingresources.bridge
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener
|
5
|
+
import com.facebook.react.bridge.ReactContext
|
6
|
+
import com.wix.detox.reactnative.idlingresources.DetoxIdlingResource
|
7
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Created by simonracz on 01/06/2017.
|
11
|
+
*/
|
12
|
+
/**
|
13
|
+
*
|
14
|
+
*
|
15
|
+
* IdlingResource for Espresso, which monitors the traffic of
|
16
|
+
* React Native's JS bridge.
|
17
|
+
*
|
18
|
+
*/
|
19
|
+
class BridgeIdlingResource(private val reactContext: ReactContext) : DetoxIdlingResource(),
|
20
|
+
NotThreadSafeBridgeIdleDebugListener {
|
21
|
+
private val idleNow = AtomicBoolean(true)
|
22
|
+
|
23
|
+
init {
|
24
|
+
reactContext.catalystInstance.addBridgeIdleDebugListener(this)
|
25
|
+
}
|
26
|
+
|
27
|
+
fun onDetach() {
|
28
|
+
reactContext.catalystInstance.removeBridgeIdleDebugListener(this)
|
29
|
+
}
|
30
|
+
|
31
|
+
override fun getName(): String {
|
32
|
+
return BridgeIdlingResource::class.java.name
|
33
|
+
}
|
34
|
+
|
35
|
+
override fun getDebugName(): String {
|
36
|
+
return "bridge"
|
37
|
+
}
|
38
|
+
|
39
|
+
override fun getBusyHint(): Map<String, Any>? {
|
40
|
+
return null
|
41
|
+
}
|
42
|
+
|
43
|
+
override fun checkIdle(): Boolean {
|
44
|
+
val ret = idleNow.get()
|
45
|
+
if (!ret) {
|
46
|
+
Log.i(LOG_TAG, "JS Bridge is busy")
|
47
|
+
}
|
48
|
+
return ret
|
49
|
+
}
|
50
|
+
|
51
|
+
override fun onTransitionToBridgeIdle() {
|
52
|
+
idleNow.set(true)
|
53
|
+
notifyIdle()
|
54
|
+
}
|
55
|
+
|
56
|
+
override fun onTransitionToBridgeBusy() {
|
57
|
+
idleNow.set(false)
|
58
|
+
// Log.i(LOG_TAG, "JS Bridge transitions to busy.");
|
59
|
+
}
|
60
|
+
|
61
|
+
override fun onBridgeDestroyed() {
|
62
|
+
}
|
63
|
+
|
64
|
+
override fun onUnregistered() {
|
65
|
+
super.onUnregistered()
|
66
|
+
onDetach()
|
67
|
+
}
|
68
|
+
|
69
|
+
companion object {
|
70
|
+
private const val LOG_TAG = "Detox"
|
71
|
+
}
|
72
|
+
}
|