detox 20.44.0-smoke.0 → 20.44.0-smoke.1

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.
Files changed (42) hide show
  1. package/Detox-android/com/wix/detox/{20.44.0-smoke.0/detox-20.44.0-smoke.0-sources.jar → 20.44.0-smoke.1/detox-20.44.0-smoke.1-sources.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1-sources.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1-sources.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1-sources.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1-sources.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.44.0-smoke.0/detox-20.44.0-smoke.0.aar → 20.44.0-smoke.1/detox-20.44.0-smoke.1.aar} +0 -0
  7. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.aar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.aar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.aar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.aar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.44.0-smoke.0/detox-20.44.0-smoke.0.pom → 20.44.0-smoke.1/detox-20.44.0-smoke.1.pom} +1 -1
  12. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.44.0-smoke.1/detox-20.44.0-smoke.1.pom.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  17. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  18. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  19. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  20. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  21. package/Detox-ios-framework.tbz +0 -0
  22. package/Detox-ios-src.tbz +0 -0
  23. package/Detox-ios-xcuitest.tbz +0 -0
  24. package/android/detox/src/full/java/com/wix/detox/inquiry/DetoxAnimationTracker.kt +70 -0
  25. package/android/detox/src/full/java/com/wix/detox/inquiry/DetoxFabricAnimationHook.kt +16 -125
  26. package/android/detox/src/full/java/com/wix/detox/inquiry/DetoxFabricIntegration.kt +99 -0
  27. package/android/detox/src/full/java/com/wix/detox/inquiry/DetoxFabricUIManagerWrapper.kt +37 -0
  28. package/android/detox/src/full/java/com/wix/detox/inquiry/ViewLifecycleRegistry.kt +1 -1
  29. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/fabric/FabricUIManagerIdlingResources.kt +4 -41
  30. package/package.json +2 -2
  31. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0-sources.jar.md5 +0 -1
  32. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0-sources.jar.sha1 +0 -1
  33. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0-sources.jar.sha256 +0 -1
  34. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0-sources.jar.sha512 +0 -1
  35. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.aar.md5 +0 -1
  36. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.aar.sha1 +0 -1
  37. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.aar.sha256 +0 -1
  38. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.aar.sha512 +0 -1
  39. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.pom.md5 +0 -1
  40. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.pom.sha1 +0 -1
  41. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.pom.sha256 +0 -1
  42. package/Detox-android/com/wix/detox/20.44.0-smoke.0/detox-20.44.0-smoke.0.pom.sha512 +0 -1
@@ -0,0 +1 @@
1
+ bdf9863f8c4afcf4541218e9b3bed4a3
@@ -0,0 +1 @@
1
+ 760a64eb6cdd8807b45b398d53de460c48df99a5
@@ -0,0 +1 @@
1
+ 8e42be451e2bd115b75216749965d28317bddb694a2e880adab3abb709ba1d08
@@ -0,0 +1 @@
1
+ 5cb65dc5c27e0964f4fd77c1cb638cd071b43db67100cae210c0205ea2e87b3268bfb8543c06a8baf10aa748d4eb49302db99390464b639bc4e9c8a2eeabd278
@@ -0,0 +1 @@
1
+ 1a39cefde2e8dde2ca54d70b0c5e5b0d
@@ -0,0 +1 @@
1
+ 39e35796a4308c0a15457b1613b96b090f721432
@@ -0,0 +1 @@
1
+ 76090af6a690fc00138ac3c3a307fe3cc49dfde32789bbc2d8066fa53e67805b
@@ -0,0 +1 @@
1
+ 12b0c9b12325ad848ba52cdbbea6a37d837b341d5f98d6c4c34c45f357cebbfc767466df76479ebde2f1546cdc2211cfe02a3bf383371ac24b1e3de43df568b5
@@ -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.44.0-smoke.0</version>
6
+ <version>20.44.0-smoke.1</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
+ aae3ffc3cd9babca3385c2de23ca2be0
@@ -0,0 +1 @@
1
+ b6de9c93a0a4fdc91a1e1335dc19a90d6fe592bd
@@ -0,0 +1 @@
1
+ 305c59339a78c67c7fa2b6ab908c7f455d6faeb039827af94e5426238d4f464e
@@ -0,0 +1 @@
1
+ 3e6d2c931c52d22342ae2c2cbc0cbd4c38c74e3240a48d95cfe69a1561eb76337dbfdd4dd2753414c19f02b42e16c1fa8f2965efe9fffafce9122cd798eecf22
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.44.0-smoke.0</latest>
7
- <release>20.44.0-smoke.0</release>
6
+ <latest>20.44.0-smoke.1</latest>
7
+ <release>20.44.0-smoke.1</release>
8
8
  <versions>
9
- <version>20.44.0-smoke.0</version>
9
+ <version>20.44.0-smoke.1</version>
10
10
  </versions>
11
- <lastUpdated>20251009064730</lastUpdated>
11
+ <lastUpdated>20251009104839</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 6fd136d7a8c19e7c19f3c34acafd3f68
1
+ 4baad9ede6680e5d2b46f1246a48c8f9
@@ -1 +1 @@
1
- 3925c59668fe2612ba6a696b291a0ca11553fbbe
1
+ b07f36a5c0ae07b6a7961b318ca15b8acc44d602
@@ -1 +1 @@
1
- 0c09abf9ea6b645efa11a1b3a06900511d2bb8c7e941c5e4ee15ea7babd94278
1
+ a95b41be51ad53267864aae6fc777db00648abe236c7bdbd46c645543e9c052f
@@ -1 +1 @@
1
- eb554b0043657d82361a9955b128c1fe514454844892b7daffef616c59ae39c3de434033fc6dcf1f7521422ef7201739b7b01af7ba6a8f73b4beca11073a7630
1
+ 03f466d7a8a4a9f3a5b82b78cc9fcfc0020dd9bb7e3c7d821096887eb241118db40ce09f2f4912a6de05bd2b4c4d75ad48133665e37f68c37bae4a3b227d08ca
Binary file
package/Detox-ios-src.tbz CHANGED
Binary file
Binary file
@@ -0,0 +1,70 @@
1
+ package com.wix.detox.inquiry
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.ReactContext
5
+ import com.facebook.react.fabric.FabricUIManager
6
+ import com.facebook.react.uimanager.UIManagerHelper
7
+ // import com.facebook.react.uimanager.UIManagerType
8
+
9
+ /**
10
+ * Main entry point for Detox animation tracking in Fabric.
11
+ * This provides a simple API to initialize and use the animation tracking system.
12
+ */
13
+ object DetoxAnimationTracker {
14
+ private const val LOG_TAG = "DetoxAnimationTracker"
15
+ private var isInitialized = false
16
+
17
+ /**
18
+ * Initialize the animation tracking system.
19
+ * This should be called once when Detox starts up.
20
+ */
21
+ fun initialize(reactContext: ReactContext) {
22
+ if (isInitialized) {
23
+ Log.d(LOG_TAG, "DetoxAnimationTracker already initialized")
24
+ return
25
+ }
26
+
27
+ try {
28
+ // Initialize the Fabric integration
29
+ DetoxFabricIntegration.initialize(reactContext)
30
+ isInitialized = true
31
+ Log.i(LOG_TAG, "DetoxAnimationTracker initialized successfully")
32
+
33
+ } catch (e: Exception) {
34
+ Log.e(LOG_TAG, "Failed to initialize DetoxAnimationTracker", e)
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Get the current animation statistics
40
+ */
41
+ fun getAnimationStats(): Map<String, Any> {
42
+ return ViewLifecycleRegistry.getStats()
43
+ }
44
+
45
+ /**
46
+ * Get all recently animated views
47
+ */
48
+ fun getRecentlyAnimatedViews(): List<android.view.View> {
49
+ return ViewLifecycleRegistry.getRecentlyAnimatedViews()
50
+ }
51
+
52
+ /**
53
+ * Check if a specific view was recently animated
54
+ */
55
+ fun wasRecentlyAnimated(view: android.view.View): Boolean {
56
+ return ViewLifecycleRegistry.wasRecentlyAnimated(view)
57
+ }
58
+
59
+ /**
60
+ * Clear all animation tracking data
61
+ */
62
+ fun clear() {
63
+ ViewLifecycleRegistry.clear()
64
+ }
65
+
66
+ /**
67
+ * Check if the tracker is initialized
68
+ */
69
+ fun isInitialized(): Boolean = isInitialized
70
+ }
@@ -3,51 +3,37 @@ package com.wix.detox.inquiry
3
3
  import android.util.Log
4
4
  import android.view.View
5
5
  import com.facebook.react.bridge.ReadableMap
6
- import com.facebook.react.fabric.mounting.SurfaceMountingManager
6
+ import com.facebook.react.fabric.FabricUIManager
7
7
  import com.wix.detox.inquiry.ViewLifecycleRegistry.markAnimated
8
8
  import com.wix.detox.inquiry.ViewLifecycleRegistry.markMounted
9
9
  import com.wix.detox.inquiry.ViewLifecycleRegistry.markUpdated
10
- import com.wix.detox.inquiry.ViewLifecycleRegistry.markCustomEvent
11
10
 
12
11
  /**
13
- * Hook into React Native's Fabric new architecture to track view lifecycle events.
14
- * This hooks into the exact points where views are mounted, updated, and animated.
12
+ * Hook into React Native's Fabric new architecture to track animated views.
13
+ * This provides precise tracking by intercepting the exact points where animated
14
+ * properties are applied to views in Fabric.
15
15
  */
16
16
  object DetoxFabricAnimationHook {
17
17
  private const val LOG_TAG = "DetoxFabricHook"
18
18
 
19
19
  /**
20
- * Hook into IntBufferBatchMountItem.execute() to track animated view updates.
21
- * This is called when animated props are applied to views in Fabric.
20
+ * Hook into FabricUIManager.synchronouslyUpdateViewOnUIThread to track animated updates.
21
+ * This marks views as animated whenever there's any animation activity, giving lots of false positives.
22
22
  */
23
- fun hookIntBufferBatchMountItem(
24
- viewTag: Int,
23
+ fun hookSynchronouslyUpdateViewOnUIThread(
24
+ reactTag: Int,
25
25
  props: ReadableMap?,
26
- surfaceMountingManager: SurfaceMountingManager
26
+ fabricUIManager: FabricUIManager
27
27
  ) {
28
28
  try {
29
29
  // Get the actual Android View
30
- val androidView = getViewByTag(surfaceMountingManager, viewTag)
30
+ val androidView = fabricUIManager.resolveView(reactTag)
31
31
  if (androidView == null) {
32
- Log.d(LOG_TAG, "View not found for tag: $viewTag")
32
+ Log.d(LOG_TAG, "View not found for tag: $reactTag")
33
33
  return
34
34
  }
35
35
 
36
- // Check if this is an animated update
37
- if (isAnimatedPropsUpdate(props)) {
38
- Log.d(LOG_TAG, "Animated props update for view tag: $viewTag")
39
- markAnimated(androidView)
40
-
41
- // Log problematic animations
42
- if (isProblematicAnimation(props)) {
43
- Log.w(LOG_TAG, "Problematic animation detected for view tag: $viewTag")
44
- markCustomEvent(androidView, "problematic_animation")
45
- }
46
- } else {
47
- // Regular props update
48
- markUpdated(androidView)
49
- }
50
-
36
+ markAnimated(androidView)
51
37
  } catch (e: Exception) {
52
38
  Log.w(LOG_TAG, "Failed to hook animated view update", e)
53
39
  }
@@ -57,13 +43,13 @@ object DetoxFabricAnimationHook {
57
43
  * Hook into view mount operations to track when views are created.
58
44
  */
59
45
  fun hookViewMount(
60
- viewTag: Int,
61
- surfaceMountingManager: SurfaceMountingManager
46
+ reactTag: Int,
47
+ fabricUIManager: FabricUIManager
62
48
  ) {
63
49
  try {
64
- val androidView = getViewByTag(surfaceMountingManager, viewTag)
50
+ val androidView = fabricUIManager.resolveView(reactTag)
65
51
  if (androidView != null) {
66
- Log.d(LOG_TAG, "View mounted with tag: $viewTag")
52
+ Log.d(LOG_TAG, "View mounted with tag: $reactTag")
67
53
  markMounted(androidView)
68
54
  }
69
55
  } catch (e: Exception) {
@@ -71,86 +57,6 @@ object DetoxFabricAnimationHook {
71
57
  }
72
58
  }
73
59
 
74
- /**
75
- * Get Android View by React Native view tag using reflection.
76
- * This works around the fact that SurfaceMountingManager doesn't expose a direct getView method.
77
- */
78
- private fun getViewByTag(
79
- surfaceMountingManager: SurfaceMountingManager,
80
- viewTag: Int
81
- ): View? {
82
- return try {
83
- // Use reflection to access the internal view registry
84
- val viewRegistryField = surfaceMountingManager.javaClass.getDeclaredField("mViewRegistry")
85
- viewRegistryField.isAccessible = true
86
- val viewRegistry = viewRegistryField.get(surfaceMountingManager)
87
-
88
- // Get the view from the registry
89
- val getViewMethod = viewRegistry.javaClass.getMethod("getView", Int::class.java)
90
- getViewMethod.invoke(viewRegistry, viewTag) as? View
91
- } catch (e: Exception) {
92
- Log.w(LOG_TAG, "Failed to get view by tag: $viewTag", e)
93
- null
94
- }
95
- }
96
-
97
- /**
98
- * Check if this is an animated props update by looking for animated properties.
99
- */
100
- private fun isAnimatedPropsUpdate(props: ReadableMap?): Boolean {
101
- if (props == null) return false
102
-
103
- val animatedKeys = setOf(
104
- "transform", "opacity", "scaleX", "scaleY", "scale",
105
- "translateX", "translateY", "rotateX", "rotateY", "rotateZ",
106
- "backgroundColor", "borderRadius", "borderWidth"
107
- )
108
-
109
- val iterator = props.keySetIterator()
110
- while (iterator.hasNextKey()) {
111
- val key = iterator.nextKey()
112
- if (animatedKeys.any { key.contains(it, ignoreCase = true) }) {
113
- return true
114
- }
115
- }
116
-
117
- return false
118
- }
119
-
120
- /**
121
- * Check if this animation might be problematic (infinite loops, conflicting animations, etc.).
122
- */
123
- private fun isProblematicAnimation(props: ReadableMap?): Boolean {
124
- if (props == null) return false
125
-
126
- // Check for potential infinite loop patterns
127
- val transformKeys = mutableSetOf<String>()
128
- val iterator = props.keySetIterator()
129
-
130
- while (iterator.hasNextKey()) {
131
- val key = iterator.nextKey()
132
- if (key.contains("transform", ignoreCase = true)) {
133
- transformKeys.add(key)
134
- }
135
- }
136
-
137
- // Multiple transform properties might indicate conflicting animations
138
- if (transformKeys.size > 3) {
139
- Log.w(LOG_TAG, "Multiple transform properties detected: $transformKeys")
140
- return true
141
- }
142
-
143
- // Check for opacity animations that might cause issues
144
- if (props.hasKey("opacity")) {
145
- val opacity = props.getDouble("opacity")
146
- if (opacity < 0.0 || opacity > 1.0) {
147
- Log.w(LOG_TAG, "Invalid opacity value: $opacity")
148
- return true
149
- }
150
- }
151
-
152
- return false
153
- }
154
60
 
155
61
  /**
156
62
  * Get view coordinates for highlighting
@@ -167,21 +73,6 @@ object DetoxFabricAnimationHook {
167
73
  return coords
168
74
  }
169
75
 
170
- /**
171
- * Get view coordinates relative to root view
172
- */
173
- fun getViewCoordinatesRelativeToRoot(view: View, rootView: View): IntArray {
174
- val viewCoords = getViewCoordinates(view)
175
- val rootCoords = getViewCoordinates(rootView)
176
-
177
- return intArrayOf(
178
- viewCoords[0] - rootCoords[0], // Relative X
179
- viewCoords[1] - rootCoords[1], // Relative Y
180
- viewCoords[2], // Width
181
- viewCoords[3] // Height
182
- )
183
- }
184
-
185
76
  /**
186
77
  * Log current registry statistics
187
78
  */
@@ -0,0 +1,99 @@
1
+ package com.wix.detox.inquiry
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.ReactContext
5
+ import com.facebook.react.fabric.FabricUIManager
6
+ import com.facebook.react.uimanager.UIManagerHelper
7
+ // import com.facebook.react.uimanager.UIManagerType
8
+
9
+ /**
10
+ * Integration point for Detox with React Native's Fabric architecture.
11
+ * This provides hooks into Fabric's animation system to track animated views.
12
+ */
13
+ object DetoxFabricIntegration {
14
+ private const val LOG_TAG = "DetoxFabricIntegration"
15
+ private var isInitialized = false
16
+
17
+ /**
18
+ * Initialize the Fabric animation hooks.
19
+ * This should be called once when Detox starts up.
20
+ */
21
+ fun initialize(reactContext: ReactContext) {
22
+ if (isInitialized) {
23
+ Log.d(LOG_TAG, "DetoxFabricIntegration already initialized")
24
+ return
25
+ }
26
+
27
+ try {
28
+ // Get the FabricUIManager
29
+ val fabricUIManager = UIManagerHelper.getUIManager(reactContext, 1) as? FabricUIManager
30
+ if (fabricUIManager == null) {
31
+ Log.w(LOG_TAG, "FabricUIManager not available - Fabric animation tracking disabled")
32
+ return
33
+ }
34
+
35
+ // Hook into the FabricUIManager
36
+ hookFabricUIManager(fabricUIManager)
37
+ isInitialized = true
38
+ Log.i(LOG_TAG, "DetoxFabricIntegration initialized successfully")
39
+
40
+ } catch (e: Exception) {
41
+ Log.e(LOG_TAG, "Failed to initialize DetoxFabricIntegration", e)
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Hook into FabricUIManager to track animated updates.
47
+ * This uses reflection to intercept synchronouslyUpdateViewOnUIThread calls.
48
+ */
49
+ private fun hookFabricUIManager(fabricUIManager: FabricUIManager) {
50
+ try {
51
+ // Create a wrapper that intercepts calls to synchronouslyUpdateViewOnUIThread
52
+ val originalMethod = FabricUIManager::class.java.getDeclaredMethod(
53
+ "synchronouslyUpdateViewOnUIThread",
54
+ Int::class.java,
55
+ com.facebook.react.bridge.ReadableMap::class.java
56
+ )
57
+
58
+ // Note: In a real implementation, you would use bytecode manipulation
59
+ // or AOP to intercept this method. For now, we'll provide a manual hook
60
+ // that can be called from the application code.
61
+
62
+ Log.d(LOG_TAG, "FabricUIManager hook prepared (manual integration required)")
63
+
64
+ } catch (e: Exception) {
65
+ Log.w(LOG_TAG, "Failed to hook FabricUIManager", e)
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Manual hook for synchronouslyUpdateViewOnUIThread.
71
+ * This should be called from the application's FabricUIManager wrapper.
72
+ */
73
+ fun onSynchronouslyUpdateViewOnUIThread(
74
+ reactTag: Int,
75
+ props: com.facebook.react.bridge.ReadableMap?,
76
+ fabricUIManager: FabricUIManager
77
+ ) {
78
+ DetoxFabricAnimationHook.hookSynchronouslyUpdateViewOnUIThread(reactTag, props, fabricUIManager)
79
+ }
80
+
81
+ /**
82
+ * Manual hook for view mount operations.
83
+ */
84
+ fun onViewMount(reactTag: Int, fabricUIManager: FabricUIManager) {
85
+ DetoxFabricAnimationHook.hookViewMount(reactTag, fabricUIManager)
86
+ }
87
+
88
+ /**
89
+ * Check if the integration is initialized
90
+ */
91
+ fun isInitialized(): Boolean = isInitialized
92
+
93
+ /**
94
+ * Get current animation statistics
95
+ */
96
+ fun getAnimationStats(): Map<String, Any> {
97
+ return ViewLifecycleRegistry.getStats()
98
+ }
99
+ }
@@ -0,0 +1,37 @@
1
+ package com.wix.detox.inquiry
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.facebook.react.fabric.FabricUIManager
6
+
7
+ /**
8
+ * Wrapper for FabricUIManager that intercepts animation-related calls.
9
+ * This provides a clean way to hook into Fabric's animation system.
10
+ */
11
+ class DetoxFabricUIManagerWrapper(
12
+ private val originalUIManager: FabricUIManager
13
+ ) {
14
+ private val LOG_TAG = "DetoxFabricUIManagerWrapper"
15
+
16
+ fun synchronouslyUpdateViewOnUIThread(reactTag: Int, props: ReadableMap?) {
17
+ try {
18
+ // Call the original method first (only if props is not null)
19
+ if (props != null) {
20
+ originalUIManager.synchronouslyUpdateViewOnUIThread(reactTag, props)
21
+ }
22
+
23
+ // Then hook our animation tracking
24
+ DetoxFabricAnimationHook.hookSynchronouslyUpdateViewOnUIThread(reactTag, props, originalUIManager)
25
+
26
+ } catch (e: Exception) {
27
+ Log.w(LOG_TAG, "Failed to process animated view update", e)
28
+ // Still call the original method to avoid breaking the app (only if props is not null)
29
+ if (props != null) {
30
+ originalUIManager.synchronouslyUpdateViewOnUIThread(reactTag, props)
31
+ }
32
+ }
33
+ }
34
+
35
+ // Delegate all other methods to the original UIManager
36
+ fun resolveView(reactTag: Int) = originalUIManager.resolveView(reactTag)
37
+ }
@@ -66,7 +66,7 @@ object ViewLifecycleRegistry {
66
66
  */
67
67
  fun markAnimated(view: View) {
68
68
  val now = System.currentTimeMillis()
69
-
69
+
70
70
  viewLifecycleInfo.compute(view) { _, existing ->
71
71
  val info = existing ?: ViewLifecycleInfo(view)
72
72
  info.copy(
@@ -140,7 +140,7 @@ class FabricUIManagerIdlingResources(
140
140
  32 -> { // INSTRUCTION_UPDATE_PROPS
141
141
  val viewTag = intBuffer[i++]
142
142
  val props = objBuffer[j++] as? com.facebook.react.bridge.ReadableMap
143
-
143
+
144
144
  // Track animated view update
145
145
  trackAnimatedViewUpdate(viewTag, props)
146
146
  }
@@ -204,14 +204,7 @@ class FabricUIManagerIdlingResources(
204
204
  val view = getViewByTag(fabricUIManager as Any, viewTag)
205
205
 
206
206
  if (view != null) {
207
- // Check if this is an animated update
208
- val isAnimated = isAnimatedPropsUpdate(props)
209
-
210
- if (isAnimated) {
211
- ViewLifecycleRegistry.markAnimated(view)
212
- } else {
213
- ViewLifecycleRegistry.markUpdated(view)
214
- }
207
+ com.wix.detox.inquiry.DetoxFabricAnimationHook.hookSynchronouslyUpdateViewOnUIThread(viewTag, props, fabricUIManager as com.facebook.react.fabric.FabricUIManager)
215
208
  }
216
209
  } catch (e: Exception) {
217
210
  // Silently ignore errors to avoid breaking the idling resource
@@ -225,11 +218,11 @@ class FabricUIManagerIdlingResources(
225
218
  return try {
226
219
  // Get MountingManager from FabricUIManager
227
220
  val mountingManager = Reflect.on(fabricUIManager).field("mMountingManager").get<Any>()
228
-
221
+
229
222
  // Get SurfaceMountingManager for the view
230
223
  val getSurfaceManagerMethod = mountingManager.javaClass.getMethod("getSurfaceManagerForView", Int::class.java)
231
224
  val surfaceMountingManager = getSurfaceManagerMethod.invoke(mountingManager, viewTag)
232
-
225
+
233
226
  if (surfaceMountingManager != null) {
234
227
  // Get the actual Android View
235
228
  val getViewMethod = surfaceMountingManager.javaClass.getMethod("getView", Int::class.java)
@@ -242,35 +235,5 @@ class FabricUIManagerIdlingResources(
242
235
  }
243
236
  }
244
237
 
245
- /**
246
- * Check if this is an animated props update.
247
- */
248
- private fun isAnimatedPropsUpdate(props: com.facebook.react.bridge.ReadableMap?): Boolean {
249
- if (props == null) {
250
- Log.i("DetoxFabricDebug", "Props is null - not animated")
251
- return false
252
- }
253
-
254
- val animatedKeys = setOf(
255
- "transform", "opacity", "scaleX", "scaleY", "scale",
256
- "translateX", "translateY", "rotateX", "rotateY", "rotateZ",
257
- "backgroundColor", "borderRadius", "borderWidth"
258
- )
259
-
260
- Log.i("DetoxFabricDebug", "Checking props for animated keys...")
261
-
262
- val iterator = props.keySetIterator()
263
- while (iterator.hasNextKey()) {
264
- val key = iterator.nextKey()
265
- Log.i("DetoxFabricDebug", "Checking key: $key")
266
- if (animatedKeys.any { key.contains(it, ignoreCase = true) }) {
267
- Log.i("DetoxFabricDebug", "Found animated key: $key")
268
- return true
269
- }
270
- }
271
-
272
- Log.i("DetoxFabricDebug", "No animated keys found")
273
- return false
274
- }
275
238
 
276
239
  }
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.44.0-smoke.0",
4
+ "version": "20.44.0-smoke.1",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -120,5 +120,5 @@
120
120
  "browserslist": [
121
121
  "node 14"
122
122
  ],
123
- "gitHead": "3a5520e1a0fcb8f727cd58f43389be5482302224"
123
+ "gitHead": "5e0b38a97eccb64d73369b1a3ccbd9c31ecde284"
124
124
  }
@@ -1 +0,0 @@
1
- a3db6cd0603cac8288674ad9a3500d8f
@@ -1 +0,0 @@
1
- 1ad7d900ea972d2ee93f237abcc969e0ad522652
@@ -1 +0,0 @@
1
- b0290a59c47efb8a80702a11a2dfb69498ddcd0da14d63d30f558574105fbe17
@@ -1 +0,0 @@
1
- 81bcbcbc24ded6f8b469f8be58ad0195f72b39faadc1f3da271d646c93756dac15476d208b1424cde7f9966614a01e122452083b060094bde60ba64d080ff9c4
@@ -1 +0,0 @@
1
- 216f0dfc73c1b4f9ab0514607d5f5f2b
@@ -1 +0,0 @@
1
- 9d8dfd8b0ac4ebeaeb7f4af1d8ab1d650046662d
@@ -1 +0,0 @@
1
- 7c48b2a45b2deda2526d564ffc1472a9ec7dd5d123591113106b480281c5e9ce
@@ -1 +0,0 @@
1
- 4208bb610d9268ad130dba46fa3a08eb2dd39660b700b3218c3b784937b8248ff93c51443bce4cff4d339bf3cc8969f37159235d26b284b7accb00e1ca30722f
@@ -1 +0,0 @@
1
- a4be7bd3d45ebb560642a7c0761625fd
@@ -1 +0,0 @@
1
- 285ed616044919523ccdcc037a962672de13646e
@@ -1 +0,0 @@
1
- 0338db52bbfeb69095f0a1c31abb80acec835b1031e60a1047982260ab232ff8
@@ -1 +0,0 @@
1
- b2bf4d188dfbeca23574936656a9e09936762f5d53263529414696aa294770c324d556d309a1e9887b1e56734eb706072ab4cfc880af4bdbfe9e9d9b26618930