detox 20.27.7-smoke.0 → 20.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. package/Detox-android/com/wix/detox/{20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar → 20.30.0/detox-20.30.0-sources.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar +0 -0
  7. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.27.7-smoke.0/detox-20.27.7-smoke.0.pom → 20.30.0/detox-20.30.0.pom} +2 -2
  12. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.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/build.gradle +5 -5
  25. package/android/detox/proguard-rules-app.pro +3 -0
  26. package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +54 -3
  27. package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +11 -0
  28. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/IsDisplayingAtLeastDetoxMatcher.kt +2 -2
  29. package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java +4 -7
  30. package/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java +0 -5
  31. package/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java +33 -8
  32. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +6 -11
  33. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeInfo.kt +4 -11
  34. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxIdlingResource.kt +42 -0
  35. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/ReactNativeIdlingResources.kt +145 -0
  36. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/animations/AnimatedModuleIdlingResource.kt +61 -0
  37. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/bridge/BridgeIdlingResource.kt +72 -0
  38. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/DetoxIdlingResourceFactory.kt +32 -0
  39. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/IdlingResourcesName.kt +10 -0
  40. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/LooperName.kt +6 -0
  41. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/looper/MQThreadsReflector.kt +47 -0
  42. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/network/NetworkIdlingResource.kt +105 -0
  43. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{NetworkingModuleReflected.kt → network/NetworkingModuleReflected.kt} +1 -1
  44. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{AsyncStorageIdlingResource.kt → storage/AsyncStorageIdlingResource.kt} +33 -35
  45. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{SerialExecutorReflected.kt → storage/SerialExecutorReflected.kt} +1 -1
  46. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt +21 -19
  47. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIManagerModuleReflected.kt +19 -27
  48. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIModuleIdlingResource.kt +5 -17
  49. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceTest.kt +248 -0
  50. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResourcesTest.kt +5 -1
  51. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt +1 -0
  52. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceTest.kt +212 -0
  53. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  54. package/android/rninfo.gradle +31 -24
  55. package/android/settings.gradle +11 -6
  56. package/detox.d.ts +39 -0
  57. package/package.json +11 -8
  58. package/scripts/postinstall.js +2 -2
  59. package/scripts/updateGradle.js +41 -8
  60. package/src/DetoxWorker.js +11 -6
  61. package/src/android/espressoapi/EspressoDetox.js +83 -0
  62. package/src/copilot/DetoxCopilot.js +3 -15
  63. package/src/copilot/detoxCopilotFrameworkDriver.js +27 -15
  64. package/src/devices/runtime/RuntimeDevice.js +11 -0
  65. package/src/devices/runtime/drivers/DeviceDriverBase.js +8 -0
  66. package/src/devices/runtime/drivers/android/AndroidDriver.js +16 -0
  67. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +35 -0
  68. package/src/utils/assertArgument.js +9 -0
  69. package/src/utils/invocationTraceDescriptions.js +1 -0
  70. package/src/utils/mapDeviceLongPressArguments.js +56 -0
  71. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.md5 +0 -1
  72. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha1 +0 -1
  73. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha256 +0 -1
  74. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha512 +0 -1
  75. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar +0 -0
  76. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.md5 +0 -1
  77. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha1 +0 -1
  78. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha256 +0 -1
  79. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha512 +0 -1
  80. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.md5 +0 -1
  81. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha1 +0 -1
  82. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha256 +0 -1
  83. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha512 +0 -1
  84. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar +0 -0
  85. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.md5 +0 -1
  86. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha1 +0 -1
  87. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha256 +0 -1
  88. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha512 +0 -1
  89. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar +0 -0
  90. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.md5 +0 -1
  91. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha1 +0 -1
  92. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha256 +0 -1
  93. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha512 +0 -1
  94. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom +0 -100
  95. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.md5 +0 -1
  96. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha1 +0 -1
  97. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha256 +0 -1
  98. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha512 +0 -1
  99. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +0 -13
  100. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +0 -1
  101. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +0 -1
  102. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +0 -1
  103. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +0 -1
  104. package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxDriverAtoms.java +0 -642
  105. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +0 -229
  106. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java +0 -215
  107. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java +0 -94
  108. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java +0 -29
  109. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java +0 -134
  110. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt +0 -23
  111. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt +0 -16
  112. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +0 -71
  113. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt +0 -227
  114. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt +0 -47
  115. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt +0 -189
@@ -1,23 +0,0 @@
1
-
2
- package com.wix.detox.reactnative.idlingresources.timers
3
-
4
- import com.facebook.react.bridge.ReactContext
5
- import com.facebook.react.modules.core.TimingModule
6
-
7
- private const val BUSY_WINDOW_THRESHOLD = 1500L
8
-
9
- /**
10
- * Delegates the interrogation to the native module itself, added
11
- * [here](https://github.com/facebook/react-native/pull/27539) in the context
12
- * of RN v0.62 (followed by a previous refactor and rename of the class).
13
- */
14
- class DelegatedIdleInterrogationStrategy(private val timingModule: TimingModule): IdleInterrogationStrategy {
15
- override fun isIdleNow(): Boolean = !timingModule.hasActiveTimersInRange(BUSY_WINDOW_THRESHOLD)
16
-
17
- companion object {
18
- fun create(reactContext: ReactContext): DelegatedIdleInterrogationStrategy {
19
- val timingModule = reactContext.getNativeModule(TimingModule::class.java)!!
20
- return DelegatedIdleInterrogationStrategy(timingModule)
21
- }
22
- }
23
- }
@@ -1,16 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources.timers
2
-
3
- import com.facebook.react.bridge.ReactContext
4
- import com.wix.detox.common.UIThread
5
- import java.util.concurrent.Callable
6
-
7
- interface IdleInterrogationStrategy {
8
- fun isIdleNow(): Boolean
9
- }
10
-
11
- fun getInterrogationStrategy(reactContext: ReactContext): IdleInterrogationStrategy? =
12
- // Getting a native-module (inside) also initializes it if needed. That has to run on a
13
- // looper thread, and the easiest to make sure that happens is to use the main thread.
14
- UIThread.runSync(Callable {
15
- return@Callable DelegatedIdleInterrogationStrategy.create(reactContext)
16
- })
@@ -1,71 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources.uimodule
2
-
3
- import android.util.Log
4
- import android.view.View
5
- import com.facebook.react.uimanager.IllegalViewOperationException
6
- import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
7
- import com.wix.detox.reactnative.ReactNativeInfo
8
- import java.lang.ref.WeakReference
9
-
10
- private const val NUM_TIMES_BEFORE_NOTIFY_IDLE = 10
11
- private const val SET_NATIVE_VALUE = "setNativeValue"
12
- private const val CLASS_REACT_SWITCH = "com.facebook.react.views.switchview.ReactSwitch"
13
-
14
- class RN66Workaround {
15
- private var timesStuckQueueDetected = 0
16
- private var stuckOperation: WeakReference<Any?>? = null
17
-
18
- // This is a workaround for https://github.com/facebook/react-native/issues/32594
19
- // uses duck typing heuristics to determine that this is probably the stuck Switch operation and if so, ignores it
20
- fun isScarceUISwitchCommandStuckInQueue(uiManagerModuleReflected: UIManagerModuleReflected): Boolean {
21
- var isStuckSwitchOperation = false
22
-
23
- if (isRelevantRNVersion() && uiManagerModuleReflected.getUIOpsCount() >= 1) {
24
- val nextUIOperation = uiManagerModuleReflected.getNextUIOpReflected()
25
- val view = getUIOpView(uiManagerModuleReflected, nextUIOperation)
26
- val isReactSwitch = isReactSwitch(view)
27
- val hasOneRetryIncremented = nextUIOperation?.numRetries == 1
28
- val isSetNativeValueCommand = (nextUIOperation?.viewCommand ?: "") == SET_NATIVE_VALUE
29
-
30
- if (isReactSwitch && hasOneRetryIncremented && isSetNativeValueCommand) {
31
- if (stuckOperation?.get() == nextUIOperation?.instance) {
32
- timesStuckQueueDetected++
33
- } else {
34
- stuckOperation = WeakReference(nextUIOperation?.instance)
35
- timesStuckQueueDetected = 0
36
- }
37
- }
38
-
39
- if (timesStuckQueueDetected >= NUM_TIMES_BEFORE_NOTIFY_IDLE) {
40
- isStuckSwitchOperation = true
41
- }
42
- } else {
43
- timesStuckQueueDetected = 0
44
- }
45
- return isStuckSwitchOperation
46
- }
47
-
48
- private fun isRelevantRNVersion(): Boolean {
49
- val rnVersion = ReactNativeInfo.rnVersion()
50
- return rnVersion.minor == 66 || (rnVersion.minor == 67 && rnVersion.patch < 4)
51
- }
52
-
53
- private fun getUIOpView(uiManagerModuleReflected: UIManagerModuleReflected, uiOperation: DispatchCommandOperationReflected?): View? {
54
- val nativeViewHierarchyManager = uiManagerModuleReflected.nativeViewHierarchyManager() ?: return null
55
- val tag = uiOperation?.tag ?: return null
56
- return try {
57
- nativeViewHierarchyManager.getViewClass(tag)
58
- } catch(e: IllegalViewOperationException) {
59
- Log.e(LOG_TAG, "failed to get view from tag ", e.cause)
60
- null
61
- }
62
- }
63
-
64
- private fun isReactSwitch(view: View?) = try {
65
- val ReactSwitchClass: Class<*> = Class.forName(CLASS_REACT_SWITCH)
66
- if (view != null) ReactSwitchClass.isAssignableFrom(view.javaClass) else false
67
- } catch (e: ClassNotFoundException) {
68
- Log.e(LOG_TAG, "failed to get $CLASS_REACT_SWITCH class ", e.cause)
69
- false
70
- }
71
- }
@@ -1,227 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources
2
-
3
- import androidx.test.espresso.IdlingResource
4
- import com.facebook.react.bridge.NativeModule
5
- import com.wix.detox.UTHelpers.yieldToOtherThreads
6
- import org.assertj.core.api.Assertions.assertThat
7
- import org.mockito.kotlin.*
8
- import org.spekframework.spek2.Spek
9
- import org.spekframework.spek2.style.specification.describe
10
- import java.util.concurrent.Executor
11
- import java.util.concurrent.Executors
12
-
13
- private class AsyncStorageModuleStub: NativeModule {
14
- val executor: Executor = mock(name = "native-module's executor")
15
- override fun getName() = "stub"
16
- override fun initialize() {}
17
- override fun canOverrideExistingModule() = false
18
- override fun onCatalystInstanceDestroy() {}
19
- override fun invalidate() {}
20
- }
21
-
22
- class AsyncStorageIdlingResourceSpec: Spek({
23
- describe("React Native Async-Storage idling-resource") {
24
- lateinit var sexecutor: Executor
25
- lateinit var sexecutorReflected: SerialExecutorReflected
26
- lateinit var sexecutorReflectedGenFn: (executor: Executor) -> SerialExecutorReflected
27
- lateinit var module: AsyncStorageModuleStub
28
- lateinit var uut: AsyncStorageIdlingResource
29
-
30
- beforeEachTest {
31
- sexecutor = mock()
32
- module = AsyncStorageModuleStub()
33
- sexecutorReflected = mock() {
34
- on { executor() }.thenReturn(sexecutor)
35
- }
36
- sexecutorReflectedGenFn = mock() {
37
- on { invoke(eq(module.executor)) }.thenReturn(sexecutorReflected)
38
- }
39
-
40
-
41
- uut = AsyncStorageIdlingResource(module, sexecutorReflectedGenFn)
42
- }
43
-
44
- fun givenNoActiveTasks() = whenever(sexecutorReflected.hasActiveTask()).thenReturn(false)
45
- fun givenAnActiveTask() = whenever(sexecutorReflected.hasActiveTask()).thenReturn(true)
46
- fun givenNoPendingTasks() = whenever(sexecutorReflected.hasPendingTasks()).thenReturn(false)
47
- fun givenPendingTasks() = whenever(sexecutorReflected.hasPendingTasks()).thenReturn(true)
48
- fun givenIdleSExecutor() {
49
- givenNoActiveTasks()
50
- givenNoPendingTasks()
51
- }
52
- fun givenBusySExecutor() {
53
- givenAnActiveTask()
54
- givenNoPendingTasks()
55
- }
56
- fun verifyNoTasksEnqueued() = verify(sexecutorReflected, never()).executeTask(any())
57
- fun verifyTaskEnqueuedOnce() = verify(sexecutorReflected, times(1)).executeTask(any())
58
- fun verifyTaskEnqueuedTwice() = verify(sexecutorReflected, times(2)).executeTask(any())
59
-
60
- it("should have a name") {
61
- assertThat(uut.name).isEqualTo("com.wix.detox.reactnative.idlingresources.AsyncStorageIdlingResource")
62
- }
63
-
64
- it("should have a debug-name") {
65
- assertThat(uut.getDebugName()).isEqualTo("io")
66
- }
67
-
68
- describe("idle-checking") {
69
- it("should be idle") {
70
- givenIdleSExecutor()
71
- assertThat(uut.isIdleNow).isTrue()
72
- }
73
-
74
- it("should be busy if executor is executing") {
75
- givenAnActiveTask()
76
- givenNoPendingTasks()
77
- assertThat(uut.isIdleNow).isFalse()
78
- }
79
-
80
- it("should be busy if executor has pending tasks") {
81
- givenNoActiveTasks()
82
- givenPendingTasks()
83
- assertThat(uut.isIdleNow).isFalse()
84
- }
85
-
86
- it("should be synchronized over actual executor") {
87
- val localExecutor = Executors.newSingleThreadExecutor()
88
- var isIdle: Boolean? = null
89
- synchronized(sexecutor) {
90
- localExecutor.submit {
91
- isIdle = uut.isIdleNow
92
- }
93
- yieldToOtherThreads(localExecutor)
94
- assertThat(isIdle).isNull()
95
- }
96
- yieldToOtherThreads(localExecutor)
97
- }
98
-
99
- it("should enqueue an idle-check task if resource is busy") {
100
- givenBusySExecutor()
101
- uut.isIdleNow
102
- verifyTaskEnqueuedOnce()
103
- }
104
-
105
- it("should not enqueue an idle-check task if resource if idle") {
106
- givenIdleSExecutor()
107
- uut.isIdleNow
108
- verifyNoTasksEnqueued()
109
- }
110
-
111
- it("should not enqueue more than one idle-check task") {
112
- givenBusySExecutor()
113
-
114
- repeat(2) {
115
- uut.isIdleNow
116
- }
117
- verifyTaskEnqueuedOnce()
118
- }
119
- }
120
-
121
- describe("callback registration") {
122
- lateinit var callback: IdlingResource.ResourceCallback
123
-
124
- beforeEachTest {
125
- callback = mock()
126
- }
127
-
128
- fun verifyTransitionToIdleCalled() = verify(callback).onTransitionToIdle()
129
- fun verifyTransitionToIdleNotCalled() = verify(callback, never()).onTransitionToIdle()
130
-
131
- it("should enqueue an idle-check task") {
132
- uut.registerIdleTransitionCallback(callback)
133
- verifyTaskEnqueuedOnce()
134
- }
135
-
136
- it("should be synchronized over actual executor") {
137
- val localExecutor = Executors.newSingleThreadExecutor()
138
-
139
- synchronized(sexecutor) {
140
- localExecutor.submit {
141
- uut.registerIdleTransitionCallback(callback)
142
- }
143
- yieldToOtherThreads(localExecutor)
144
- verifyNoTasksEnqueued()
145
- }
146
- yieldToOtherThreads(localExecutor)
147
- }
148
-
149
- describe("the idle-check task") {
150
- fun executeIdleCheckTask() {
151
- argumentCaptor<Runnable>().also {
152
- verify(sexecutorReflected).executeTask(it.capture())
153
- }.firstValue.run()
154
- }
155
-
156
- it("should transition to idle") {
157
- givenIdleSExecutor()
158
-
159
- uut.registerIdleTransitionCallback(callback)
160
- executeIdleCheckTask()
161
-
162
- verifyTransitionToIdleCalled()
163
- }
164
-
165
- it("should not transition to idle if busy") {
166
- givenAnActiveTask()
167
- givenPendingTasks()
168
-
169
- uut.registerIdleTransitionCallback(callback)
170
- executeIdleCheckTask()
171
-
172
- verifyTransitionToIdleNotCalled()
173
- }
174
-
175
- it("should not inspect sexecutor for activity, because it runs on the executor itself") {
176
- givenAnActiveTask()
177
- givenPendingTasks()
178
-
179
- uut.registerIdleTransitionCallback(callback)
180
- executeIdleCheckTask()
181
-
182
- verify(sexecutorReflected, never()).hasActiveTask()
183
- }
184
-
185
- it("should reenqueue if still busy") {
186
- givenAnActiveTask()
187
- givenPendingTasks()
188
-
189
- uut.registerIdleTransitionCallback(callback)
190
- executeIdleCheckTask()
191
-
192
- verifyTaskEnqueuedTwice()
193
- }
194
-
195
- it("should be synchronized") {
196
- val localExecutor = Executors.newSingleThreadExecutor()
197
-
198
- givenIdleSExecutor()
199
- uut.registerIdleTransitionCallback(callback)
200
-
201
- synchronized(sexecutor) {
202
- localExecutor.submit {
203
- executeIdleCheckTask()
204
- }
205
- yieldToOtherThreads(localExecutor)
206
- verifyTransitionToIdleNotCalled()
207
- }
208
- yieldToOtherThreads(localExecutor)
209
- }
210
-
211
- describe("vs. immediate idle-check") {
212
- it("should allow for an enqueuing of more tasks after idle-transition") {
213
- uut.registerIdleTransitionCallback(callback)
214
-
215
- givenIdleSExecutor()
216
- executeIdleCheckTask()
217
-
218
- givenBusySExecutor()
219
- uut.isIdleNow
220
-
221
- verifyTaskEnqueuedTwice()
222
- }
223
- }
224
- }
225
- }
226
- }
227
- })
@@ -1,47 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources.timers
2
-
3
- import com.facebook.react.bridge.NativeModule
4
- import org.assertj.core.api.Assertions.assertThat
5
- import org.mockito.kotlin.*
6
- import org.spekframework.spek2.Spek
7
- import org.spekframework.spek2.style.specification.describe
8
- import com.facebook.react.modules.core.TimingModule
9
-
10
- private const val BUSY_INTERVAL_MS = 1500L
11
-
12
- object DelegatedIdleInterrogationStrategySpec : Spek({
13
- describe("Timers idle-interrogation strategy") {
14
-
15
- lateinit var timingModule: TimingModule
16
-
17
- beforeEachTest {
18
- timingModule = mock()
19
- }
20
-
21
- fun givenActiveTimersInQueue() {
22
- whenever(timingModule.hasActiveTimersInRange(any())).thenReturn(true)
23
- }
24
-
25
- fun givenNoActiveTimersInQueue() {
26
- whenever(timingModule.hasActiveTimersInRange(any())).thenReturn(false)
27
- }
28
-
29
- fun uut() = DelegatedIdleInterrogationStrategy(timingModule)
30
-
31
- it("should be idle if timing module has no active timers") {
32
- givenNoActiveTimersInQueue()
33
- assertThat(uut().isIdleNow()).isTrue()
34
- }
35
-
36
- it("should be busy if timing module has active timers") {
37
- givenActiveTimersInQueue()
38
- assertThat(uut().isIdleNow()).isFalse()
39
- }
40
-
41
- it("should specify the busy-interval as the active-timers lookahead range") {
42
- givenActiveTimersInQueue()
43
- uut().isIdleNow()
44
- verify(timingModule).hasActiveTimersInRange(eq(BUSY_INTERVAL_MS))
45
- }
46
- }
47
- })
@@ -1,189 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources.timers
2
-
3
- import android.view.Choreographer
4
- import androidx.test.espresso.IdlingResource
5
- import org.assertj.core.api.Assertions
6
- import org.mockito.kotlin.*
7
- import org.spekframework.spek2.Spek
8
- import org.spekframework.spek2.style.specification.describe
9
-
10
- private fun anIdlingResourceCallback() = mock<IdlingResource.ResourceCallback>()
11
-
12
- object TimersIdlingResourceSpec : Spek({
13
- describe("React Native timers idling-resource") {
14
- lateinit var choreographer: Choreographer
15
- lateinit var idleInterrogationStrategy: IdleInterrogationStrategy
16
-
17
- beforeEachTest {
18
- idleInterrogationStrategy = mock()
19
- choreographer = mock()
20
- }
21
-
22
- fun uut() = TimersIdlingResource(idleInterrogationStrategy) { choreographer }
23
-
24
- fun givenIdleStrategy() {
25
- whenever(idleInterrogationStrategy.isIdleNow()).thenReturn(true)
26
- }
27
-
28
- fun givenBusyStrategy() {
29
- whenever(idleInterrogationStrategy.isIdleNow()).thenReturn(false)
30
- }
31
-
32
- fun getChoreographerCallback(): Choreographer.FrameCallback {
33
- argumentCaptor<Choreographer.FrameCallback>().apply {
34
- verify(choreographer).postFrameCallback(capture())
35
- return firstValue
36
- }
37
- }
38
-
39
- fun invokeChoreographerCallback() {
40
- getChoreographerCallback().doFrame(0L)
41
- }
42
-
43
- it("should return a debug-name") {
44
- Assertions.assertThat(uut().getDebugName()).isEqualTo("timers")
45
- }
46
-
47
- it("should be idle if strategy says so") {
48
- givenIdleStrategy()
49
- Assertions.assertThat(uut().isIdleNow).isTrue()
50
- }
51
-
52
- it("should be busy if strategy says so") {
53
- givenBusyStrategy()
54
- Assertions.assertThat(uut().isIdleNow).isFalse()
55
- }
56
-
57
- it("should transition to idle if found idle by strategy") {
58
- givenIdleStrategy()
59
-
60
- val callback = anIdlingResourceCallback()
61
-
62
- with(uut()) {
63
- registerIdleTransitionCallback(callback)
64
- isIdleNow
65
- }
66
-
67
- verify(callback).onTransitionToIdle()
68
- }
69
-
70
- it("should NOT transition to idle if found busy by strategy") {
71
- givenBusyStrategy()
72
-
73
- val callback = anIdlingResourceCallback()
74
-
75
- with(uut()) {
76
- registerIdleTransitionCallback(callback)
77
- isIdleNow
78
- }
79
-
80
- verify(callback, never()).onTransitionToIdle()
81
- }
82
-
83
- it("should be idle if paused") {
84
- givenBusyStrategy()
85
-
86
- val uut = uut().apply {
87
- pause()
88
- }
89
-
90
- Assertions.assertThat(uut.isIdleNow).isTrue()
91
- }
92
-
93
- it("should be busy if paused and resumed") {
94
- givenBusyStrategy()
95
-
96
- val uut = uut().apply {
97
- pause()
98
- resume()
99
- }
100
-
101
- Assertions.assertThat(uut.isIdleNow).isFalse()
102
- }
103
-
104
- it("should notify of transition to idle upon pausing") {
105
- givenBusyStrategy()
106
-
107
- val callback = anIdlingResourceCallback()
108
-
109
- with(uut()) {
110
- registerIdleTransitionCallback(callback)
111
- pause()
112
- }
113
-
114
- verify(callback).onTransitionToIdle()
115
- }
116
-
117
- it("should enqueue an is-idle check using choreographer when a callback gets registered") {
118
- with(uut()) {
119
- registerIdleTransitionCallback(mock())
120
- }
121
-
122
- verify(choreographer).postFrameCallback(any())
123
- }
124
-
125
- it("should transition to idle when preregistered choreographer is dispatched") {
126
- givenIdleStrategy()
127
-
128
- val callback = anIdlingResourceCallback()
129
-
130
- uut().registerIdleTransitionCallback(callback)
131
- invokeChoreographerCallback()
132
-
133
- verify(callback).onTransitionToIdle()
134
- }
135
-
136
- it("should NOT transition to idle if not idle when preregistered choreographer is dispatched") {
137
- givenBusyStrategy()
138
-
139
- val callback = anIdlingResourceCallback()
140
-
141
- uut().registerIdleTransitionCallback(callback)
142
- invokeChoreographerCallback()
143
-
144
- verify(callback, never()).onTransitionToIdle()
145
- }
146
-
147
- it("should re-register choreographer if found idle while preregistered choreographer is dispatched") {
148
- givenBusyStrategy()
149
-
150
- val callback = anIdlingResourceCallback()
151
-
152
- val uut = uut()
153
- uut.registerIdleTransitionCallback(callback)
154
- invokeChoreographerCallback()
155
-
156
- verify(choreographer, times(2)).postFrameCallback(any())
157
- }
158
-
159
- it("should adhere to pausing also when invoked via choreographer callback") {
160
- givenBusyStrategy()
161
-
162
- val callback = anIdlingResourceCallback()
163
-
164
- uut().apply {
165
- pause()
166
- registerIdleTransitionCallback(callback)
167
- }
168
- val runtimeChoreographerCallback = getChoreographerCallback()
169
-
170
- reset(callback, choreographer)
171
- runtimeChoreographerCallback.doFrame(0L)
172
-
173
- verify(callback, never()).onTransitionToIdle()
174
- verify(choreographer, never()).postFrameCallback(any())
175
- }
176
-
177
- it("should enqueue an additional idle check (using choreographer) if found busy") {
178
- givenBusyStrategy()
179
- uut().isIdleNow
180
- verify(choreographer).postFrameCallback(any())
181
- }
182
-
183
- it("should NOT enqueue an additional idle check (using choreographer) if found idle") {
184
- givenIdleStrategy()
185
- uut().isIdleNow
186
- verify(choreographer, never()).postFrameCallback(any())
187
- }
188
- }
189
- })