detox 19.10.0 → 19.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Detox-android/com/wix/detox/{19.10.0/detox-19.10.0-javadoc.jar → 19.11.0/detox-19.11.0-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{19.10.0/detox-19.10.0-sources.jar → 19.11.0/detox-19.11.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.aar +0 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{19.10.0/detox-19.10.0.pom → 19.11.0/detox-19.11.0.pom} +1 -1
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/19.11.0/detox-19.11.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-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
- package/package.json +2 -2
- package/runners/jest-circus/listeners/DetoxCoreListener.js +24 -15
- package/src/DetoxExportWrapper.js +1 -1
- package/src/android/core/NativeElement.js +56 -20
- package/src/android/core/NativeExpect.js +28 -9
- package/src/android/interactions/native.js +24 -18
- package/src/artifacts/timeline/TimelineArtifactPlugin.js +6 -9
- package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
- package/src/devices/allocation/DeviceAllocator.js +1 -2
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +1 -2
- package/src/devices/runtime/RuntimeDevice.js +7 -11
- package/src/ios/expectTwo.js +152 -67
- package/src/utils/invocationTraceDescriptions.js +43 -0
- package/src/utils/trace.js +52 -10
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.aar +0 -0
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/19.10.0/detox-19.10.0.pom.sha512 +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9aba5676c7298fb259def31abb2391c2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8489941696f685e4d9ee0f2695e524a9ee882ff7
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
5c074864be82defddfe6f03d23f1023718773a6caf867fd6de97306167b96c10
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fc404aa3532e1bf13a1e12871b9a4d6c27575cacdfae5b76179308f321091b67d60f5a81e74bd0b3d6304a7930c3a9f79d15015fda37d4cdc5cb849274eb4b6b
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c607efb999d878b919150d3c868094fe
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
18641f7574235c6ec8c81ea52b75442ce919f213
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0e23270810340a40547ede0002fb741353646db1878d5825f67a2212a13d3d41
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
440caa1e9ede22144e4f55d2c2c034c13e4b336f9f387f0fa0811bd651612c0bef7981c1b1ae826ab78519185c930a9287a6c6f3c76a554184282fdf8684a344
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
88fff568e621751c02f293579cce453a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9398e3ea8573a634ddc61abf4f6b21d9e17ba728
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ae00e739f49017b43024ff3a508e03dafa7f002b406a746f43f742fa6c21cd15
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0239c96c8027c9274b6823bfadd5ddea7ca0803db694f53ee30d0d39b8ce5c4dd8d72f4e7d0af089db5d722fecf629e81b62759b5dc4cc434be86910b9b37f5d
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
|
4
4
|
<groupId>com.wix</groupId>
|
|
5
5
|
<artifactId>detox</artifactId>
|
|
6
|
-
<version>19.
|
|
6
|
+
<version>19.11.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>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2300f079161364c78e01d8c27334ac7f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1031ee5586ac864c9b0cbcaa5876dfbc07325f1f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
25d21ff3daef4e4da80808464fc808efbd4d0fa75f5e88ce9376fb1d85a922d8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c1fae4e858403138b44db05d47128f74c1ac8b14a9f55dcae90ef90800040507bb8bdd97af6c64d26811ddcdf14be1a341531e4c8a4fab0323f500167b4d3499
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>com.wix</groupId>
|
|
4
4
|
<artifactId>detox</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>19.
|
|
7
|
-
<release>19.
|
|
6
|
+
<latest>19.11.0</latest>
|
|
7
|
+
<release>19.11.0</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>19.
|
|
9
|
+
<version>19.11.0</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20220831134632</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
63739c1fd16a9d1140a49b7857aa0fdf
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
0dcec1feec1b37fdf53e88ab4779a702631cd864
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
e1c67c307a105c7c7c82fae75e7d56f8b9718b1bb7dc9f604560909f39dce425
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c5633deb1fbf020dd6bc03ba8796bd5bd85de50efadc76870c3e5f5cc2b27191bad2a59ea37abb50a96accc373810fa45799d1f60f4dd499637d3eef1f6d8601
|
package/Detox-ios-src.tbz
CHANGED
|
Binary file
|
package/Detox-ios.tbz
CHANGED
|
Binary file
|
|
@@ -14,6 +14,7 @@ public class LaunchArgs {
|
|
|
14
14
|
private static final String DETOX_NOTIFICATION_PATH_ARG = "detoxUserNotificationDataURL";
|
|
15
15
|
private static final String DETOX_BLACKLIST_URLS_ARG = "detoxURLBlacklistRegex";
|
|
16
16
|
private static final String DETOX_URL_OVERRIDE_ARG = "detoxURLOverride";
|
|
17
|
+
private static final String DETOX_ENABLE_SYNCHRONIZATION = "detoxEnableSynchronization";
|
|
17
18
|
private static final List<String> RESERVED_INSTRUMENTATION_ARGS = Arrays.asList("class", "package", "func", "unit", "size", "perf", "debug", "log", "emma", "coverageFile");
|
|
18
19
|
|
|
19
20
|
public boolean hasNotificationPath() {
|
|
@@ -36,6 +37,14 @@ public class LaunchArgs {
|
|
|
36
37
|
return InstrumentationRegistry.getArguments().containsKey(DETOX_BLACKLIST_URLS_ARG);
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
public String getEnableSynchronization() {
|
|
41
|
+
return InstrumentationRegistry.getArguments().getString(DETOX_ENABLE_SYNCHRONIZATION);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public boolean hasEnableSynchronization() {
|
|
45
|
+
return InstrumentationRegistry.getArguments().containsKey(DETOX_ENABLE_SYNCHRONIZATION);
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
public String getUrlOverride() {
|
|
40
49
|
return InstrumentationRegistry.getArguments().getString(DETOX_URL_OVERRIDE_ARG);
|
|
41
50
|
}
|
|
@@ -39,7 +39,7 @@ object ReactNativeExtension {
|
|
|
39
39
|
reloadReactNativeInBackground(it)
|
|
40
40
|
val reactContext = awaitNewReactNativeContext(it, previousReactContext)
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
enableOrDisableSynchronization(reactContext, networkSyncEnabled)
|
|
43
43
|
hackRN50OrHigherWaitForReady()
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -58,7 +58,7 @@ object ReactNativeExtension {
|
|
|
58
58
|
(applicationContext as ReactApplication).let {
|
|
59
59
|
val reactContext = awaitNewReactNativeContext(it, null)
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
enableOrDisableSynchronization(reactContext)
|
|
62
62
|
hackRN50OrHigherWaitForReady()
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -124,6 +124,19 @@ object ReactNativeExtension {
|
|
|
124
124
|
return rnLoadingMonitor.getNewContext()!!
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
private fun enableOrDisableSynchronization(reactContext: ReactContext, networkSyncEnabled: Boolean = true) {
|
|
128
|
+
if (shouldDisableSynchronization()) {
|
|
129
|
+
clearAllSynchronization()
|
|
130
|
+
} else {
|
|
131
|
+
setupIdlingResources(reactContext, networkSyncEnabled)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private fun shouldDisableSynchronization(): Boolean {
|
|
136
|
+
val launchArgs = LaunchArgs()
|
|
137
|
+
return launchArgs.hasEnableSynchronization() && launchArgs.enableSynchronization.equals("0")
|
|
138
|
+
}
|
|
139
|
+
|
|
127
140
|
private fun setupIdlingResources(reactContext: ReactContext, networkSyncEnabled: Boolean = true) {
|
|
128
141
|
val launchArgs = LaunchArgs()
|
|
129
142
|
|
|
@@ -2,6 +2,7 @@ package com.wix.detox.reactnative
|
|
|
2
2
|
|
|
3
3
|
import android.os.Looper
|
|
4
4
|
import android.util.Log
|
|
5
|
+
import androidx.test.espresso.Espresso
|
|
5
6
|
import androidx.test.espresso.IdlingRegistry
|
|
6
7
|
import androidx.test.espresso.base.IdlingResourceRegistry
|
|
7
8
|
import com.facebook.react.bridge.ReactContext
|
|
@@ -12,7 +13,6 @@ import com.wix.detox.reactnative.idlingresources.timers.getInterrogationStrategy
|
|
|
12
13
|
import com.wix.detox.reactnative.idlingresources.uimodule.UIModuleIdlingResource
|
|
13
14
|
import org.joor.Reflect
|
|
14
15
|
import org.joor.ReflectException
|
|
15
|
-
import java.util.Set
|
|
16
16
|
|
|
17
17
|
private const val LOG_TAG = "DetoxRNIdleRes"
|
|
18
18
|
|
|
@@ -46,15 +46,11 @@ private class MQThreadReflected(private val queue: Any?, private val queueName:
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
class ReactNativeIdlingResources constructor(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
49
|
+
private val reactContext: ReactContext,
|
|
50
|
+
private var launchArgs: LaunchArgs,
|
|
51
|
+
internal var networkSyncEnabled: Boolean = true
|
|
52
|
+
) {
|
|
56
53
|
companion object {
|
|
57
|
-
private const val FIELD_UI_BG_MSG_QUEUE = "mUiBackgroundMessageQueueThread"
|
|
58
54
|
private const val FIELD_NATIVE_MODULES_MSG_QUEUE = "mNativeModulesMessageQueueThread"
|
|
59
55
|
private const val FIELD_JS_MSG_QUEUE = "mJSMessageQueueThread"
|
|
60
56
|
}
|
|
@@ -69,17 +65,11 @@ class ReactNativeIdlingResources constructor(
|
|
|
69
65
|
|
|
70
66
|
fun registerAll() {
|
|
71
67
|
Log.i(LOG_TAG, "Setting up Espresso Idling Resources for React Native")
|
|
72
|
-
|
|
73
68
|
unregisterAll()
|
|
74
69
|
|
|
75
|
-
|
|
76
|
-
val blacklistUrls = launchArgs.getURLBlacklist()
|
|
77
|
-
setBlacklistUrls(blacklistUrls)
|
|
78
|
-
}
|
|
79
|
-
|
|
70
|
+
setupUrlBlacklist()
|
|
80
71
|
setupMQThreadsInterrogators()
|
|
81
72
|
syncIdlingResources()
|
|
82
|
-
|
|
83
73
|
setupCustomRNIdlingResources()
|
|
84
74
|
syncIdlingResources()
|
|
85
75
|
}
|
|
@@ -108,28 +98,42 @@ class ReactNativeIdlingResources constructor(
|
|
|
108
98
|
networkIdlingResource?.resume()
|
|
109
99
|
}
|
|
110
100
|
}
|
|
101
|
+
|
|
111
102
|
fun pauseRNTimersIdlingResource() = timersIdlingResource?.pause()
|
|
112
103
|
fun resumeRNTimersIdlingResource() = timersIdlingResource?.resume()
|
|
113
104
|
fun pauseUIIdlingResource() = uiModuleIdlingResource?.pause()
|
|
114
105
|
fun resumeUIIdlingResource() = uiModuleIdlingResource?.resume()
|
|
115
|
-
|
|
116
|
-
fun
|
|
106
|
+
|
|
107
|
+
fun setBlacklistUrls(urlList: String) {
|
|
108
|
+
setIldingResourceBlacklist(urlList)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private fun setIldingResourceBlacklist(urlList: String) {
|
|
112
|
+
val urlArray = toFormattedUrlArray(urlList)
|
|
113
|
+
NetworkIdlingResource.setURLBlacklist(urlArray)
|
|
114
|
+
}
|
|
117
115
|
|
|
118
116
|
private fun setupMQThreadsInterrogators() {
|
|
119
117
|
if (IdlingRegistry.getInstance().loopers.isEmpty()) {
|
|
120
118
|
val mqThreadsReflector = MQThreadsReflector(reactContext)
|
|
121
|
-
// val mqUIBackground = mqThreadsReflector.getQueue(FIELD_UI_BG_MSG_QUEUE)?.getLooper() TODO
|
|
122
119
|
val mqJS = mqThreadsReflector.getQueue(FIELD_JS_MSG_QUEUE)?.getLooper()
|
|
123
|
-
val mqNativeModules =
|
|
120
|
+
val mqNativeModules =
|
|
121
|
+
mqThreadsReflector.getQueue(FIELD_NATIVE_MODULES_MSG_QUEUE)?.getLooper()
|
|
124
122
|
|
|
125
123
|
IdlingRegistry.getInstance().apply {
|
|
126
|
-
// registerLooperAsIdlingResource(mqUIBackground)
|
|
127
124
|
registerLooperAsIdlingResource(mqJS)
|
|
128
125
|
registerLooperAsIdlingResource(mqNativeModules)
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
128
|
}
|
|
132
129
|
|
|
130
|
+
private fun setupUrlBlacklist() {
|
|
131
|
+
if (launchArgs.hasURLBlacklist()) {
|
|
132
|
+
val blacklistUrls = launchArgs.urlBlacklist
|
|
133
|
+
setIldingResourceBlacklist(blacklistUrls)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
133
137
|
private fun setupCustomRNIdlingResources() {
|
|
134
138
|
rnBridgeIdlingResource = BridgeIdlingResource(reactContext)
|
|
135
139
|
timersIdlingResource = TimersIdlingResource(getInterrogationStrategy(reactContext)!!)
|
|
@@ -151,13 +155,16 @@ class ReactNativeIdlingResources constructor(
|
|
|
151
155
|
|
|
152
156
|
private fun syncIdlingResources() {
|
|
153
157
|
IdlingRegistry.getInstance().apply {
|
|
154
|
-
val irr: IdlingResourceRegistry =
|
|
158
|
+
val irr: IdlingResourceRegistry =
|
|
159
|
+
Reflect.on(Espresso::class.java).field("baseRegistry").get()
|
|
155
160
|
irr.sync(this.resources, this.loopers)
|
|
156
161
|
}
|
|
157
162
|
}
|
|
158
163
|
|
|
159
164
|
private fun unregisterMQThreadsInterrogators() {
|
|
160
|
-
|
|
165
|
+
val idlingResourceInstance = IdlingRegistry.getInstance()
|
|
166
|
+
val loopersField = Reflect.on(idlingResourceInstance).field("loopers")
|
|
167
|
+
loopersField.get<MutableSet<Any>>().clear()
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
private fun unregisterCustomRNIdlingResources() {
|
|
@@ -166,7 +173,8 @@ class ReactNativeIdlingResources constructor(
|
|
|
166
173
|
timersIdlingResource,
|
|
167
174
|
rnBridgeIdlingResource,
|
|
168
175
|
uiModuleIdlingResource,
|
|
169
|
-
animIdlingResource
|
|
176
|
+
animIdlingResource
|
|
177
|
+
)
|
|
170
178
|
rnBridgeIdlingResource?.onDetach()
|
|
171
179
|
|
|
172
180
|
removeNetworkIdlingResource()
|
|
@@ -174,13 +182,15 @@ class ReactNativeIdlingResources constructor(
|
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
private fun setupAsyncStorageIdlingResource() {
|
|
177
|
-
asyncStorageIdlingResource =
|
|
178
|
-
|
|
179
|
-
|
|
185
|
+
asyncStorageIdlingResource =
|
|
186
|
+
AsyncStorageIdlingResource.createIfNeeded(reactContext, false)?.also {
|
|
187
|
+
IdlingRegistry.getInstance().register(it)
|
|
188
|
+
}
|
|
180
189
|
|
|
181
|
-
legacyAsyncStorageIdlingResource =
|
|
182
|
-
|
|
183
|
-
|
|
190
|
+
legacyAsyncStorageIdlingResource =
|
|
191
|
+
AsyncStorageIdlingResource.createIfNeeded(reactContext, true)?.also {
|
|
192
|
+
IdlingRegistry.getInstance().register(it)
|
|
193
|
+
}
|
|
184
194
|
}
|
|
185
195
|
|
|
186
196
|
private fun removeAsyncStorageIdlingResource() {
|
|
@@ -212,13 +222,8 @@ class ReactNativeIdlingResources constructor(
|
|
|
212
222
|
|
|
213
223
|
private fun toFormattedUrlArray(urlList: String): List<String> {
|
|
214
224
|
var formattedUrls = urlList
|
|
215
|
-
formattedUrls = formattedUrls.replace(Regex("""[()"]"""), "")
|
|
216
|
-
formattedUrls = formattedUrls.trim()
|
|
217
|
-
return formattedUrls.split(',')
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
fun setBlacklistUrls(urlList: String) {
|
|
221
|
-
val urlArray = toFormattedUrlArray(urlList)
|
|
222
|
-
NetworkIdlingResource.setURLBlacklist(urlArray);
|
|
225
|
+
formattedUrls = formattedUrls.replace(Regex("""[()"]"""), "")
|
|
226
|
+
formattedUrls = formattedUrls.trim()
|
|
227
|
+
return formattedUrls.split(',')
|
|
223
228
|
}
|
|
224
229
|
}
|
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": "19.
|
|
4
|
+
"version": "19.11.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"detox": "local-cli/cli.js"
|
|
7
7
|
},
|
|
@@ -177,5 +177,5 @@
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
},
|
|
180
|
-
"gitHead": "
|
|
180
|
+
"gitHead": "900cdb17bd766869cb2d46915ff2c7821808c676"
|
|
181
181
|
}
|
|
@@ -22,16 +22,6 @@ class DetoxCoreListener {
|
|
|
22
22
|
this.detox = detox;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
_getTestInvocations(test) {
|
|
26
|
-
const { DETOX_RERUN_INDEX } = process.env;
|
|
27
|
-
|
|
28
|
-
if (!isNaN(DETOX_RERUN_INDEX)) {
|
|
29
|
-
return Number(DETOX_RERUN_INDEX) * this._testRunTimes + test.invocations;
|
|
30
|
-
} else {
|
|
31
|
-
return test.invocations;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
25
|
async run_describe_start({ describeBlock: { name, children } }) {
|
|
36
26
|
if (children.length) {
|
|
37
27
|
await this.detox[onRunDescribeStart]({ name });
|
|
@@ -80,20 +70,39 @@ class DetoxCoreListener {
|
|
|
80
70
|
this._startedTests.add(test);
|
|
81
71
|
|
|
82
72
|
await this.detox[onTestStart]({
|
|
73
|
+
...this._getTestMetadata(test),
|
|
74
|
+
status: 'running',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_getTestMetadata(test) {
|
|
79
|
+
return {
|
|
83
80
|
title: test.name,
|
|
81
|
+
parent: test.parent.name,
|
|
84
82
|
fullName: getFullTestName(test),
|
|
85
83
|
status: 'running',
|
|
84
|
+
functionCode: test.fn.toString(),
|
|
86
85
|
invocations: this._getTestInvocations(test),
|
|
87
|
-
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
_getTestInvocations(test) {
|
|
90
|
+
const { DETOX_RERUN_INDEX } = process.env;
|
|
91
|
+
|
|
92
|
+
if (!isNaN(DETOX_RERUN_INDEX)) {
|
|
93
|
+
return Number(DETOX_RERUN_INDEX) * this._testRunTimes + test.invocations;
|
|
94
|
+
} else {
|
|
95
|
+
return test.invocations;
|
|
96
|
+
}
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
async test_done({ test }) {
|
|
91
100
|
if (this._startedTests.has(test)) {
|
|
92
101
|
await this.detox[onTestDone]({
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
...this._getTestMetadata(test),
|
|
103
|
+
status: _.isEmpty(test.errors) ? 'passed' : 'failed',
|
|
104
|
+
errors: _.isEmpty(test.errors) ? undefined : test.errors,
|
|
105
|
+
asyncError: _.isEmpty(test.asyncError) ? undefined : test.asyncError,
|
|
97
106
|
timedOut: hasTimedOut(test)
|
|
98
107
|
});
|
|
99
108
|
|
|
@@ -5,6 +5,7 @@ const tempfile = require('tempfile');
|
|
|
5
5
|
|
|
6
6
|
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
|
7
7
|
const invoke = require('../../invoke');
|
|
8
|
+
const { actionDescription } = require('../../utils/invocationTraceDescriptions');
|
|
8
9
|
const actions = require('../actions/native');
|
|
9
10
|
const DetoxMatcherApi = require('../espressoapi/DetoxMatcher');
|
|
10
11
|
const { ActionInteraction } = require('../interactions/native');
|
|
@@ -18,12 +19,11 @@ class NativeElement {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
_selectElementWithMatcher(matcher) {
|
|
21
|
-
// if (!(matcher instanceof NativeMatcher)) throw new DetoxRuntimeError(`Element _selectElementWithMatcher argument must be a valid NativeMatcher, got ${typeof matcher}`);
|
|
22
22
|
this._call = invoke.call(invoke.Espresso, 'onView', matcher._call);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
atIndex(index) {
|
|
26
|
-
if (typeof index !== 'number') throw new DetoxRuntimeError(`Element atIndex argument must be a number, got ${typeof index}`);
|
|
26
|
+
if (typeof index !== 'number') throw new DetoxRuntimeError({ message: `Element atIndex argument must be a number, got ${typeof index}` });
|
|
27
27
|
const matcher = this._originalMatcher;
|
|
28
28
|
this._originalMatcher._call = invoke.callDirectly(DetoxMatcherApi.matcherForAtIndex(index, matcher._call.value));
|
|
29
29
|
|
|
@@ -32,56 +32,84 @@ class NativeElement {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async tap(value) {
|
|
35
|
-
|
|
35
|
+
const action = new actions.TapAction(value);
|
|
36
|
+
const traceDescription = actionDescription.tapAtPoint(value);
|
|
37
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
async tapAtPoint(value) {
|
|
39
|
-
|
|
41
|
+
const action = new actions.TapAtPointAction(value);
|
|
42
|
+
const traceDescription = actionDescription.tapAtPoint(value);
|
|
43
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
async longPress() {
|
|
43
|
-
|
|
47
|
+
const action = new actions.LongPressAction();
|
|
48
|
+
const traceDescription = actionDescription.longPress();
|
|
49
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
async multiTap(times) {
|
|
47
|
-
|
|
53
|
+
if (typeof times !== 'number') throw new Error('times should be a number, but got ' + (times + (' (' + (typeof times + ')'))));
|
|
54
|
+
if (times < 1) throw new Error('times should be greater than 0, but got ' + times);
|
|
55
|
+
|
|
56
|
+
const action = new actions.MultiClickAction(times);
|
|
57
|
+
const traceDescription = actionDescription.multiTap(times);
|
|
58
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
async tapBackspaceKey() {
|
|
51
|
-
|
|
62
|
+
const action = new actions.PressKeyAction(67);
|
|
63
|
+
const traceDescription = actionDescription.tapBackspaceKey();
|
|
64
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
async tapReturnKey() {
|
|
55
|
-
|
|
68
|
+
const action = new actions.TypeTextAction('\n');
|
|
69
|
+
const traceDescription = actionDescription.tapReturnKey();
|
|
70
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
async typeText(value) {
|
|
59
|
-
|
|
74
|
+
const action = new actions.TypeTextAction(value);
|
|
75
|
+
const traceDescription = actionDescription.typeText(value);
|
|
76
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
async replaceText(value) {
|
|
63
|
-
|
|
80
|
+
const action = new actions.ReplaceTextAction(value);
|
|
81
|
+
const traceDescription = actionDescription.replaceText(value);
|
|
82
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
64
83
|
}
|
|
65
84
|
|
|
66
85
|
async clearText() {
|
|
67
|
-
|
|
86
|
+
const action = new actions.ClearTextAction();
|
|
87
|
+
const traceDescription = actionDescription.clearText();
|
|
88
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
async scroll(amount, direction = 'down', startPositionX, startPositionY) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return await new ActionInteraction(this._invocationManager, this,
|
|
92
|
+
const action = new actions.ScrollAmountAction(direction, amount, startPositionX, startPositionY);
|
|
93
|
+
const traceDescription = actionDescription.scroll(amount, direction, startPositionX, startPositionY);
|
|
94
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
74
95
|
}
|
|
75
96
|
|
|
76
97
|
async scrollTo(edge) {
|
|
77
98
|
// override the user's element selection with an extended matcher that looks for UIScrollView children
|
|
78
99
|
this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
|
|
79
|
-
|
|
100
|
+
|
|
101
|
+
const action = new actions.ScrollEdgeAction(edge);
|
|
102
|
+
const traceDescription = actionDescription.scrollTo(edge);
|
|
103
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
80
104
|
}
|
|
81
105
|
|
|
82
106
|
async scrollToIndex(index) {
|
|
107
|
+
// override the user's element selection with an extended matcher that looks for UIScrollView children
|
|
83
108
|
this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
|
|
84
|
-
|
|
109
|
+
|
|
110
|
+
const action = new actions.ScrollToIndex(index);
|
|
111
|
+
const traceDescription = actionDescription.scrollToIndex(index);
|
|
112
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
85
113
|
}
|
|
86
114
|
|
|
87
115
|
/**
|
|
@@ -96,13 +124,17 @@ class NativeElement {
|
|
|
96
124
|
|
|
97
125
|
// override the user's element selection with an extended matcher that avoids RN issues with RCTScrollView
|
|
98
126
|
this._selectElementWithMatcher(this._originalMatcher._avoidProblematicReactNativeElements());
|
|
127
|
+
|
|
99
128
|
const action = new actions.SwipeAction(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
|
|
100
|
-
|
|
129
|
+
const traceDescription = actionDescription.swipe(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
|
|
130
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
101
131
|
}
|
|
102
132
|
|
|
103
133
|
async takeScreenshot(screenshotName) {
|
|
104
134
|
// TODO this should be moved to a lower-layer handler of this use-case
|
|
105
|
-
const
|
|
135
|
+
const action = new actions.TakeElementScreenshot();
|
|
136
|
+
const traceDescription = actionDescription.takeScreenshot(screenshotName);
|
|
137
|
+
const resultBase64 = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
106
138
|
const filePath = tempfile('detox.element-screenshot.png');
|
|
107
139
|
await fs.writeFile(filePath, resultBase64, 'base64');
|
|
108
140
|
|
|
@@ -115,12 +147,16 @@ class NativeElement {
|
|
|
115
147
|
}
|
|
116
148
|
|
|
117
149
|
async getAttributes() {
|
|
118
|
-
const
|
|
150
|
+
const action = new actions.GetAttributes();
|
|
151
|
+
const traceDescription = actionDescription.getAttributes();
|
|
152
|
+
const result = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
119
153
|
return JSON.parse(result);
|
|
120
154
|
}
|
|
121
155
|
|
|
122
156
|
async adjustSliderToPosition(newPosition) {
|
|
123
|
-
|
|
157
|
+
const action = new actions.AdjustSliderToPosition(newPosition);
|
|
158
|
+
const traceDescription = actionDescription.adjustSliderToPosition(newPosition);
|
|
159
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
|
124
160
|
}
|
|
125
161
|
}
|
|
126
162
|
|