detox 20.0.6-breaking.new-global-lifecycle.0 → 20.0.7-prerelease.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha512 +1 -0
  21. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  22. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  23. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  24. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  25. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  26. package/Detox-ios-src.tbz +0 -0
  27. package/Detox-ios.tbz +0 -0
  28. package/android/detox/proguard-rules-app.pro +4 -0
  29. package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
  30. package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
  31. package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
  32. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
  33. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
  34. package/index.d.ts +10 -1
  35. package/package.json +2 -2
  36. package/runners/jest/testEnvironment/index.js +3 -2
  37. package/src/DetoxWorker.js +0 -6
  38. package/src/android/core/NativeElement.js +56 -20
  39. package/src/android/core/NativeExpect.js +28 -9
  40. package/src/android/interactions/native.js +24 -18
  41. package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
  42. package/src/client/Client.js +18 -1
  43. package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
  44. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +3 -1
  45. package/src/devices/runtime/RuntimeDevice.js +2 -4
  46. package/src/devices/runtime/drivers/android/AndroidDriver.js +9 -1
  47. package/src/ios/expectTwo.js +152 -67
  48. package/src/logger/DetoxLogger.js +5 -1
  49. package/src/logger/utils/tracerLegacy.js +24 -1
  50. package/src/utils/errorUtils.js +4 -3
  51. package/src/utils/invocationTraceDescriptions.js +43 -0
  52. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
  53. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
  54. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
  55. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
  56. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
  57. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
  58. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
  59. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
  60. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar +0 -0
  61. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.md5 +0 -1
  62. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
  63. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
  64. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
  65. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.md5 +0 -1
  66. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
  67. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
  68. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
@@ -0,0 +1 @@
1
+ 6ee9bcfa6e27561a20785f38d6978a16091d3da2
@@ -0,0 +1 @@
1
+ 06ad5ed2c2c02a65f50c2913c88d9d83361b43decd36f3094ebbe088bbb5f784
@@ -0,0 +1 @@
1
+ 4eaa276ed4517115f488a2fd76b24df233eb630eacf10544a90d7ef57ab0bf827d7495c9b0f39fd79edf7568bbde0b693d8bec308257bc1f0804a7dc6a32161f
@@ -0,0 +1 @@
1
+ f4fe7c3a998cef8964ff7f5af05eb529b38e09ee
@@ -0,0 +1 @@
1
+ 114b949bbbf5f8fe5f6f355f5f629edb38e08e2221b6303e34a638c7bb824765
@@ -0,0 +1 @@
1
+ c77832e978a4e102716c7fd6fa70d04645e02c8a377bdf09cfa482a8f70a514c5d35d7dd4f0c10b5dcd690817a3fb740f2a7914fc905a22489522e7363f9f44d
@@ -0,0 +1 @@
1
+ 90f9a8b95a3f10adc93442d4f4684092
@@ -0,0 +1 @@
1
+ f03ce7143af53f09f8734c8ee3eb5a532f8143fa
@@ -0,0 +1 @@
1
+ 742ad662c67c18780e0844567205b1d02772f160b1876154cbe485bf8048c461
@@ -0,0 +1 @@
1
+ dfd697ec8d6f5ee8296379bbbf3f5b487ad70a729a658c6118b2e4923c10959bdd56a30959eb48afa1cf0bfe210ba8a500423d6b9f3993c2570505d59288c0de
@@ -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.0.6-breaking.new-global-lifecycle.0</version>
6
+ <version>20.0.7-prerelease.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
+ 7bf66c5ea2c958c30ac7565193ba4bc8
@@ -0,0 +1 @@
1
+ 2485b54c1a62e1557d76ebc51a1741ccc4f10304
@@ -0,0 +1 @@
1
+ d133d5b090110c223f578f117b344a1bb1e86c3df2d55f50dfd00f1b17498254
@@ -0,0 +1 @@
1
+ 11a29cc20eb22ce2133475e187c0941b7d32bff186857ddceb2ee88f3f3b1d46e32eb0cbed032598f57933cca7b9ed8d36008d9c8b882dc202afdd20d9fe5def
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.0.6-breaking.new-global-lifecycle.0</latest>
7
- <release>20.0.6-breaking.new-global-lifecycle.0</release>
6
+ <latest>20.0.7-prerelease.0</latest>
7
+ <release>20.0.7-prerelease.0</release>
8
8
  <versions>
9
- <version>20.0.6-breaking.new-global-lifecycle.0</version>
9
+ <version>20.0.7-prerelease.0</version>
10
10
  </versions>
11
- <lastUpdated>20220905115247</lastUpdated>
11
+ <lastUpdated>20220906143110</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 97dde91895b9c45b58fb7cc6364a9e8d
1
+ 443209a3d276fc780cececc129d8e70b
@@ -1 +1 @@
1
- 11290dd2dfe8f2c159e0e12f674e42613903c592
1
+ 283f03aa8235477f8b3070d4cfa36018d5a7fe7f
@@ -1 +1 @@
1
- 077984469b0de32349680ac5d31fd15ad7f4bc9bbcb81cc9e6a1138a14c5ad57
1
+ 40762b77b08b8369c14f0f11ecf0832d7fd56ecaa618b1a0a62c3c5d16938ed9
@@ -1 +1 @@
1
- 15ce6f12a05807a757acb5ae887aac0ffac8cc2738327275ada27b3b4849662a832fce5203d3a5aca7223b49b438176e990204726878456f5cb9dadb0f1a38d9
1
+ 5b3fceef49c72fa0bd12736858bf0e6f16cefc317c648ff83525d2fdc4b7831cce101c206d3640ba7a79edc432b90d481f279cba5285f7c36ce1f613caf163f6
package/Detox-ios-src.tbz CHANGED
Binary file
package/Detox-ios.tbz CHANGED
Binary file
@@ -6,6 +6,10 @@
6
6
  -keep class com.facebook.react.ReactNativeHost { *; }
7
7
  -keep class com.facebook.react.ReactInstanceManager { *; }
8
8
  -keep class com.facebook.react.ReactInstanceManager** { *; }
9
+ -keep class com.facebook.react.ReactInstanceEventListener { *; }
10
+
11
+ -keep class com.facebook.react.views.slider.ReactSlider { *; }
12
+ -keep class com.reactnativecommunity.slider.ReactSlider { *; }
9
13
  -keep class com.reactnativecommunity.asyncstorage.** { *; }
10
14
 
11
15
  -keep class kotlin.jvm.** { *; }
@@ -6,7 +6,7 @@ import com.wix.detox.adapters.server.OutboundServerAdapter
6
6
  class DetoxCrashHandler(private val outboundServerAdapter: OutboundServerAdapter) {
7
7
  fun attach() {
8
8
  Thread.setDefaultUncaughtExceptionHandler { thread, exception ->
9
- Log.e(LOG_TAG, "Crash detected!!! thread=${thread.name} (${thread.id})")
9
+ Log.e(LOG_TAG, "Crash detected!!! thread=${thread.name} (${thread.id})", exception)
10
10
 
11
11
  val crashInfo = mapOf("errorDetails" to "@Thread ${thread.name}(${thread.id}):\n${Log.getStackTraceString(exception)}\nCheck device logs for full details!")
12
12
  outboundServerAdapter.sendMessage(ACTION_NAME, crashInfo, MESSAGE_ID)
@@ -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
  }
@@ -10,7 +10,7 @@ import com.wix.detox.reactnative.ReactNativeExtension
10
10
 
11
11
  class TestEngineFacade {
12
12
  fun awaitIdle(): Unit? = Espresso.onIdle() {
13
- Log.i(LOG_TAG, "Wait is over: app is now idle!")
13
+ Log.i(LOG_TAG, "Wait is over: App is now idle!")
14
14
  null
15
15
  }
16
16
  fun syncIdle() = UiAutomatorHelper.espressoSync() // TODO Check whether this can be replaced with #awaitIdle()
@@ -39,7 +39,7 @@ object ReactNativeExtension {
39
39
  reloadReactNativeInBackground(it)
40
40
  val reactContext = awaitNewReactNativeContext(it, previousReactContext)
41
41
 
42
- setupIdlingResources(reactContext, networkSyncEnabled)
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
- setupIdlingResources(reactContext)
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
- private val reactContext: ReactContext,
50
- private var launchArgs: LaunchArgs,
51
- internal var networkSyncEnabled: Boolean = true
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
- if (launchArgs.hasURLBlacklist()) {
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
- fun pauseJSBridgeIdlingResource() = rnBridgeIdlingResource?.pause()
116
- fun resumeJSBridgeIdlingResource() = rnBridgeIdlingResource?.resume()
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 = mqThreadsReflector.getQueue(FIELD_NATIVE_MODULES_MSG_QUEUE)?.getLooper()
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 = Reflect.on(androidx.test.espresso.Espresso::class.java).field("baseRegistry").get()
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
- Reflect.on(IdlingRegistry.getInstance()).field("loopers").get<Set<Any>>().clear()
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 = AsyncStorageIdlingResource.createIfNeeded(reactContext, false)?.also {
178
- IdlingRegistry.getInstance().register(it)
179
- }
185
+ asyncStorageIdlingResource =
186
+ AsyncStorageIdlingResource.createIfNeeded(reactContext, false)?.also {
187
+ IdlingRegistry.getInstance().register(it)
188
+ }
180
189
 
181
- legacyAsyncStorageIdlingResource = AsyncStorageIdlingResource.createIfNeeded(reactContext, true)?.also {
182
- IdlingRegistry.getInstance().register(it)
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/index.d.ts CHANGED
@@ -353,12 +353,21 @@ declare global {
353
353
  readonly startSection: (name: string) => void;
354
354
  /** @deprecated */
355
355
  readonly endSection: (name: string) => void;
356
+ /** @private */
357
+ readonly invocationCall: (...args: unknown[]) => unknown;
356
358
  };
357
359
 
358
360
  /**
361
+ * Trace a single call, with a given name and arguments.
362
+ *
359
363
  * @deprecated
364
+ * @param sectionName The name of the section to trace.
365
+ * @param promiseOrFunction Promise or a function that provides a promise.
366
+ * @param args Optional arguments to pass to the trace.
367
+ * @returns The returned value of the traced call.
368
+ * @see https://wix.github.io/Detox/docs/next/api/detox-object-api/#detoxtracecall.
360
369
  */
361
- readonly traceCall: <T>(event: string, action: () => Promise<T>) => Promise<T>;
370
+ readonly traceCall: <T>(event: string, action: () => Promise<T>, args?: Record<string, unknown>) => Promise<T>;
362
371
  }
363
372
 
364
373
  interface Logger {
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.0.6-breaking.new-global-lifecycle.0",
4
+ "version": "20.0.7-prerelease.0",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -184,5 +184,5 @@
184
184
  }
185
185
  }
186
186
  },
187
- "gitHead": "29baf7cab1ff919fd57d11f5e41664e741777f76"
187
+ "gitHead": "4b75f39310b93707f01e2bb38a4fba4d385e8acd"
188
188
  }
@@ -1,5 +1,6 @@
1
- // @ts-nocheck
2
- const maybeNodeEnvironment = require('jest-environment-node'); // eslint-disable-line node/no-extraneous-require
1
+ const resolveFrom = require('resolve-from');
2
+ const maybeNodeEnvironment = require(resolveFrom(process.cwd(), 'jest-environment-node'));
3
+ // @ts-ignore
3
4
  const NodeEnvironment = maybeNodeEnvironment.default || maybeNodeEnvironment;
4
5
 
5
6
  const detox = require('../../../internals');
@@ -195,7 +195,6 @@ class DetoxWorker {
195
195
  onTestStart = async (testSummary) => {
196
196
  if (this._isCleaningUp) return;
197
197
  this._validateTestSummary('beforeEach', testSummary);
198
- this._logTestRunCheckpoint('DETOX_BEFORE_EACH', testSummary);
199
198
 
200
199
  if (this._isCleaningUp) return;
201
200
  await this._dumpUnhandledErrorsIfAny({
@@ -215,7 +214,6 @@ class DetoxWorker {
215
214
  onTestDone = async (testSummary) => {
216
215
  if (this._isCleaningUp) return;
217
216
  this._validateTestSummary('afterEach', testSummary);
218
- this._logTestRunCheckpoint('DETOX_AFTER_EACH', testSummary);
219
217
 
220
218
  if (this._isCleaningUp) return;
221
219
  await this._artifactsManager.onTestDone(testSummary);
@@ -251,10 +249,6 @@ class DetoxWorker {
251
249
  }
252
250
  }
253
251
 
254
- _logTestRunCheckpoint(event, { status, fullName }) {
255
- this.log.trace({ event, status }, `${status} test: ${JSON.stringify(fullName)}`);
256
- }
257
-
258
252
  _validateTestSummary(methodName, testSummary) {
259
253
  if (!_.isPlainObject(testSummary)) {
260
254
  throw this._runtimeErrorComposer.invalidTestSummary(methodName, testSummary);
@@ -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
- return await new ActionInteraction(this._invocationManager, this, new actions.TapAction(value)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.TapAtPointAction(value)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.LongPressAction()).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.MultiClickAction(times)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.PressKeyAction(67)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.TypeTextAction('\n')).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.TypeTextAction(value)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.ReplaceTextAction(value)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.ClearTextAction()).execute();
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
- // override the user's element selection with an extended matcher that looks for UIScrollView children
72
- // this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
73
- return await new ActionInteraction(this._invocationManager, this, new actions.ScrollAmountAction(direction, amount, startPositionX, startPositionY)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.ScrollEdgeAction(edge)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.ScrollToIndex(index)).execute();
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
- return await new ActionInteraction(this._invocationManager, this, action).execute();
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 resultBase64 = await new ActionInteraction(this._invocationManager, this, new actions.TakeElementScreenshot()).execute();
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 result = await new ActionInteraction(this._invocationManager, this, new actions.GetAttributes()).execute();
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
- return await new ActionInteraction(this._invocationManager, this, new actions.AdjustSliderToPosition(newPosition)).execute();
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