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.
- 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
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.aar.sha512 +1 -0
- 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
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.30.0/detox-20.30.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/android/build.gradle +5 -5
- package/android/detox/proguard-rules-app.pro +3 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +54 -3
- package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +11 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/matcher/IsDisplayingAtLeastDetoxMatcher.kt +2 -2
- package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java +4 -7
- package/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java +0 -5
- package/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java +33 -8
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +6 -11
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeInfo.kt +4 -11
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxIdlingResource.kt +42 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/ReactNativeIdlingResources.kt +145 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/animations/AnimatedModuleIdlingResource.kt +61 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/bridge/BridgeIdlingResource.kt +72 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/DetoxIdlingResourceFactory.kt +32 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/IdlingResourcesName.kt +10 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/factory/LooperName.kt +6 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/looper/MQThreadsReflector.kt +47 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/network/NetworkIdlingResource.kt +105 -0
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{NetworkingModuleReflected.kt → network/NetworkingModuleReflected.kt} +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{AsyncStorageIdlingResource.kt → storage/AsyncStorageIdlingResource.kt} +33 -35
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/{SerialExecutorReflected.kt → storage/SerialExecutorReflected.kt} +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt +21 -19
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIManagerModuleReflected.kt +19 -27
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIModuleIdlingResource.kt +5 -17
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceTest.kt +248 -0
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResourcesTest.kt +5 -1
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt +1 -0
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceTest.kt +212 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/android/rninfo.gradle +31 -24
- package/android/settings.gradle +11 -6
- package/detox.d.ts +39 -0
- package/package.json +11 -8
- package/scripts/postinstall.js +2 -2
- package/scripts/updateGradle.js +41 -8
- package/src/DetoxWorker.js +11 -6
- package/src/android/espressoapi/EspressoDetox.js +83 -0
- package/src/copilot/DetoxCopilot.js +3 -15
- package/src/copilot/detoxCopilotFrameworkDriver.js +27 -15
- package/src/devices/runtime/RuntimeDevice.js +11 -0
- package/src/devices/runtime/drivers/DeviceDriverBase.js +8 -0
- package/src/devices/runtime/drivers/android/AndroidDriver.js +16 -0
- package/src/devices/runtime/drivers/ios/SimulatorDriver.js +35 -0
- package/src/utils/assertArgument.js +9 -0
- package/src/utils/invocationTraceDescriptions.js +1 -0
- package/src/utils/mapDeviceLongPressArguments.js +56 -0
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom +0 -100
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +0 -13
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +0 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxDriverAtoms.java +0 -642
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +0 -229
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java +0 -215
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java +0 -94
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java +0 -29
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java +0 -134
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt +0 -23
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt +0 -16
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +0 -71
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt +0 -227
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt +0 -47
- package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt +0 -189
@@ -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
|
-
})
|