detox 20.0.0-breaking.new-global-lifecycle.0 → 20.0.3-breaking.new-global-lifecycle.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.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar → 20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom → 20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom} +2 -2
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/build.gradle +2 -2
- package/android/detox/build.gradle +2 -2
- package/android/detox/publish-pom.gradle +5 -1
- package/android/detox/publishing.gradle +9 -7
- package/android/detox/src/full/java/com/wix/detox/adapters/server/WebSocketClient.java +3 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +1 -3
- package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +1 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +22 -0
- package/android/detox/src/{main → full}/java/com/wix/detox/espresso/action/GetAttributesAction.kt +13 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/common/SliderHelper.kt +75 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +16 -23
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt +54 -8
- package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +13 -4
- package/android/detox/src/main/java/com/wix/detox/common/DetoxErrors.java +4 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +2 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/action/common/ReflectUtils.kt +10 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/UiControllerUtils.kt +1 -1
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +15 -3
- package/android/detox/src/testFull/java/com/wix/detox/espresso/common/SliderHelperTest.kt +39 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +2 -1
- package/android/gradlew +181 -107
- package/index.d.ts +5 -0
- package/internals.d.ts +25 -18
- package/local-cli/build.js +1 -1
- package/local-cli/build.test.js +14 -14
- package/local-cli/test.js +3 -3
- package/local-cli/test.test.js +20 -14
- package/local-cli/testCommand/TestRunnerCommand.js +6 -6
- package/package.json +4 -4
- package/runners/jest/testEnvironment/index.js +1 -1
- package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +5 -9
- package/runners/jest/testEnvironment/listeners/SpecReporter.js +1 -1
- package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +1 -1
- package/src/DetoxWorker.js +12 -1
- package/src/artifacts/log/android/ADBLogcatRecording.js +11 -28
- package/src/configuration/composeAppsConfig.js +1 -1
- package/src/configuration/composeRunnerConfig.js +49 -1
- package/src/configuration/index.js +9 -8
- package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +1 -0
- package/src/devices/common/drivers/android/exec/ADB.js +5 -0
- package/src/errors/DetoxConfigErrorComposer.js +5 -3
- package/src/ipc/IPCClient.js +3 -2
- package/src/ipc/IPCServer.js +16 -3
- package/src/ipc/state.js +24 -2
- package/src/realms/DetoxContext.js +3 -3
- package/src/realms/DetoxPrimaryContext.js +13 -7
- package/src/realms/DetoxSecondaryContext.js +4 -3
- package/src/utils/ChromeTracingExporter.js +6 -5
- package/src/utils/environment.js +30 -15
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +0 -36
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/AdjustSliderToPositionActionTest.kt +0 -59
@@ -0,0 +1 @@
|
|
1
|
+
c6493b7e10e165c7c6e7f0b4cf9d100c
|
@@ -0,0 +1 @@
|
|
1
|
+
6afd03fe5e86a8a04e4caf452772e710d2943deb
|
@@ -0,0 +1 @@
|
|
1
|
+
1fd68b232ab5d4668575c8d666cacb5c8ab02e50f7aed50d8d53d36d2c669eee
|
@@ -0,0 +1 @@
|
|
1
|
+
3b59f3522d88982355734b5a6d74add724fdd37b569bfc4fb07a8a1f954aab82e054bb5348833b9c156479af8440af6aabb4c2f0f684ff10afe7ca330d2a17a1
|
@@ -0,0 +1 @@
|
|
1
|
+
692bae402dc4d4f29b815943905eb9e7
|
@@ -0,0 +1 @@
|
|
1
|
+
130eba535610edf748a958abcddf5b2551b371a6
|
@@ -0,0 +1 @@
|
|
1
|
+
3ab48363cf0d353f3013e0a1157a8f1781e3ef91f86929c321c885aba8f0af52
|
@@ -0,0 +1 @@
|
|
1
|
+
b5034dce6f23e5356cc635d35c511314c074f1a4b01ae5cf15663f00d9b27711add721b3a9e9b318bacae16209e8474ccf3fd29533f4e591353169da7ad6c2c5
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
e7043eb4fd0dfa3c309fd8cd35ee68e5
|
@@ -0,0 +1 @@
|
|
1
|
+
80bef0c22a710dabb0e72b8d15c59125db1bd58b
|
@@ -0,0 +1 @@
|
|
1
|
+
7828ffdff493f8a856efad9b7db540e4e6b13b91260292efe98791013ba2db04
|
@@ -0,0 +1 @@
|
|
1
|
+
a57448b5eec5edfb2b45b99b9c8a6714b3384f71ade0f25da7b453d14c29597e818690b293cefa9be9362be29efb2c420664283cb1fc994883cd143d46506a2f
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
2
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
4
4
|
<groupId>com.wix</groupId>
|
5
5
|
<artifactId>detox</artifactId>
|
6
|
-
<version>20.0.
|
6
|
+
<version>20.0.3-breaking.new-global-lifecycle.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
|
+
1576eed74ead432e6108c03493a6873c
|
@@ -0,0 +1 @@
|
|
1
|
+
092446317977f5dc4261d559e9608932254f5e3b
|
@@ -0,0 +1 @@
|
|
1
|
+
f05c7aab6a3e42433c2934f4b7617441cce2d9c1879319cd5999b765cce8d968
|
@@ -0,0 +1 @@
|
|
1
|
+
1c0756ed5dd13915de4625248beffb25c78fdf56635b54b65df36c61116ae860a66bc421e14641630d165b1cc630f51a225221dbd8789214d108bc531eb51ef7
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<groupId>com.wix</groupId>
|
4
4
|
<artifactId>detox</artifactId>
|
5
5
|
<versioning>
|
6
|
-
<latest>20.0.
|
7
|
-
<release>20.0.
|
6
|
+
<latest>20.0.3-breaking.new-global-lifecycle.0</latest>
|
7
|
+
<release>20.0.3-breaking.new-global-lifecycle.0</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.0.
|
9
|
+
<version>20.0.3-breaking.new-global-lifecycle.0</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20220815091331</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2ef77b80bf45d2428c511a0c5723661e
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
a0dbdca1e65a0410798600e9b701a189b1831aac
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
ef9c05cfe345d3f50b63c73a2207a80d0a417bb2288059f987285188457c41eb
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
495f7993e651cf04a0cc907638214236249c2944faec87b77795d0eb923a602b414c550dbe0d82ad3555d1b7f55a62671bcdf81e5169f1f23a8fecd53f1f5cca
|
package/Detox-ios-src.tbz
CHANGED
Binary file
|
package/Detox-ios.tbz
CHANGED
Binary file
|
package/android/build.gradle
CHANGED
@@ -3,7 +3,7 @@ buildscript {
|
|
3
3
|
isOfficialDetoxLib = true
|
4
4
|
kotlinVersion = '1.2.0'
|
5
5
|
dokkaVersion = '1.6.0'
|
6
|
-
buildToolsVersion = '
|
6
|
+
buildToolsVersion = '31.0.0'
|
7
7
|
compileSdkVersion = 31
|
8
8
|
targetSdkVersion = 31
|
9
9
|
minSdkVersion = 21
|
@@ -15,7 +15,7 @@ buildscript {
|
|
15
15
|
google()
|
16
16
|
}
|
17
17
|
dependencies {
|
18
|
-
classpath 'com.android.tools.build:gradle:
|
18
|
+
classpath 'com.android.tools.build:gradle:7.0.4'
|
19
19
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
20
20
|
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokkaVersion"
|
21
21
|
|
@@ -5,8 +5,8 @@ apply plugin: 'kotlin-android-extensions'
|
|
5
5
|
def _ext = rootProject.ext
|
6
6
|
def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 31
|
7
7
|
def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 31
|
8
|
-
def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion :
|
9
|
-
def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion :
|
8
|
+
def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : "31.0.0"
|
9
|
+
def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 21
|
10
10
|
def _kotlinVersion = _ext.has('detoxKotlinVersion') ? _ext.detoxKotlinVersion : '1.2.0'
|
11
11
|
def _kotlinStdlib = _ext.has('detoxKotlinStdlib') ? _ext.detoxKotlinStdlib : 'kotlin-stdlib-jdk8'
|
12
12
|
|
@@ -4,8 +4,12 @@ project.ext.buildPomXmlDependencies = { pom, configurations ->
|
|
4
4
|
pom.withXml {
|
5
5
|
final rootNode = asNode().appendNode('dependencies')
|
6
6
|
addConfigurationDependencies(rootNode, configurations.api, 'compile')
|
7
|
-
addConfigurationDependencies(rootNode, configurations.compile, 'compile')
|
8
7
|
addConfigurationDependencies(rootNode, configurations.implementation, 'runtime')
|
8
|
+
|
9
|
+
// Legacy syntax
|
10
|
+
if (configurations.hasProperty('compile')) {
|
11
|
+
addConfigurationDependencies(rootNode, configurations.compile, 'compile')
|
12
|
+
}
|
9
13
|
}
|
10
14
|
}
|
11
15
|
|
@@ -140,13 +140,15 @@ signing {
|
|
140
140
|
|
141
141
|
project.afterEvaluate {
|
142
142
|
project.tasks.all { Task task ->
|
143
|
-
android
|
144
|
-
|
145
|
-
|
146
|
-
task.
|
147
|
-
|
148
|
-
|
149
|
-
|
143
|
+
android {
|
144
|
+
libraryVariants.all { variant ->
|
145
|
+
String variantName = variant.name.capitalize()
|
146
|
+
if (task.name == "publishMaven${variantName}AarPublicationToMavenRepository") {
|
147
|
+
task.dependsOn "assemble${variantName}"
|
148
|
+
task.dependsOn project.tasks.signArchives
|
149
|
+
task.doFirst {
|
150
|
+
onPrePublish()
|
151
|
+
}
|
150
152
|
}
|
151
153
|
}
|
152
154
|
}
|
@@ -2,6 +2,8 @@ package com.wix.detox.adapters.server;
|
|
2
2
|
|
3
3
|
import android.util.Log;
|
4
4
|
|
5
|
+
import com.wix.detox.common.DetoxErrors;
|
6
|
+
|
5
7
|
import org.json.JSONException;
|
6
8
|
import org.json.JSONObject;
|
7
9
|
|
@@ -84,7 +86,7 @@ public class WebSocketClient {
|
|
84
86
|
wsEventsHandler.onAction(type, params.toString(), messageId);
|
85
87
|
}
|
86
88
|
} catch (JSONException e) {
|
87
|
-
|
89
|
+
throw new DetoxErrors.DetoxIllegalArgumentException(e);
|
88
90
|
}
|
89
91
|
}
|
90
92
|
|
@@ -2,7 +2,6 @@ package com.wix.detox.espresso;
|
|
2
2
|
|
3
3
|
import android.view.View;
|
4
4
|
|
5
|
-
import com.facebook.react.views.slider.ReactSliderManager;
|
6
5
|
import com.wix.detox.common.DetoxErrors.DetoxRuntimeException;
|
7
6
|
import com.wix.detox.common.DetoxErrors.StaleActionException;
|
8
7
|
import com.wix.detox.espresso.action.AdjustSliderToPositionAction;
|
@@ -151,8 +150,7 @@ public class DetoxAction {
|
|
151
150
|
}
|
152
151
|
|
153
152
|
public static ViewAction adjustSliderToPosition(final double newPosition) {
|
154
|
-
|
155
|
-
return new AdjustSliderToPositionAction(newPosition, reactSliderManager);
|
153
|
+
return new AdjustSliderToPositionAction(newPosition);
|
156
154
|
}
|
157
155
|
|
158
156
|
public static ViewAction takeViewScreenshot() {
|
@@ -5,7 +5,7 @@ import android.util.Log;
|
|
5
5
|
import android.view.Choreographer;
|
6
6
|
|
7
7
|
import com.wix.detox.common.UIThread;
|
8
|
-
import com.wix.detox.espresso.common.utils.UiControllerUtils;
|
8
|
+
import com.wix.detox.espresso.action.common.utils.UiControllerUtils;
|
9
9
|
|
10
10
|
import org.joor.Reflect;
|
11
11
|
import org.joor.ReflectException;
|
package/android/detox/src/full/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
package com.wix.detox.espresso.action
|
2
|
+
|
3
|
+
import android.view.View
|
4
|
+
import androidx.appcompat.widget.AppCompatSeekBar
|
5
|
+
import androidx.test.espresso.UiController
|
6
|
+
import androidx.test.espresso.ViewAction
|
7
|
+
import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom
|
8
|
+
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
9
|
+
import com.wix.detox.espresso.common.SliderHelper
|
10
|
+
import org.hamcrest.Matcher
|
11
|
+
import org.hamcrest.Matchers
|
12
|
+
|
13
|
+
class AdjustSliderToPositionAction(private val targetPositionPct: Double) : ViewAction {
|
14
|
+
override fun getDescription() = "adjustSliderToPosition"
|
15
|
+
override fun getConstraints(): Matcher<View?>? =
|
16
|
+
Matchers.allOf( isDisplayed(), isAssignableFrom(AppCompatSeekBar::class.java) )
|
17
|
+
|
18
|
+
override fun perform(uiController: UiController?, view: View) {
|
19
|
+
val sliderHelper = SliderHelper.create(view)
|
20
|
+
sliderHelper.setProgressPct(targetPositionPct)
|
21
|
+
}
|
22
|
+
}
|
package/android/detox/src/{main → full}/java/com/wix/detox/espresso/action/GetAttributesAction.kt
RENAMED
@@ -9,6 +9,7 @@ import android.widget.TextView
|
|
9
9
|
import androidx.test.espresso.UiController
|
10
10
|
import com.google.android.material.slider.Slider
|
11
11
|
import com.wix.detox.espresso.ViewActionWithResult
|
12
|
+
import com.wix.detox.espresso.common.SliderHelper
|
12
13
|
import org.hamcrest.Matcher
|
13
14
|
import org.hamcrest.Matchers
|
14
15
|
import org.hamcrest.Matchers.allOf
|
@@ -127,13 +128,24 @@ private class CheckBoxAttributes {
|
|
127
128
|
rootObject.put("value", view.isChecked)
|
128
129
|
}
|
129
130
|
|
131
|
+
/**
|
132
|
+
* Note: this applies also to [androidx.appcompat.widget.AppCompatSeekBar], which
|
133
|
+
* is anything RN-slider-ish.
|
134
|
+
*/
|
130
135
|
private class ProgressBarAttributes {
|
131
136
|
fun get(json: JSONObject, view: View) {
|
132
137
|
if (view is ProgressBar) {
|
133
|
-
|
138
|
+
SliderHelper.maybeCreate(view)?.let {
|
139
|
+
getRNSliderValue(json, it)
|
140
|
+
} ?:
|
141
|
+
getProgressBarValue(json, view)
|
134
142
|
}
|
135
143
|
}
|
136
144
|
|
145
|
+
private fun getRNSliderValue(rootObject: JSONObject, sliderHelper: SliderHelper) {
|
146
|
+
rootObject.put("value", sliderHelper.getCurrentProgressPct())
|
147
|
+
}
|
148
|
+
|
137
149
|
private fun getProgressBarValue(rootObject: JSONObject, view: ProgressBar) =
|
138
150
|
rootObject.put("value", view.progress)
|
139
151
|
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
package com.wix.detox.espresso.common
|
2
|
+
|
3
|
+
import android.view.View
|
4
|
+
import androidx.appcompat.widget.AppCompatSeekBar
|
5
|
+
import com.facebook.react.bridge.JavaOnlyMap
|
6
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
7
|
+
import com.facebook.react.views.slider.ReactSlider
|
8
|
+
import com.wix.detox.common.DetoxErrors.DetoxIllegalStateException
|
9
|
+
import com.wix.detox.espresso.action.common.ReflectUtils
|
10
|
+
import org.joor.Reflect
|
11
|
+
|
12
|
+
private const val CLASS_REACT_SLIDER_LEGACY = "com.facebook.react.views.slider.ReactSlider"
|
13
|
+
private const val CLASS_REACT_SLIDER_COMMUNITY = "com.reactnativecommunity.slider.ReactSlider"
|
14
|
+
|
15
|
+
abstract class SliderHelper(protected val slider: AppCompatSeekBar) {
|
16
|
+
fun getCurrentProgressPct(): Double {
|
17
|
+
val nativeProgress = slider.progress.toDouble()
|
18
|
+
val nativeMax = slider.max
|
19
|
+
return nativeProgress / nativeMax
|
20
|
+
}
|
21
|
+
|
22
|
+
// TODO Make this more testable (e.g. by delegating the set action away)
|
23
|
+
fun setProgressPct(valuePct: Double) {
|
24
|
+
val maxJSProgress = calcMaxJSProgress()
|
25
|
+
val valueJS = valuePct * maxJSProgress
|
26
|
+
setProgressJS(valueJS)
|
27
|
+
}
|
28
|
+
|
29
|
+
protected abstract fun setProgressJS(valueJS: Double)
|
30
|
+
|
31
|
+
private fun calcMaxJSProgress(): Double {
|
32
|
+
val nativeProgress = slider.progress.toDouble()
|
33
|
+
val nativeMax = slider.max
|
34
|
+
val toMaxFactor = nativeMax / nativeProgress
|
35
|
+
|
36
|
+
val jsProgress = getJSProgress()
|
37
|
+
return jsProgress * toMaxFactor
|
38
|
+
}
|
39
|
+
|
40
|
+
private fun getJSProgress(): Double =
|
41
|
+
Reflect.on(slider).call("toRealProgress", slider.progress).get() as Double
|
42
|
+
|
43
|
+
companion object {
|
44
|
+
fun create(view: View) =
|
45
|
+
maybeCreate(view)
|
46
|
+
?: throw DetoxIllegalStateException("Cannot handle this type of a seek-bar view (Class ${view.javaClass.canonicalName}). " +
|
47
|
+
"Only React Native sliders are currently supported.")
|
48
|
+
|
49
|
+
fun maybeCreate(view: View): SliderHelper? =
|
50
|
+
when {
|
51
|
+
ReflectUtils.isAssignableFrom(view, CLASS_REACT_SLIDER_LEGACY)
|
52
|
+
-> LegacySliderHelper(view as ReactSlider)
|
53
|
+
ReflectUtils.isAssignableFrom(view, CLASS_REACT_SLIDER_COMMUNITY)
|
54
|
+
-> CommunitySliderHelper(view as AppCompatSeekBar)
|
55
|
+
else
|
56
|
+
-> null
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
private class LegacySliderHelper(slider: AppCompatSeekBar): SliderHelper(slider) {
|
62
|
+
override fun setProgressJS(valueJS: Double) {
|
63
|
+
val reactSliderManager = com.facebook.react.views.slider.ReactSliderManager()
|
64
|
+
reactSliderManager.updateProperties(slider as ReactSlider, buildStyles("value", valueJS))
|
65
|
+
}
|
66
|
+
|
67
|
+
private fun buildStyles(vararg keysAndValues: Any) = ReactStylesDiffMap(JavaOnlyMap.of(*keysAndValues))
|
68
|
+
}
|
69
|
+
|
70
|
+
private class CommunitySliderHelper(slider: AppCompatSeekBar): SliderHelper(slider) {
|
71
|
+
override fun setProgressJS(valueJS: Double) {
|
72
|
+
val reactSliderManager = Class.forName("com.reactnativecommunity.slider.ReactSliderManager").newInstance()
|
73
|
+
Reflect.on(reactSliderManager).call("setValue", slider, valueJS)
|
74
|
+
}
|
75
|
+
}
|
@@ -3,15 +3,17 @@
|
|
3
3
|
package com.wix.detox.espresso.matcher
|
4
4
|
|
5
5
|
import android.view.View
|
6
|
+
import androidx.appcompat.widget.AppCompatSeekBar
|
6
7
|
import androidx.test.espresso.matcher.BoundedMatcher
|
7
8
|
import androidx.test.espresso.matcher.ViewMatchers
|
8
9
|
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
|
9
|
-
import com.
|
10
|
+
import com.wix.detox.espresso.common.SliderHelper
|
10
11
|
import org.hamcrest.BaseMatcher
|
11
12
|
import org.hamcrest.Description
|
12
13
|
import org.hamcrest.Matcher
|
13
14
|
import org.hamcrest.Matchers.allOf
|
14
15
|
import org.hamcrest.TypeSafeMatcher
|
16
|
+
import kotlin.math.abs
|
15
17
|
|
16
18
|
/*
|
17
19
|
* An extension of [androidx.test.espresso.matcher.ViewMatchers].
|
@@ -36,6 +38,19 @@ fun isOfClassName(className: String): Matcher<View> {
|
|
36
38
|
fun isMatchingAtIndex(index: Int, innerMatcher: Matcher<View>): Matcher<View> =
|
37
39
|
ViewAtIndexMatcher(index, innerMatcher)
|
38
40
|
|
41
|
+
fun toHaveSliderPosition(expectedValuePct: Double, tolerance: Double): Matcher<View?> =
|
42
|
+
object: BoundedMatcher<View?, AppCompatSeekBar>(AppCompatSeekBar::class.java) {
|
43
|
+
override fun describeTo(description: Description) {
|
44
|
+
description.appendText("sliderPositionPercent($expectedValuePct)")
|
45
|
+
}
|
46
|
+
|
47
|
+
override fun matchesSafely(view: AppCompatSeekBar): Boolean {
|
48
|
+
val sliderHelper = SliderHelper.create(view)
|
49
|
+
val progressPct = sliderHelper.getCurrentProgressPct()
|
50
|
+
return (abs(progressPct - expectedValuePct) <= tolerance)
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
39
54
|
/**
|
40
55
|
* Same as [androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom], but accepts any class. Needed
|
41
56
|
* in order to avoid warning when passing 'any' class.
|
@@ -47,25 +62,3 @@ private class IsAssignableFromMatcher(private val clazz: Class<*>) : TypeSafeMat
|
|
47
62
|
description.appendText("is assignable from class: $clazz")
|
48
63
|
}
|
49
64
|
}
|
50
|
-
|
51
|
-
fun toHaveSliderPosition(expectedValue: Double, tolerance: Double): Matcher<View?> {
|
52
|
-
return object : BoundedMatcher<View?, ReactSlider>(ReactSlider::class.java) {
|
53
|
-
override fun describeTo(description: Description) {
|
54
|
-
description.appendText("expected: $expectedValue")
|
55
|
-
}
|
56
|
-
|
57
|
-
override fun matchesSafely(slider: ReactSlider?): Boolean {
|
58
|
-
val currentProgress = slider?.progress
|
59
|
-
|
60
|
-
if (currentProgress != null) {
|
61
|
-
val realProgress = slider.toRealProgress(currentProgress)
|
62
|
-
val currentPctFactor = slider.max / currentProgress.toDouble()
|
63
|
-
val realTotal = realProgress * currentPctFactor
|
64
|
-
val actualValue = realProgress / realTotal
|
65
|
-
return Math.abs(actualValue - expectedValue) <= tolerance
|
66
|
-
}
|
67
|
-
|
68
|
-
return false
|
69
|
-
}
|
70
|
-
}
|
71
|
-
}
|
@@ -7,17 +7,22 @@ import com.facebook.react.ReactInstanceManager
|
|
7
7
|
import com.facebook.react.bridge.ReactContext
|
8
8
|
import com.wix.detox.common.DetoxErrors
|
9
9
|
import com.wix.detox.config.DetoxConfig
|
10
|
+
import org.joor.Reflect
|
11
|
+
import java.lang.reflect.Proxy
|
10
12
|
import java.util.concurrent.CountDownLatch
|
11
13
|
import java.util.concurrent.TimeUnit
|
12
14
|
|
13
15
|
private const val LOG_TAG = "DetoxRNLoading"
|
14
16
|
|
17
|
+
private const val REACT_INSTANCE_EVENT_LISTENER_CLASS = "com.facebook.react.ReactInstanceEventListener"
|
18
|
+
private const val REACT_INSTANCE_EVENT_LISTENER_CLASS_COMPAT = "com.facebook.react.ReactInstanceManager\$ReactInstanceEventListener"
|
19
|
+
|
15
20
|
open class ReactNativeLoadingMonitor(
|
16
21
|
private val instrumentation: Instrumentation,
|
17
22
|
private val rnApplication: ReactApplication,
|
18
23
|
private val previousReactContext: ReactContext?,
|
19
24
|
private val config: DetoxConfig = DetoxConfig.CONFIG) {
|
20
|
-
val countDownLatch = CountDownLatch(1)
|
25
|
+
private val countDownLatch = CountDownLatch(1)
|
21
26
|
|
22
27
|
fun getNewContext(): ReactContext? {
|
23
28
|
subscribeToNewRNContextUpdates()
|
@@ -35,13 +40,9 @@ open class ReactNativeLoadingMonitor(
|
|
35
40
|
return@Runnable
|
36
41
|
}
|
37
42
|
|
38
|
-
rnInstanceManager
|
39
|
-
|
40
|
-
|
41
|
-
rnInstanceManager.removeReactInstanceEventListener(this)
|
42
|
-
countDownLatch.countDown()
|
43
|
-
}
|
44
|
-
})
|
43
|
+
subscribeAsyncRNContextHandler(rnInstanceManager) {
|
44
|
+
countDownLatch.countDown()
|
45
|
+
}
|
45
46
|
})
|
46
47
|
}
|
47
48
|
|
@@ -81,3 +82,48 @@ open class ReactNativeLoadingMonitor(
|
|
81
82
|
return rnInstanceManager.currentReactContext
|
82
83
|
}
|
83
84
|
}
|
85
|
+
|
86
|
+
private interface DummyListenerIdentifier
|
87
|
+
|
88
|
+
/**
|
89
|
+
* This baby bridges over RN's breaking change introduced in version 0.68:
|
90
|
+
* `ReactInstanceManager$ReactInstanceEventListener` was extracted onto a separate interface, having
|
91
|
+
* `ReactInstanceManager.{add|remove}ReactInstanceEventLister()` changing their signature to use it, accordingly.
|
92
|
+
*
|
93
|
+
* This made us resort to a solution based on dynamic proxies, because - depending on RN's version (at runtime), we
|
94
|
+
* need to dynamically decide what interface we "extend" (or actually shadow) via the proxy.
|
95
|
+
*
|
96
|
+
* @see RNDiff https://github.com/facebook/react-native/compare/v0.67.4..v0.68.0#diff-2f01f0cd7ff8c9ea58f12ef0eff5fa8250cad144dd5490598d80d8e9e743458aR1009
|
97
|
+
* @see DynamicProxies https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
|
98
|
+
*/
|
99
|
+
private fun subscribeAsyncRNContextHandler(rnInstanceManager: ReactInstanceManager, onReactContextInitialized: () -> Any) {
|
100
|
+
val listenerClass = resolveListenerClass()
|
101
|
+
val proxyInterfaces = arrayOf(
|
102
|
+
listenerClass,
|
103
|
+
DummyListenerIdentifier::class.java // In order to be able to implement equals()
|
104
|
+
)
|
105
|
+
val listener = Proxy.newProxyInstance(listenerClass.classLoader, proxyInterfaces) { listener, method, args ->
|
106
|
+
Log.d(LOG_TAG, "Listener-proxy method called: ${method.name}")
|
107
|
+
|
108
|
+
val result = when (method.name) {
|
109
|
+
"onReactContextInitialized" -> {
|
110
|
+
Log.i(LOG_TAG, "Got new RN-context async'ly through listener")
|
111
|
+
Reflect.on(rnInstanceManager).call("removeReactInstanceEventListener", listener)
|
112
|
+
onReactContextInitialized()
|
113
|
+
}
|
114
|
+
"equals" -> {
|
115
|
+
val candidate = args[0]
|
116
|
+
candidate is DummyListenerIdentifier
|
117
|
+
}
|
118
|
+
else -> Any()
|
119
|
+
}
|
120
|
+
|
121
|
+
result
|
122
|
+
}
|
123
|
+
Reflect.on(rnInstanceManager).call("addReactInstanceEventListener", listener)
|
124
|
+
}
|
125
|
+
|
126
|
+
private fun resolveListenerClass(): Class<*> {
|
127
|
+
val className = if (ReactNativeInfo.rnVersion().minor >= 68) REACT_INSTANCE_EVENT_LISTENER_CLASS else REACT_INSTANCE_EVENT_LISTENER_CLASS_COMPAT
|
128
|
+
return Class.forName(className)
|
129
|
+
}
|
@@ -2,6 +2,7 @@ package com.wix.detox.reactnative.idlingresources.uimodule
|
|
2
2
|
|
3
3
|
import android.util.Log
|
4
4
|
import android.view.View
|
5
|
+
import com.facebook.react.uimanager.IllegalViewOperationException
|
5
6
|
import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
|
6
7
|
import com.wix.detox.reactnative.ReactNativeInfo
|
7
8
|
import java.lang.ref.WeakReference
|
@@ -19,9 +20,7 @@ class RN66Workaround {
|
|
19
20
|
fun isScarceUISwitchCommandStuckInQueue(uiManagerModuleReflected: UIManagerModuleReflected): Boolean {
|
20
21
|
var isStuckSwitchOperation = false
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
if (rnVersion.minor >= 66 && uiManagerModuleReflected.getUIOpsCount() >= 1) {
|
23
|
+
if (isRelevantRNVersion() && uiManagerModuleReflected.getUIOpsCount() >= 1) {
|
25
24
|
val nextUIOperation = uiManagerModuleReflected.getNextUIOpReflected()
|
26
25
|
val view = getUIOpView(uiManagerModuleReflected, nextUIOperation)
|
27
26
|
val isReactSwitch = isReactSwitch(view)
|
@@ -46,10 +45,20 @@ class RN66Workaround {
|
|
46
45
|
return isStuckSwitchOperation
|
47
46
|
}
|
48
47
|
|
48
|
+
private fun isRelevantRNVersion(): Boolean {
|
49
|
+
val rnVersion = ReactNativeInfo.rnVersion()
|
50
|
+
return rnVersion.minor == 66 || (rnVersion.minor == 67 && rnVersion.patch < 4)
|
51
|
+
}
|
52
|
+
|
49
53
|
private fun getUIOpView(uiManagerModuleReflected: UIManagerModuleReflected, uiOperation: DispatchCommandOperationReflected?): View? {
|
50
54
|
val nativeViewHierarchyManager = uiManagerModuleReflected.nativeViewHierarchyManager() ?: return null
|
51
55
|
val tag = uiOperation?.tag ?: return null
|
52
|
-
return
|
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
|
+
}
|
53
62
|
}
|
54
63
|
|
55
64
|
private fun isReactSwitch(view: View?) = try {
|
@@ -5,7 +5,6 @@ public interface DetoxErrors {
|
|
5
5
|
public DetoxRuntimeException(Throwable cause) {
|
6
6
|
super(cause);
|
7
7
|
}
|
8
|
-
|
9
8
|
public DetoxRuntimeException(String message) {
|
10
9
|
super(message);
|
11
10
|
}
|
@@ -31,5 +30,9 @@ public interface DetoxErrors {
|
|
31
30
|
public DetoxIllegalArgumentException(String message) {
|
32
31
|
super(message);
|
33
32
|
}
|
33
|
+
|
34
|
+
public DetoxIllegalArgumentException(Throwable cause) {
|
35
|
+
super(cause);
|
36
|
+
}
|
34
37
|
}
|
35
38
|
}
|
@@ -1,10 +1,11 @@
|
|
1
|
+
|
1
2
|
package com.wix.detox.espresso
|
2
3
|
|
3
4
|
import androidx.test.espresso.UiController
|
4
5
|
import com.wix.detox.common.proxy.CallInfo
|
5
6
|
import com.wix.detox.common.proxy.SpyingInvocationHandler
|
6
7
|
import com.wix.detox.common.proxy.MethodsSpy
|
7
|
-
import com.wix.detox.espresso.common.utils.getUiController
|
8
|
+
import com.wix.detox.espresso.action.common.utils.getUiController
|
8
9
|
import org.joor.Reflect
|
9
10
|
|
10
11
|
class UiControllerSpy: MethodsSpy("uiController") {
|