detox 20.19.5 → 20.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Detox-android/com/wix/detox/{20.19.5/detox-20.19.5-sources.jar → 20.20.0/detox-20.20.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.19.5/detox-20.19.5.pom → 20.20.0/detox-20.20.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.20.0/detox-20.20.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-android/com/wix/detox-legacy/{20.19.5/detox-legacy-20.19.5-sources.jar → 20.20.0/detox-legacy-20.20.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/{20.19.5/detox-legacy-20.19.5.pom → 20.20.0/detox-legacy-20.20.0.pom} +1 -1
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.20.0/detox-legacy-20.20.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +47 -21
- package/android/detox/src/full/java/com/wix/detox/espresso/action/GetAttributesAction.kt +12 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSwipeWithLongPress.kt +44 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/action/LongPressAndDragAction.kt +89 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/ViewInteractionExt.kt +32 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwiper.kt +66 -4
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt +6 -54
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/LinearSwiper.kt +26 -0
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +11 -0
- package/detox.d.ts +10 -2
- package/package.json +2 -2
- package/src/android/actions/native.js +27 -0
- package/src/android/core/NativeElement.js +22 -0
- package/src/android/espressoapi/DetoxAction.js +42 -0
- package/src/utils/rn-consts/rn-consts.js +12 -4
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.aar +0 -0
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.19.5/detox-20.19.5.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.aar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.19.5/detox-legacy-20.19.5.pom.sha512 +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
06c04df2d24757bd08bfc0fb5fc8d83e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4c33f3a70d19672e881481cf7b96a33455ce6617
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
f155c86b66a87ba0ac92dd2d563b9a521283527b267b1b15ab0c299a830fe1dd
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2a468f22ad46429526c351cd93a78b11ffca19976b4c125de6e0bcb567e8a3187cf44d1937fc0a3ad6c44373a17050e390c9be633dcd637adfbb2506b32d9524
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
96e530b8d58b0393d98c0e2247e1a60f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2cb5d2fda3e4957c55e3b00e993a430ac3d213e9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4d96c2710e83ed6a596c3c97898d70d2b685c8a7e97ba8aa510feed72d7b5b1f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
62e8a9348d35ac705353da85b95bb1ae85854b4e60646c78524e03258cc173540a08d1372f2b5a8a105b180373578596d0da5ef42199d218b7bdfef844f00269
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
|
4
4
|
<groupId>com.wix</groupId>
|
|
5
5
|
<artifactId>detox</artifactId>
|
|
6
|
-
<version>20.
|
|
6
|
+
<version>20.20.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
|
+
3d130211f53462c2d621c933568bdc94
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
07ced3a0e52a803220fd2553f6907c09e162df46
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b49710a0ec44f42ab8ba63fa81361ae91b4cd71d3e1c46965cc3c6af4ec90d1e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a8d8afe9f4df9f4ab07c02ae9dbcae81e86e21ea378e41a4df6343de08d9eea626e2c80206de8f981b158ca16d709b665bd8d4c181b6a89cf0b6df8c016f9dde
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>com.wix</groupId>
|
|
4
4
|
<artifactId>detox</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>20.
|
|
7
|
-
<release>20.
|
|
6
|
+
<latest>20.20.0</latest>
|
|
7
|
+
<release>20.20.0</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>20.
|
|
9
|
+
<version>20.20.0</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20240402121112</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b69c7a4f9b9179cc48026542d7d7ca21
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
42ab3ad77518bab1b07ecbb5100b9d59b50ff6ed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c71a6efdc97efcb4fc1feb04c35e13062273be1f02367d2388dabbd6addbb94c
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5c498fd316bd028482c25d65c899e24b63a1363ae9591df2fb51de82da4b30e5609527c6792fa4cf1a2533a539cac068fb04ed72fdbbc2f5eeafdf2fcebd5aaa
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24c25326aec65db700f9112956c3ee87
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
82f39d382db703e29d470b276e048777dd66144f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
69c5b169569a5f7b54257e49ee3314aef1ee50c698783776e1d61eb825f237fe
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
379ca59ec57000fa2962779117e1e5531168dd84cc22fc684c204697d0ac22d9cd8c27c764996b5a4bf7dfef9c494872484e8daa9bf570629675532f7c65d98d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
46e8e8822d7864d2c5e20be3c3bba027
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d7a82a0126cb27386c4bb29607214424615b5ee3
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4438c339d4c6a810e76d007a755b1b4bbdacbaa92eab840ec5090f8207d4fc41
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6d960c8e53a8df4c5c4139abbd2ce44f7fab6855ebf44908e82e8eb8f90bcbe3392b6fbc421e1782811b3227613f4f5923e5ed29341d08fc77605b1f80b31d15
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
|
4
4
|
<groupId>com.wix</groupId>
|
|
5
5
|
<artifactId>detox-legacy</artifactId>
|
|
6
|
-
<version>20.
|
|
6
|
+
<version>20.20.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
|
+
a55835cbc1f84fec7901d1f9ab16271e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
313d55b91dafea72d29ffc5c62e64d767b1aa840
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
e2e5a32d53c8de1088462f1a77e0b0f95d12e6a28a4d8f2621334427b2f1fa81
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4188771a4703ce3adcefa0a5b07faee21e76a4ebded28d056b1f2691681aaacf8acc7863552a8cf7d8243d04a94f99e36e1c34b21cdb3117fd4941a6b41e36d5
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>com.wix</groupId>
|
|
4
4
|
<artifactId>detox-legacy</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>20.
|
|
7
|
-
<release>20.
|
|
6
|
+
<latest>20.20.0</latest>
|
|
7
|
+
<release>20.20.0</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>20.
|
|
9
|
+
<version>20.20.0</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20240402121223</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5b288a143f63e3103a7b388e7204ee29
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
927f092fe8186e38b20b049af1f013c6a986e6d0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
348dc12d41676e31072d4e02a855ec781956b08c51e8a9409bdaf00728cda685
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
150ea0094b15ae726bd08d78de639efa60177284d26397fd42127bcdf93ca78e7d390d025d95ce1f2ae387dce55a706cb2ef843ebc7701f74625d03d32bb6b70
|
package/Detox-ios-src.tbz
CHANGED
|
Binary file
|
package/Detox-ios.tbz
CHANGED
|
Binary file
|
|
@@ -1,19 +1,34 @@
|
|
|
1
1
|
package com.wix.detox.espresso;
|
|
2
2
|
|
|
3
|
+
import static androidx.test.espresso.action.ViewActions.actionWithAssertions;
|
|
4
|
+
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
|
|
5
|
+
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
|
6
|
+
import static org.hamcrest.Matchers.allOf;
|
|
7
|
+
|
|
3
8
|
import android.view.View;
|
|
4
|
-
import android.os.Build;
|
|
5
9
|
|
|
10
|
+
import androidx.test.espresso.UiController;
|
|
11
|
+
import androidx.test.espresso.ViewAction;
|
|
12
|
+
import androidx.test.espresso.ViewInteraction;
|
|
13
|
+
import androidx.test.espresso.action.CoordinatesProvider;
|
|
14
|
+
import androidx.test.espresso.action.GeneralClickAction;
|
|
15
|
+
import androidx.test.espresso.action.GeneralLocation;
|
|
16
|
+
import androidx.test.espresso.action.Press;
|
|
17
|
+
import androidx.test.espresso.contrib.PickerActions;
|
|
18
|
+
|
|
19
|
+
import com.wix.detox.action.common.MotionDir;
|
|
6
20
|
import com.wix.detox.common.DetoxErrors.DetoxRuntimeException;
|
|
7
21
|
import com.wix.detox.common.DetoxErrors.StaleActionException;
|
|
8
|
-
import com.wix.detox.espresso.action.RNDetoxAccessibilityAction;
|
|
9
22
|
import com.wix.detox.espresso.action.AdjustSliderToPositionAction;
|
|
10
23
|
import com.wix.detox.espresso.action.DetoxMultiTap;
|
|
24
|
+
import com.wix.detox.espresso.action.GetAttributesAction;
|
|
25
|
+
import com.wix.detox.espresso.action.LongPressAndDragAction;
|
|
11
26
|
import com.wix.detox.espresso.action.RNClickAction;
|
|
27
|
+
import com.wix.detox.espresso.action.RNDetoxAccessibilityAction;
|
|
12
28
|
import com.wix.detox.espresso.action.ScreenshotResult;
|
|
13
29
|
import com.wix.detox.espresso.action.ScrollToIndexAction;
|
|
14
30
|
import com.wix.detox.espresso.action.TakeViewScreenshotAction;
|
|
15
|
-
import com.wix.detox.espresso.action.
|
|
16
|
-
import com.wix.detox.action.common.MotionDir;
|
|
31
|
+
import com.wix.detox.espresso.action.common.utils.ViewInteractionExt;
|
|
17
32
|
import com.wix.detox.espresso.scroll.DetoxScrollAction;
|
|
18
33
|
import com.wix.detox.espresso.scroll.DetoxScrollActionStaleAtEdge;
|
|
19
34
|
import com.wix.detox.espresso.scroll.ScrollEdgeException;
|
|
@@ -21,26 +36,12 @@ import com.wix.detox.espresso.scroll.ScrollHelper;
|
|
|
21
36
|
import com.wix.detox.espresso.scroll.SwipeHelper;
|
|
22
37
|
|
|
23
38
|
import org.hamcrest.Matcher;
|
|
39
|
+
|
|
24
40
|
import java.text.ParseException;
|
|
25
41
|
import java.text.SimpleDateFormat;
|
|
26
|
-
import java.time.ZonedDateTime;
|
|
27
42
|
import java.util.Calendar;
|
|
28
43
|
import java.util.Date;
|
|
29
44
|
|
|
30
|
-
import androidx.test.espresso.UiController;
|
|
31
|
-
import androidx.test.espresso.ViewAction;
|
|
32
|
-
import androidx.test.espresso.action.CoordinatesProvider;
|
|
33
|
-
import androidx.test.espresso.action.GeneralClickAction;
|
|
34
|
-
import androidx.test.espresso.action.GeneralLocation;
|
|
35
|
-
import androidx.test.espresso.action.Press;
|
|
36
|
-
import androidx.test.espresso.contrib.PickerActions;
|
|
37
|
-
|
|
38
|
-
import static androidx.test.espresso.action.ViewActions.actionWithAssertions;
|
|
39
|
-
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
|
|
40
|
-
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
|
41
|
-
|
|
42
|
-
import static org.hamcrest.Matchers.allOf;
|
|
43
|
-
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* Created by simonracz on 10/07/2017.
|
|
@@ -69,7 +70,7 @@ public class DetoxAction {
|
|
|
69
70
|
view.getLocationOnScreen(xy);
|
|
70
71
|
final float fx = xy[0] + px;
|
|
71
72
|
final float fy = xy[1] + py;
|
|
72
|
-
return new float[]
|
|
73
|
+
return new float[]{fx, fy};
|
|
73
74
|
}
|
|
74
75
|
};
|
|
75
76
|
return actionWithAssertions(new RNClickAction(c));
|
|
@@ -78,7 +79,7 @@ public class DetoxAction {
|
|
|
78
79
|
/**
|
|
79
80
|
* Scrolls to the edge of the given scrollable view.
|
|
80
81
|
*
|
|
81
|
-
* @param edge
|
|
82
|
+
* @param edge Direction to scroll (see {@link MotionDir})
|
|
82
83
|
* @param startOffsetPercentX Percentage denoting where the scroll should start from on the X-axis, with respect to the scrollable view.
|
|
83
84
|
* @param startOffsetPercentY Percentage denoting where the scroll should start from on the Y-axis, with respect to the scrollable view.
|
|
84
85
|
* @return ViewAction
|
|
@@ -182,6 +183,31 @@ public class DetoxAction {
|
|
|
182
183
|
return new AdjustSliderToPositionAction(newPosition);
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
public static ViewAction longPressAndDrag(Integer duration,
|
|
187
|
+
Double normalizedPositionX,
|
|
188
|
+
Double normalizedPositionY,
|
|
189
|
+
ViewInteraction targetElement,
|
|
190
|
+
Double normalizedTargetPositionX,
|
|
191
|
+
Double normalizedTargetPositionY,
|
|
192
|
+
boolean isFast,
|
|
193
|
+
Integer holdDuration) {
|
|
194
|
+
|
|
195
|
+
// We receive a ViewInteraction which represents an interactions of the target view. We need to extract the view
|
|
196
|
+
// from it in order to get the coordinates of the target view.
|
|
197
|
+
View targetView = ViewInteractionExt.getView(targetElement);
|
|
198
|
+
|
|
199
|
+
return actionWithAssertions(new LongPressAndDragAction(
|
|
200
|
+
duration,
|
|
201
|
+
normalizedPositionX,
|
|
202
|
+
normalizedPositionY,
|
|
203
|
+
targetView,
|
|
204
|
+
normalizedTargetPositionX,
|
|
205
|
+
normalizedTargetPositionY,
|
|
206
|
+
isFast,
|
|
207
|
+
holdDuration
|
|
208
|
+
));
|
|
209
|
+
}
|
|
210
|
+
|
|
185
211
|
public static ViewAction takeViewScreenshot() {
|
|
186
212
|
return new ViewActionWithResult<String>() {
|
|
187
213
|
private final TakeViewScreenshotAction action = new TakeViewScreenshotAction();
|
|
@@ -53,6 +53,7 @@ private class CommonAttributes : AttributeExtractor {
|
|
|
53
53
|
getAccessibilityLabel(json, view)
|
|
54
54
|
getAlpha(json, view)
|
|
55
55
|
getElevation(json, view)
|
|
56
|
+
getFrame(json, view)
|
|
56
57
|
getHeight(json, view)
|
|
57
58
|
getWidth(json, view)
|
|
58
59
|
getHasFocus(json, view)
|
|
@@ -64,6 +65,17 @@ private class CommonAttributes : AttributeExtractor {
|
|
|
64
65
|
json.put("identifier", it.toString())
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
private fun getFrame(json: JSONObject, view: View) {
|
|
69
|
+
val location = IntArray(2)
|
|
70
|
+
view.getLocationOnScreen(location)
|
|
71
|
+
json.put("frame", JSONObject().apply {
|
|
72
|
+
put("x", location[0])
|
|
73
|
+
put("y", location[1])
|
|
74
|
+
put("width", view.width)
|
|
75
|
+
put("height", view.height)
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
67
79
|
private fun getVisibility(json: JSONObject, view: View) {
|
|
68
80
|
json.put("visibility", visibilityMap[view.visibility])
|
|
69
81
|
json.put("visible", view.getLocalVisibleRect(Rect()))
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package com.wix.detox.espresso.action
|
|
2
|
+
|
|
3
|
+
import com.wix.detox.espresso.scroll.DetoxSwiper
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of the Detox swipe action with long press in the beginning of the swipe and at the end
|
|
7
|
+
*/
|
|
8
|
+
class DetoxSwipeWithLongPress(
|
|
9
|
+
private val durationStart: Int,
|
|
10
|
+
private val durationEnd: Int,
|
|
11
|
+
private val startX: Float,
|
|
12
|
+
private val startY: Float,
|
|
13
|
+
private val endX: Float,
|
|
14
|
+
private val endY: Float,
|
|
15
|
+
private val motionCount: Int,
|
|
16
|
+
private val swiper: DetoxSwiper
|
|
17
|
+
) {
|
|
18
|
+
|
|
19
|
+
fun perform() {
|
|
20
|
+
with(swiper) {
|
|
21
|
+
startAt(startX, startY)
|
|
22
|
+
wait(durationStart)
|
|
23
|
+
try {
|
|
24
|
+
val stepSizeX = (endX - startX) / (motionCount + 2f)
|
|
25
|
+
val stepSizeY = (endY - startY) / (motionCount + 2f)
|
|
26
|
+
|
|
27
|
+
var targetX = startX
|
|
28
|
+
var targetY = startY
|
|
29
|
+
for (step in 1..motionCount) {
|
|
30
|
+
targetX += stepSizeX
|
|
31
|
+
targetY += stepSizeY
|
|
32
|
+
|
|
33
|
+
if (!moveTo(targetX, targetY)) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
} finally {
|
|
38
|
+
moveTo(endX, endY)
|
|
39
|
+
wait(durationEnd)
|
|
40
|
+
finishAt(endX, endY)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package com.wix.detox.espresso.action
|
|
2
|
+
|
|
3
|
+
import android.graphics.Point
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.view.View
|
|
6
|
+
import androidx.test.espresso.UiController
|
|
7
|
+
import androidx.test.espresso.ViewAction
|
|
8
|
+
import androidx.test.espresso.matcher.ViewMatchers
|
|
9
|
+
import com.wix.detox.espresso.scroll.LinearSwiper
|
|
10
|
+
import org.hamcrest.Matcher
|
|
11
|
+
import kotlin.math.ceil
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
private const val SLOW_SCROLL_MOTIONS = 50
|
|
15
|
+
private const val FAST_SCROLL_MOTIONS = 20
|
|
16
|
+
|
|
17
|
+
class LongPressAndDragAction(
|
|
18
|
+
private val duration: Int,
|
|
19
|
+
private val normalizedPositionX: Double,
|
|
20
|
+
private val normalizedPositionY: Double,
|
|
21
|
+
private val targetView: View,
|
|
22
|
+
private val normalizedTargetPositionX: Double,
|
|
23
|
+
private val normalizedTargetPositionY: Double,
|
|
24
|
+
isFast: Boolean,
|
|
25
|
+
private val holdDuration: Int
|
|
26
|
+
) : ViewAction {
|
|
27
|
+
|
|
28
|
+
private val scrollMotions = if (isFast) FAST_SCROLL_MOTIONS else SLOW_SCROLL_MOTIONS
|
|
29
|
+
|
|
30
|
+
override fun getDescription(): String {
|
|
31
|
+
return "longPressAndDrag"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override fun getConstraints(): Matcher<View> {
|
|
35
|
+
return ViewMatchers.isAssignableFrom(
|
|
36
|
+
View::class.java
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override fun perform(uiController: UiController, view: View) {
|
|
41
|
+
performSwipe(uiController, view, targetView)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private fun performSwipe(uiController: UiController, sourceView: View, targetView: View) {
|
|
45
|
+
val xy = IntArray(2)
|
|
46
|
+
|
|
47
|
+
// Get start coordinates
|
|
48
|
+
sourceView.getLocationOnScreen(xy)
|
|
49
|
+
val sourceViewPoint = Point(xy[0], xy[1])
|
|
50
|
+
val startPoint = Point(
|
|
51
|
+
ceil(sourceViewPoint.x + sourceView.width * normalizedPositionX).toInt(),
|
|
52
|
+
ceil(sourceViewPoint.y + sourceView.height * normalizedPositionY).toInt()
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Get end coordinates
|
|
56
|
+
targetView.getLocationOnScreen(xy)
|
|
57
|
+
val targetViewPoint = Point(xy[0], xy[1])
|
|
58
|
+
val endPoint = Point(
|
|
59
|
+
ceil(targetViewPoint.x + targetView.width * normalizedTargetPositionX).toInt(),
|
|
60
|
+
ceil(targetViewPoint.y + targetView.height * normalizedTargetPositionY).toInt()
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
Log.d(
|
|
64
|
+
"LongPressAndDragAction",
|
|
65
|
+
"start:$startPoint, end:$endPoint duration: $duration, holdDuration: $holdDuration, scrollMotions: $scrollMotions, source:[$sourceViewPoint,${sourceView.width}x${sourceView.height}], target:[$targetViewPoint,${targetView.width}x${targetView.height}]"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
val swiper = LinearSwiper(uiController)
|
|
69
|
+
val swipe = DetoxSwipeWithLongPress(
|
|
70
|
+
duration,
|
|
71
|
+
holdDuration,
|
|
72
|
+
startPoint.x.toFloat(),
|
|
73
|
+
startPoint.y.toFloat(),
|
|
74
|
+
endPoint.x.toFloat(),
|
|
75
|
+
endPoint.y.toFloat(),
|
|
76
|
+
scrollMotions,
|
|
77
|
+
swiper
|
|
78
|
+
)
|
|
79
|
+
swipe.perform()
|
|
80
|
+
|
|
81
|
+
sourceView.getLocationOnScreen(xy)
|
|
82
|
+
|
|
83
|
+
// Please note that the actual coordinates are not the same as the end coordinates.
|
|
84
|
+
Log.d(
|
|
85
|
+
"LongPressAndDragAction",
|
|
86
|
+
"Performed swipe. Actual coordinates x=${xy[0]}, y=${xy[1]}. Normalized position x=${xy[0] + sourceView.width * normalizedTargetPositionX}, y=${xy[1] + sourceView.height * normalizedTargetPositionX}"
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
}
|
package/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/ViewInteractionExt.kt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
@file:JvmName("ViewInteractionExt")
|
|
2
|
+
package com.wix.detox.espresso.action.common.utils
|
|
3
|
+
|
|
4
|
+
import android.view.View
|
|
5
|
+
import androidx.test.espresso.ViewAction
|
|
6
|
+
import androidx.test.espresso.ViewInteraction
|
|
7
|
+
import org.hamcrest.Matcher
|
|
8
|
+
import org.hamcrest.Matchers
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
fun ViewInteraction.getView(): View {
|
|
12
|
+
var result: View? = null
|
|
13
|
+
|
|
14
|
+
val viewAction = object : ViewAction {
|
|
15
|
+
override fun getDescription(): String {
|
|
16
|
+
return "Get View"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getConstraints(): Matcher<View> {
|
|
20
|
+
return Matchers.any(View::class.java)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override fun perform(uiController: androidx.test.espresso.UiController, view: View) {
|
|
24
|
+
result = view
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
perform(viewAction)
|
|
29
|
+
|
|
30
|
+
return result ?: throw IllegalStateException("Failed to get view")
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -1,7 +1,69 @@
|
|
|
1
1
|
package com.wix.detox.espresso.scroll
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import android.view.MotionEvent
|
|
4
|
+
import androidx.test.espresso.UiController
|
|
5
|
+
import com.wix.detox.espresso.action.common.MotionEvents
|
|
6
|
+
|
|
7
|
+
abstract class DetoxSwiper(
|
|
8
|
+
private val uiController: UiController,
|
|
9
|
+
private val motionEvents: MotionEvents
|
|
10
|
+
) {
|
|
11
|
+
|
|
12
|
+
private var downEvent: MotionEvent? = null
|
|
13
|
+
|
|
14
|
+
protected val events = mutableListOf<MotionEvent>()
|
|
15
|
+
|
|
16
|
+
fun startAt(touchX: Float, touchY: Float) {
|
|
17
|
+
assertNotStarted()
|
|
18
|
+
|
|
19
|
+
downEvent = motionEvents.obtainDownEvent(touchX, touchY)
|
|
20
|
+
events.add(downEvent!!)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fun moveTo(targetX: Float, targetY: Float): Boolean {
|
|
24
|
+
assertStarted()
|
|
25
|
+
|
|
26
|
+
val moveEvent = motionEvents.obtainMoveEvent(downEvent!!, calcEventTime(targetX, targetY), targetX, targetY)
|
|
27
|
+
events.add(moveEvent)
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun wait(duration: Int) {
|
|
32
|
+
assertStarted()
|
|
33
|
+
|
|
34
|
+
val lastEvent = events.last()
|
|
35
|
+
// Insert a fake move event without actually moving, just to wait for the given duration.
|
|
36
|
+
val waitEvent = motionEvents.obtainMoveEvent(downEvent!!, lastEvent.eventTime + duration, lastEvent.x, lastEvent.y)
|
|
37
|
+
events.add(waitEvent)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun finishAt(releaseX: Float, releaseY: Float) {
|
|
41
|
+
assertStarted()
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
val upEvent = motionEvents.obtainUpEvent(downEvent!!, calcEventTime(releaseX, releaseY), releaseX, releaseY)
|
|
45
|
+
events.add(upEvent)
|
|
46
|
+
|
|
47
|
+
// Flush!
|
|
48
|
+
uiController.injectMotionEventSequence(events)
|
|
49
|
+
} finally {
|
|
50
|
+
events.forEach { event -> event.recycle() }
|
|
51
|
+
downEvent = null
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
private fun assertStarted() {
|
|
57
|
+
if (downEvent == null) {
|
|
58
|
+
throw IllegalStateException("Swiper not initialized - did you forget to call startAt()?")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun assertNotStarted() {
|
|
63
|
+
if (downEvent != null) {
|
|
64
|
+
throw IllegalStateException("Swiper already started")
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected abstract fun calcEventTime(targetX: Float, targetY: Float): Long
|
|
7
69
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.wix.detox.espresso.scroll
|
|
2
2
|
|
|
3
|
-
import android.view.MotionEvent
|
|
4
3
|
import android.view.ViewConfiguration
|
|
5
4
|
import androidx.test.espresso.UiController
|
|
6
5
|
import com.wix.detox.espresso.action.common.MotionEvents
|
|
@@ -15,56 +14,20 @@ import com.wix.detox.espresso.action.common.MotionEvents
|
|
|
15
14
|
*/
|
|
16
15
|
class FlinglessSwiper @JvmOverloads constructor(
|
|
17
16
|
expectedMotions: Int,
|
|
18
|
-
|
|
17
|
+
uiController: UiController,
|
|
19
18
|
viewConfig: ViewConfiguration,
|
|
20
|
-
|
|
21
|
-
: DetoxSwiper {
|
|
19
|
+
motionEvents: MotionEvents = MotionEvents())
|
|
20
|
+
: DetoxSwiper(uiController, motionEvents) {
|
|
22
21
|
|
|
23
22
|
private val pixelsPerSecond = viewConfig.scaledMinimumFlingVelocity * VELOCITY_SAFETY_RATIO
|
|
24
23
|
private val fastEventsCountLimit = expectedMotions * FAST_EVENTS_RATIO
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
private var events = mutableListOf<MotionEvent>()
|
|
29
|
-
private var motionsCount = 0
|
|
30
|
-
|
|
31
|
-
override fun startAt(touchX: Float, touchY: Float) {
|
|
32
|
-
assertNotStarted()
|
|
33
|
-
|
|
34
|
-
downEvent = motionEvents.obtainDownEvent(touchX, touchY)
|
|
35
|
-
events.add(downEvent!!)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
override fun moveTo(targetX: Float, targetY: Float): Boolean {
|
|
39
|
-
assertStarted()
|
|
40
|
-
|
|
41
|
-
val moveEvent = motionEvents.obtainMoveEvent(downEvent!!, calcEventTime(targetX, targetY), targetX, targetY)
|
|
42
|
-
events.add(moveEvent)
|
|
43
|
-
|
|
44
|
-
motionsCount++
|
|
45
|
-
return true
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
override fun finishAt(releaseX: Float, releaseY: Float) {
|
|
49
|
-
assertStarted()
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
val upEvent = motionEvents.obtainUpEvent(downEvent!!, calcEventTime(releaseX, releaseY), releaseX, releaseY)
|
|
53
|
-
events.add(upEvent)
|
|
54
|
-
|
|
55
|
-
// Flush!
|
|
56
|
-
uiController.injectMotionEventSequence(events)
|
|
57
|
-
} finally {
|
|
58
|
-
events.forEach { event -> event.recycle() }
|
|
59
|
-
downEvent = null
|
|
60
|
-
motionsCount = 0
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private fun calcEventTime(targetX: Float, targetY: Float): Long {
|
|
25
|
+
override fun calcEventTime(targetX: Float, targetY: Float): Long {
|
|
65
26
|
val lastEvent = events.last()
|
|
66
27
|
var dt = 10
|
|
67
28
|
|
|
29
|
+
val motionsCount = events.size
|
|
30
|
+
|
|
68
31
|
if (motionsCount >= fastEventsCountLimit) {
|
|
69
32
|
val dx = Math.abs((targetX - lastEvent.x))
|
|
70
33
|
val dy = Math.abs((targetY - lastEvent.y))
|
|
@@ -78,17 +41,6 @@ class FlinglessSwiper @JvmOverloads constructor(
|
|
|
78
41
|
return lastEvent.eventTime + Math.max(dt, 10)
|
|
79
42
|
}
|
|
80
43
|
|
|
81
|
-
private fun assertStarted() {
|
|
82
|
-
if (downEvent == null) {
|
|
83
|
-
throw IllegalStateException("Swiper not initialized - did you forget to call startAt()?")
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private fun assertNotStarted() {
|
|
88
|
-
if (downEvent != null) {
|
|
89
|
-
throw IllegalStateException("Swiper already started")
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
44
|
|
|
93
45
|
companion object {
|
|
94
46
|
// private const val LOG_TAG = "DetoxBatchedSwiper"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.wix.detox.espresso.scroll
|
|
2
|
+
|
|
3
|
+
import androidx.test.espresso.UiController
|
|
4
|
+
import com.wix.detox.espresso.action.common.MotionEvents
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The delay between each motion event.
|
|
8
|
+
* Reducing this value may fail the swipe on different devices. Please change with caution.
|
|
9
|
+
*/
|
|
10
|
+
private const val EVENT_DELAY = 25L
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Implementation of @see DetoxSwiper that swipes in a linear fashion uses const delay between events.
|
|
14
|
+
*/
|
|
15
|
+
class LinearSwiper @JvmOverloads constructor(
|
|
16
|
+
uiController: UiController,
|
|
17
|
+
motionEvents: MotionEvents = MotionEvents()
|
|
18
|
+
) : DetoxSwiper(uiController, motionEvents) {
|
|
19
|
+
|
|
20
|
+
override fun calcEventTime(targetX: Float, targetY: Float): Long {
|
|
21
|
+
val lastEvent = events.last()
|
|
22
|
+
|
|
23
|
+
return lastEvent.eventTime + EVENT_DELAY
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt
CHANGED
|
@@ -12,6 +12,7 @@ import org.junit.Before
|
|
|
12
12
|
import org.junit.Test
|
|
13
13
|
import org.junit.runner.RunWith
|
|
14
14
|
import org.mockito.kotlin.any
|
|
15
|
+
import org.mockito.kotlin.doAnswer
|
|
15
16
|
import org.mockito.kotlin.doReturn
|
|
16
17
|
import org.mockito.kotlin.mock
|
|
17
18
|
import org.mockito.kotlin.whenever
|
|
@@ -133,11 +134,21 @@ class GetAttributesActionTest {
|
|
|
133
134
|
on { elevation } doReturn 0.314f
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
doAnswer { invocation ->
|
|
138
|
+
val location = invocation.getArgument<IntArray>(0)
|
|
139
|
+
location[0] = 10
|
|
140
|
+
location[1] = 20
|
|
141
|
+
}.whenever(view).getLocationOnScreen(any())
|
|
142
|
+
|
|
136
143
|
val resultJson = perform()
|
|
137
144
|
assertThat(resultJson.opt("alpha")).isEqualTo(0.42f)
|
|
138
145
|
assertThat(resultJson.opt("width")).isEqualTo(123)
|
|
139
146
|
assertThat(resultJson.opt("height")).isEqualTo(456)
|
|
140
147
|
assertThat(resultJson.opt("elevation")).isEqualTo(0.314f)
|
|
148
|
+
assertThat(resultJson.optJSONObject("frame")?.opt("x")).isEqualTo(10)
|
|
149
|
+
assertThat(resultJson.optJSONObject("frame")?.opt("y")).isEqualTo(20)
|
|
150
|
+
assertThat(resultJson.optJSONObject("frame")?.opt("width")).isEqualTo(123)
|
|
151
|
+
assertThat(resultJson.optJSONObject("frame")?.opt("height")).isEqualTo(456)
|
|
141
152
|
}
|
|
142
153
|
|
|
143
154
|
@Test
|
package/detox.d.ts
CHANGED
|
@@ -1740,9 +1740,11 @@ declare global {
|
|
|
1740
1740
|
value?: unknown;
|
|
1741
1741
|
}
|
|
1742
1742
|
|
|
1743
|
-
interface IosElementAttributeFrame {
|
|
1744
|
-
|
|
1743
|
+
interface IosElementAttributeFrame extends ElementAttributeFrame { }
|
|
1744
|
+
|
|
1745
|
+
interface ElementAttributeFrame {
|
|
1745
1746
|
x: number;
|
|
1747
|
+
y: number;
|
|
1746
1748
|
width: number;
|
|
1747
1749
|
height: number;
|
|
1748
1750
|
}
|
|
@@ -1821,10 +1823,12 @@ declare global {
|
|
|
1821
1823
|
*/
|
|
1822
1824
|
visibility: 'visible' | 'invisible' | 'gone';
|
|
1823
1825
|
/**
|
|
1826
|
+
* @deprecated
|
|
1824
1827
|
* Width of the element, in pixels.
|
|
1825
1828
|
*/
|
|
1826
1829
|
width: number;
|
|
1827
1830
|
/**
|
|
1831
|
+
* @deprecated
|
|
1828
1832
|
* Height of the element, in pixels.
|
|
1829
1833
|
*/
|
|
1830
1834
|
height: number;
|
|
@@ -1840,6 +1844,10 @@ declare global {
|
|
|
1840
1844
|
* Whether the element is the one currently in focus.
|
|
1841
1845
|
*/
|
|
1842
1846
|
focused: boolean;
|
|
1847
|
+
/**
|
|
1848
|
+
* The frame of the element, in screen coordinate space.
|
|
1849
|
+
*/
|
|
1850
|
+
frame: ElementAttributeFrame;
|
|
1843
1851
|
/**
|
|
1844
1852
|
* The text size for the text element.
|
|
1845
1853
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "detox",
|
|
3
3
|
"description": "E2E tests and automation for mobile",
|
|
4
|
-
"version": "20.
|
|
4
|
+
"version": "20.20.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"detox": "local-cli/cli.js"
|
|
7
7
|
},
|
|
@@ -115,5 +115,5 @@
|
|
|
115
115
|
"browserslist": [
|
|
116
116
|
"node 14"
|
|
117
117
|
],
|
|
118
|
-
"gitHead": "
|
|
118
|
+
"gitHead": "b5821206730e4541260ab98eecaf77a77c569e59"
|
|
119
119
|
}
|
|
@@ -45,6 +45,32 @@ class PressKeyAction extends Action {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
class LongPressAndDragAction extends Action {
|
|
49
|
+
constructor(duration, normalizedPositionX, normalizedPositionY, targetElement, normalizedTargetPositionX, normalizedTargetPositionY, speed, holdDuration) {
|
|
50
|
+
super();
|
|
51
|
+
|
|
52
|
+
assertNormalized({ normalizedPositionX });
|
|
53
|
+
assertNormalized({ normalizedPositionY });
|
|
54
|
+
assertNormalized({ normalizedTargetPositionX });
|
|
55
|
+
assertNormalized({ normalizedTargetPositionY });
|
|
56
|
+
assertSpeed({ speed });
|
|
57
|
+
|
|
58
|
+
this._call = invoke.callDirectly(
|
|
59
|
+
DetoxActionApi.longPressAndDrag(
|
|
60
|
+
duration,
|
|
61
|
+
normalizedPositionX,
|
|
62
|
+
normalizedPositionY,
|
|
63
|
+
targetElement._call(),
|
|
64
|
+
normalizedTargetPositionX,
|
|
65
|
+
normalizedTargetPositionY,
|
|
66
|
+
speed === 'fast',
|
|
67
|
+
holdDuration
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
48
74
|
class TypeTextAction extends Action {
|
|
49
75
|
constructor(value) {
|
|
50
76
|
super();
|
|
@@ -157,6 +183,7 @@ module.exports = {
|
|
|
157
183
|
TapAction,
|
|
158
184
|
TapAtPointAction,
|
|
159
185
|
LongPressAction,
|
|
186
|
+
LongPressAndDragAction,
|
|
160
187
|
MultiClickAction,
|
|
161
188
|
PressKeyAction,
|
|
162
189
|
TypeTextAction,
|
|
@@ -48,6 +48,28 @@ class NativeElement {
|
|
|
48
48
|
return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
async longPressAndDrag(duration, normalizedPositionX, normalizedPositionY, targetElement, normalizedTargetPositionX, normalizedTargetPositionY, speed, holdDuration) {
|
|
52
|
+
const action = new actions.LongPressAndDragAction(
|
|
53
|
+
duration,
|
|
54
|
+
normalizedPositionX,
|
|
55
|
+
normalizedPositionY,
|
|
56
|
+
targetElement,
|
|
57
|
+
normalizedTargetPositionX,
|
|
58
|
+
normalizedTargetPositionY,
|
|
59
|
+
speed,
|
|
60
|
+
holdDuration);
|
|
61
|
+
const traceDescription = actionDescription.longPressAndDrag(
|
|
62
|
+
duration,
|
|
63
|
+
normalizedPositionX,
|
|
64
|
+
normalizedPositionY,
|
|
65
|
+
targetElement,
|
|
66
|
+
normalizedTargetPositionX,
|
|
67
|
+
normalizedTargetPositionY,
|
|
68
|
+
speed,
|
|
69
|
+
holdDuration);
|
|
70
|
+
return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
|
|
71
|
+
}
|
|
72
|
+
|
|
51
73
|
async multiTap(times) {
|
|
52
74
|
if (typeof times !== 'number') throw new Error('times should be a number, but got ' + (times + (' (' + (typeof times + ')'))));
|
|
53
75
|
if (times < 1) throw new Error('times should be greater than 0, but got ' + times);
|
|
@@ -229,6 +229,48 @@ class DetoxAction {
|
|
|
229
229
|
};
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
static longPressAndDrag(duration, normalizedPositionX, normalizedPositionY, targetElement, normalizedTargetPositionX, normalizedTargetPositionY, isFast, holdDuration) {
|
|
233
|
+
if (typeof duration !== "number") throw new Error("duration should be a number, but got " + (duration + (" (" + (typeof duration + ")"))));
|
|
234
|
+
if (typeof normalizedPositionX !== "number") throw new Error("normalizedPositionX should be a number, but got " + (normalizedPositionX + (" (" + (typeof normalizedPositionX + ")"))));
|
|
235
|
+
if (typeof normalizedPositionY !== "number") throw new Error("normalizedPositionY should be a number, but got " + (normalizedPositionY + (" (" + (typeof normalizedPositionY + ")"))));
|
|
236
|
+
if (typeof normalizedTargetPositionX !== "number") throw new Error("normalizedTargetPositionX should be a number, but got " + (normalizedTargetPositionX + (" (" + (typeof normalizedTargetPositionX + ")"))));
|
|
237
|
+
if (typeof normalizedTargetPositionY !== "number") throw new Error("normalizedTargetPositionY should be a number, but got " + (normalizedTargetPositionY + (" (" + (typeof normalizedTargetPositionY + ")"))));
|
|
238
|
+
if (typeof isFast !== "boolean") throw new Error("isFast should be a boolean, but got " + (isFast + (" (" + (typeof isFast + ")"))));
|
|
239
|
+
if (typeof holdDuration !== "number") throw new Error("holdDuration should be a number, but got " + (holdDuration + (" (" + (typeof holdDuration + ")"))));
|
|
240
|
+
return {
|
|
241
|
+
target: {
|
|
242
|
+
type: "Class",
|
|
243
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
|
244
|
+
},
|
|
245
|
+
method: "longPressAndDrag",
|
|
246
|
+
args: [{
|
|
247
|
+
type: "Integer",
|
|
248
|
+
value: duration
|
|
249
|
+
}, {
|
|
250
|
+
type: "Double",
|
|
251
|
+
value: normalizedPositionX
|
|
252
|
+
}, {
|
|
253
|
+
type: "Double",
|
|
254
|
+
value: normalizedPositionY
|
|
255
|
+
}, {
|
|
256
|
+
type: "Invocation",
|
|
257
|
+
value: targetElement
|
|
258
|
+
}, {
|
|
259
|
+
type: "Double",
|
|
260
|
+
value: normalizedTargetPositionX
|
|
261
|
+
}, {
|
|
262
|
+
type: "Double",
|
|
263
|
+
value: normalizedTargetPositionY
|
|
264
|
+
}, {
|
|
265
|
+
type: "boolean",
|
|
266
|
+
value: isFast
|
|
267
|
+
}, {
|
|
268
|
+
type: "Integer",
|
|
269
|
+
value: holdDuration
|
|
270
|
+
}]
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
232
274
|
static takeViewScreenshot() {
|
|
233
275
|
return {
|
|
234
276
|
target: {
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
+
const DEFAULT_RN_VERSION = '99.9999.9999';
|
|
2
|
+
|
|
1
3
|
const rnVersion = (function parseRNVersion() {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
let raw;
|
|
5
|
+
try {
|
|
6
|
+
const packageJson = require('react-native/package.json');
|
|
7
|
+
raw = packageJson.version;
|
|
8
|
+
} catch {
|
|
9
|
+
// Default version for RN
|
|
10
|
+
raw = DEFAULT_RN_VERSION;
|
|
11
|
+
}
|
|
4
12
|
const [major, minor, patch] = raw.split('.');
|
|
5
13
|
return {
|
|
6
14
|
major,
|
|
7
15
|
minor,
|
|
8
16
|
patch,
|
|
9
|
-
raw
|
|
17
|
+
raw
|
|
10
18
|
};
|
|
11
19
|
})();
|
|
12
20
|
|
|
13
21
|
module.exports = {
|
|
14
|
-
rnVersion
|
|
22
|
+
rnVersion
|
|
15
23
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ef5f4d624c42d1cfc1c35eab0b6fc669
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
828c0678db282e6fcaa57531a9df8201bc372cbb
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1e0dd6e73697f2ac094b28fc9bdecf52c1d20e3004ec4876fa4e228e53a71d60
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1a93e1c2319c44078780d66a26d1ebc78ef988a8a0f69cbd81e4cc79149e0b300f0c33f474190678cddad86d54e79416f4c3944ffb5f0b6164aa9e29773e0998
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
221afe495c4ff28f344cff35e41e566a
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
9657a291e6e1725adb2a3e333248ad4a05892015
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
23a9f6a86b0fb26b426f6188be04dc98eed5edeaa7f77c6e682bae9b80906312
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a43c0a36b2b519a777662f087ba88e2bf781613ec86633434499ba70483fe072ebbbff6507f3ec3cb1cff7bfd5326af172d6fe7dcdc7990790796fe97d9c1519
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
8446c7127a92b93db77c0f1088d7e876
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
941870c07884db2324fb5f1b9dfa0c7dc9929a06
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2228df1b6a06c8c07b1008ab1da7a2eb743b186d05d5d797fd4151b55df08df8
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2a131492a23f98f4c45dbcf3f26a97c62e842a38cd03c21717be83fae18ccbbf41c6fc6d613e7d4308939111c2c02ab00e65001e1adaec2202bcd9d899c9a883
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
aab82e5a9267a9ccdf45b6c013aaa8ca
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
5a4bdd3ab91c7d509328e6c4f610c2ce9a5bbb0c
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a4bae311cb2922a8d3e5e75e855ca23f1d49846e19d203514c9c55bcad3aa332
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a26ce58824701b283041b74fe589d5648faf0acf85f675b5724af6dc8099be837000975787315abfb9b2f8bcc0c3b150c87df2be33339f7a08655f2cfef18b9b
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2ccac07d6c4079ce6a948d8cb8e78985
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e3b8881d1f3a9ff8c71cdfa84a7cc2a69b025401
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
73266b3affb9ce645c35133ef28db777e3e321343d9b7d946610b2178b5b3863
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d9032a388871d30165507ca248712125a3cf6f5443b2a74eed35ab3a4a075d9a6c5c631e0d80395b66b465a464e4ee7f795a65acbeb3b6082177eabafe29e1b5
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
371fa89c30de7e470906ae0a9d5ddc9b
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
abb73698e3227e38e2261f5cea3d3f87e4595d64
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
05a6d9e21b708659310e449ffd61918cf4bdc1c1614d8e2a53b89f78cc9b252e
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
6a1bb4db5e330d5e1c51af689b97bdff2bef36c4c1e0c6f0ce35e90b32ac5e288321a8fa8ca9d8967adb786c43ab11f62f2b60fb24796a760269b9ae5a873a43
|