detox 20.27.6 → 20.28.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.6/detox-20.27.6-sources.jar → 20.28.0/detox-20.28.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.27.6/detox-20.27.6.pom → 20.28.0/detox-20.28.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.28.0/detox-20.28.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.27.6/detox-legacy-20.27.6-sources.jar → 20.28.0/detox-legacy-20.28.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/{20.27.6/detox-legacy-20.27.6.aar → 20.28.0/detox-legacy-20.28.0.aar} +0 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/{20.27.6/detox-legacy-20.27.6.pom → 20.28.0/detox-legacy-20.28.0.pom} +1 -1
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.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-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +53 -2
- 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/detox.d.ts +39 -0
- package/package.json +3 -3
- package/src/android/espressoapi/EspressoDetox.js +83 -0
- 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.6/detox-20.27.6-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.aar +0 -0
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.27.6/detox-20.27.6.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.aar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.27.6/detox-legacy-20.27.6.pom.sha512 +0 -1
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
5f9c61888ac541880ca966b9cf54f996
|
@@ -0,0 +1 @@
|
|
1
|
+
905d3c70363af1ef378373c1337b2a02fb085847
|
@@ -0,0 +1 @@
|
|
1
|
+
9da6d1b24a67e2c3f54e4f85b76d2f308df4f4783a2ead715cacae4078d54198
|
@@ -0,0 +1 @@
|
|
1
|
+
488ca79bd9330a788fe0659818e9256d06908d3c9ff765ddf9ee41e253b78dbbb0db1409f794532019fa39ca3395c8a27396398cbe56d203989afb258c31f1b8
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
2d6e006f6dc0428fd9be3efb971433cf
|
@@ -0,0 +1 @@
|
|
1
|
+
7e71f1e0bd4e0beea5f2c8db164c560255332a30
|
@@ -0,0 +1 @@
|
|
1
|
+
d0d12c5ecb2c4d760332b168a9237aa1948ac10ea1736a4b75067de6ebaaf6cb
|
@@ -0,0 +1 @@
|
|
1
|
+
1ebe46cd76b0bcfdcab9fc6b1a863b257da71ee05bac63f538fab1351f55ba858d97b81aba1d040d5db74c9e27508b12dbeb6ae2e6c09ef469a184516fc82c00
|
@@ -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.28.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
|
+
72dd9fb9e071a00dfb6b7731da5a8268
|
@@ -0,0 +1 @@
|
|
1
|
+
5ea89a7c06c7d3e3ebee78b290422c25471ffccf
|
@@ -0,0 +1 @@
|
|
1
|
+
48839af705f5ce69be3f8075367e012c822f2cb9b4d5d66d1466c718f7adecd4
|
@@ -0,0 +1 @@
|
|
1
|
+
01b1f663413f39c8f25e81f70669ddce75f2f332f154c531cb5289a646d25e3cc80120580202da5bc3cf1e4fd865a61b0551126be9da37b61eeec6f75fc2b9cf
|
@@ -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.28.0</latest>
|
7
|
+
<release>20.28.0</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.
|
9
|
+
<version>20.28.0</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20241114182711</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
4409ef64d1213179048bfd9fed283361
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
112cd653d1f7777391df1fb10e9a33619f5d0c1b
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2177b496977ac272c3b7333fa2a4505f8756dca0bc265970801d60985a6a8dfd
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
da830892bc25886891e341fe7e167f4aa1138c8fc2c28246d31409c39e82aa64f13c0a0a39bb6394a260ee2f449bf16e5378be6026cf1862759d57cec40fd053
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
d01d2e826e3b99f843a7e444d309d6d2
|
@@ -0,0 +1 @@
|
|
1
|
+
3cf94f158d84d98241e421c64cc5c06142fbf4c0
|
@@ -0,0 +1 @@
|
|
1
|
+
cb302fd2cd81b8ba3a03115ab529d073bb8f223af0088e89e22af90120117412
|
@@ -0,0 +1 @@
|
|
1
|
+
37109f12c35e795d76f25a7c462c143dcedbbd0cb66bdde25364f237754da179307e87b73fae67e5432b7724903abe485c5105ac5667a7f6f26806b6c5229d88
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
f3e0e6447e243a7a93b9425d8ca2c34d
|
@@ -0,0 +1 @@
|
|
1
|
+
135215a6c872a80b0020ecface42fd07fde6e8a2
|
@@ -0,0 +1 @@
|
|
1
|
+
67f6e9df85d01f17887b135aa64b3db8b10afce941b70314fa1cc15580699102
|
@@ -0,0 +1 @@
|
|
1
|
+
a71be556721d9c7b600914bcbeaff171d0d959a3dbb816d4467c8f52caa5703d9b241c0a76c13e4010c57036fff63b0c157eb126c58a96fe593ef1a71dcd3778
|
@@ -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.28.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
|
+
2c9a5efdc4cc9949403de29543d189c3
|
@@ -0,0 +1 @@
|
|
1
|
+
dd1b295394376809aa40565060e7f0068758476d
|
@@ -0,0 +1 @@
|
|
1
|
+
28a059a24a50d3e94b75af039c1aee8dd403bb862525cce01876a4a188313eb1
|
@@ -0,0 +1 @@
|
|
1
|
+
252cf3d47cd05805ab38367c8b33793b5b7e210a5f7f88717b1439127f168181bd5b3a05fa020c4c444aad0dfb6ad81547a7bc05ce6dc5f8043aff2eea3096f1
|
@@ -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.28.0</latest>
|
7
|
+
<release>20.28.0</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.
|
9
|
+
<version>20.28.0</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20241114182808</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
dbb9351f570b2e9f79cd97583cda0e41
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
e043135169acc282528cb1990f80ae8be7fd89b2
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
723c473ca26e2ced79ca5d707aa4e96f068d3bb86577a66d54ae5c41231127f2
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
5061e8696bf7b07237dd2b8fc02f65054eaaa87884723ca0f706b3b1de63e153e636db8077c6fdfd29ad8d0ca67433ff6a327bf6ffaddf040e671a2cafb4106e
|
package/Detox-ios-framework.tbz
CHANGED
Binary file
|
package/Detox-ios-src.tbz
CHANGED
Binary file
|
package/Detox-ios-xcuitest.tbz
CHANGED
Binary file
|
@@ -21,12 +21,11 @@ import java.util.ArrayList;
|
|
21
21
|
|
22
22
|
import androidx.test.espresso.UiController;
|
23
23
|
import androidx.test.espresso.ViewAction;
|
24
|
-
import androidx.test.espresso.ViewInteraction;
|
25
|
-
import androidx.test.espresso.NoMatchingViewException;
|
26
24
|
import androidx.test.platform.app.InstrumentationRegistry;
|
27
25
|
|
28
26
|
import static androidx.test.espresso.Espresso.onView;
|
29
27
|
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
28
|
+
import static com.wix.detox.espresso.UiAutomatorHelper.getStatusBarHeightDps;
|
30
29
|
|
31
30
|
/**
|
32
31
|
* Created by rotemm on 26/12/2016.
|
@@ -34,6 +33,10 @@ import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
|
34
33
|
public class EspressoDetox {
|
35
34
|
private static final String LOG_TAG = "detox";
|
36
35
|
|
36
|
+
private static int calculateAdjustedY(View view, Integer y, boolean shouldIgnoreStatusBar) {
|
37
|
+
return shouldIgnoreStatusBar ? y + getStatusBarHeightDps(view) : y;
|
38
|
+
}
|
39
|
+
|
37
40
|
public static Object perform(Matcher<View> matcher, ViewAction action) {
|
38
41
|
ViewActionPerformer performer = ViewActionPerformer.forAction(action);
|
39
42
|
return performer.performOn(matcher);
|
@@ -121,5 +124,53 @@ public class EspressoDetox {
|
|
121
124
|
}
|
122
125
|
});
|
123
126
|
}
|
127
|
+
|
128
|
+
public static void tap(Integer x, Integer y, boolean shouldIgnoreStatusBar) {
|
129
|
+
onView(isRoot()).perform(new ViewAction() {
|
130
|
+
@Override
|
131
|
+
public Matcher<View> getConstraints() {
|
132
|
+
return isRoot();
|
133
|
+
}
|
134
|
+
|
135
|
+
@Override
|
136
|
+
public String getDescription() {
|
137
|
+
return "tap on screen";
|
138
|
+
}
|
139
|
+
|
140
|
+
@Override
|
141
|
+
public void perform(UiController uiController, View view) {
|
142
|
+
int adjustedY = calculateAdjustedY(view, y, shouldIgnoreStatusBar);
|
143
|
+
ViewAction action = DetoxAction.tapAtLocation(x, adjustedY);
|
144
|
+
action.perform(uiController, view);
|
145
|
+
uiController.loopMainThreadUntilIdle();
|
146
|
+
}
|
147
|
+
});
|
148
|
+
}
|
149
|
+
|
150
|
+
public static void longPress(Integer x, Integer y, boolean shouldIgnoreStatusBar) {
|
151
|
+
longPress(x, y, null, shouldIgnoreStatusBar);
|
152
|
+
}
|
153
|
+
|
154
|
+
public static void longPress(Integer x, Integer y, Integer duration, boolean shouldIgnoreStatusBar) {
|
155
|
+
onView(isRoot()).perform(new ViewAction() {
|
156
|
+
@Override
|
157
|
+
public Matcher<View> getConstraints() {
|
158
|
+
return isRoot();
|
159
|
+
}
|
160
|
+
|
161
|
+
@Override
|
162
|
+
public String getDescription() {
|
163
|
+
return "long press on screen";
|
164
|
+
}
|
165
|
+
|
166
|
+
@Override
|
167
|
+
public void perform(UiController uiController, View view) {
|
168
|
+
int adjustedY = calculateAdjustedY(view, y, shouldIgnoreStatusBar);
|
169
|
+
ViewAction action = DetoxAction.longPress(x, adjustedY, duration);
|
170
|
+
action.perform(uiController, view);
|
171
|
+
uiController.loopMainThreadUntilIdle();
|
172
|
+
}
|
173
|
+
});
|
174
|
+
}
|
124
175
|
}
|
125
176
|
|
@@ -1,8 +1,13 @@
|
|
1
1
|
package com.wix.detox.espresso;
|
2
2
|
|
3
|
+
import android.annotation.SuppressLint;
|
4
|
+
import android.content.Context;
|
3
5
|
import android.os.Handler;
|
6
|
+
import android.util.DisplayMetrics;
|
4
7
|
import android.util.Log;
|
8
|
+
import android.util.TypedValue;
|
5
9
|
import android.view.Choreographer;
|
10
|
+
import android.view.View;
|
6
11
|
|
7
12
|
import com.wix.detox.common.UIThread;
|
8
13
|
import com.wix.detox.espresso.action.common.utils.UiControllerUtils;
|
@@ -111,4 +116,10 @@ public class UiAutomatorHelper {
|
|
111
116
|
}
|
112
117
|
}
|
113
118
|
|
119
|
+
@SuppressLint({"DiscouragedApi", "InternalInsetResource"})
|
120
|
+
public static int getStatusBarHeightDps(View view) {
|
121
|
+
Context context = view.getContext();
|
122
|
+
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
123
|
+
return (int) (context.getResources().getDimensionPixelSize(resourceId) / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT));
|
124
|
+
}
|
114
125
|
}
|
@@ -120,7 +120,7 @@ class IsDisplayingAtLeastDetoxMatcher(private val areaPercentage: Int) : TypeSaf
|
|
120
120
|
.defaultDisplay
|
121
121
|
.getMetrics(m)
|
122
122
|
|
123
|
-
val statusBarHeight =
|
123
|
+
val statusBarHeight = getStatusBarHeightPixels(view)
|
124
124
|
val actionBarHeight = getActionBarHeight(view)
|
125
125
|
return Rect(0, 0, m.widthPixels, m.heightPixels - (statusBarHeight + actionBarHeight))
|
126
126
|
}
|
@@ -138,7 +138,7 @@ class IsDisplayingAtLeastDetoxMatcher(private val areaPercentage: Int) : TypeSaf
|
|
138
138
|
}
|
139
139
|
|
140
140
|
@SuppressLint("InternalInsetResource", "DiscouragedApi")
|
141
|
-
private fun
|
141
|
+
private fun getStatusBarHeightPixels(view: View): Int {
|
142
142
|
val resourceId = view.context.resources.getIdentifier("status_bar_height", "dimen", "android")
|
143
143
|
return if (resourceId > 0) view.context.resources.getDimensionPixelSize(resourceId) else 0
|
144
144
|
}
|
package/detox.d.ts
CHANGED
@@ -784,6 +784,45 @@ declare global {
|
|
784
784
|
*/
|
785
785
|
setOrientation(orientation: Orientation): Promise<void>;
|
786
786
|
|
787
|
+
/**
|
788
|
+
* Perform a tap at arbitrary coordinates on the device's screen.
|
789
|
+
* @param point Coordinates in the element's coordinate space. Optional. defaults: x: 100, y: 100
|
790
|
+
* @param shouldIgnoreStatusBar Coordinates will be measured starting from under the status bar. this param will affect only in Android tests. Optional. default: true
|
791
|
+
* @example await device.tap();
|
792
|
+
* @example await device.tap({ x: 100, y: 150 }, false);
|
793
|
+
* @example await device.tap({ x: 100, y: 150 });
|
794
|
+
* @example await device.tap(false);
|
795
|
+
*/
|
796
|
+
tap(): Promise<void>;
|
797
|
+
tap(point: Point2D): Promise<void>;
|
798
|
+
tap(point: Point2D, shouldIgnoreStatusBar: boolean): Promise<void>;
|
799
|
+
tap(shouldIgnoreStatusBar: boolean): Promise<void>;
|
800
|
+
|
801
|
+
/**
|
802
|
+
* Perform a long press at arbitrary coordinates on the device's screen. Custom press duration if needed.
|
803
|
+
* @param point Coordinates in the device's coordinate space. Optional. defaults: x: 100, y: 100
|
804
|
+
* @param duration Custom press duration time, in milliseconds. Optional (defaults to the standard long-press duration for Android and 1000 milliseconds for ios).
|
805
|
+
* Custom durations should be used cautiously, as they can affect test consistency and user experience expectations.
|
806
|
+
* They are typically necessary when testing components that behave differently from the platform's defaults or when simulating unique user interactions.
|
807
|
+
* @param shouldIgnoreStatusBar Coordinates will be measured starting from under the status bar. this param will affect only in Android tests. Optional. default: true
|
808
|
+
* @example await device.longPress();
|
809
|
+
* @example await device.longPress({ x: 100, y: 150 }, 2000, false);
|
810
|
+
* @example await device.longPress({ x: 100, y: 150 }, 2000);
|
811
|
+
* @example await device.longPress(2000, false);
|
812
|
+
* @example await device.longPress({ x: 100, y: 150 }, false);
|
813
|
+
* @example await device.longPress({ x: 100, y: 150 });
|
814
|
+
* @example await device.longPress(2000);
|
815
|
+
* @example await device.longPress(false);
|
816
|
+
*/
|
817
|
+
longPress(): Promise<void>;
|
818
|
+
longPress(point: Point2D, duration: number, shouldIgnoreStatusBar: boolean): Promise<void>;
|
819
|
+
longPress(point: Point2D, duration: number): Promise<void>;
|
820
|
+
longPress(duration: number, shouldIgnoreStatusBar: boolean): Promise<void>;
|
821
|
+
longPress(point: Point2D, shouldIgnoreStatusBar: boolean): Promise<void>;
|
822
|
+
longPress(point: Point2D): Promise<void>;
|
823
|
+
longPress(duration: number): Promise<void>;
|
824
|
+
longPress(shouldIgnoreStatusBar: boolean): Promise<void>;
|
825
|
+
|
787
826
|
/**
|
788
827
|
* Sets the simulator/emulator location to the given latitude and longitude.
|
789
828
|
*
|
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.28.0",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -71,7 +71,7 @@
|
|
71
71
|
"caf": "^15.0.1",
|
72
72
|
"chalk": "^4.0.0",
|
73
73
|
"child-process-promise": "^2.2.0",
|
74
|
-
"detox-copilot": "^0.0.
|
74
|
+
"detox-copilot": "^0.0.24",
|
75
75
|
"execa": "^5.1.1",
|
76
76
|
"find-up": "^5.0.0",
|
77
77
|
"fs-extra": "^11.0.0",
|
@@ -116,5 +116,5 @@
|
|
116
116
|
"browserslist": [
|
117
117
|
"node 14"
|
118
118
|
],
|
119
|
-
"gitHead": "
|
119
|
+
"gitHead": "c97e583d7e33ad9472d5b3e68dda724f1300c83c"
|
120
120
|
}
|
@@ -73,6 +73,89 @@ class EspressoDetox {
|
|
73
73
|
};
|
74
74
|
}
|
75
75
|
|
76
|
+
static tap(x, y, shouldIgnoreStatusBar) {
|
77
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
78
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
79
|
+
if (typeof shouldIgnoreStatusBar !== "boolean") throw new Error("shouldIgnoreStatusBar should be a boolean, but got " + (shouldIgnoreStatusBar + (" (" + (typeof shouldIgnoreStatusBar + ")"))));
|
80
|
+
return {
|
81
|
+
target: {
|
82
|
+
type: "Class",
|
83
|
+
value: "com.wix.detox.espresso.EspressoDetox"
|
84
|
+
},
|
85
|
+
method: "tap",
|
86
|
+
args: [{
|
87
|
+
type: "Integer",
|
88
|
+
value: x
|
89
|
+
}, {
|
90
|
+
type: "Integer",
|
91
|
+
value: y
|
92
|
+
}, {
|
93
|
+
type: "boolean",
|
94
|
+
value: shouldIgnoreStatusBar
|
95
|
+
}]
|
96
|
+
};
|
97
|
+
}
|
98
|
+
|
99
|
+
static longPress(x, y, shouldIgnoreStatusBar) {
|
100
|
+
function longPress3(x, y, shouldIgnoreStatusBar) {
|
101
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
102
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
103
|
+
if (typeof shouldIgnoreStatusBar !== "boolean") throw new Error("shouldIgnoreStatusBar should be a boolean, but got " + (shouldIgnoreStatusBar + (" (" + (typeof shouldIgnoreStatusBar + ")"))));
|
104
|
+
return {
|
105
|
+
target: {
|
106
|
+
type: "Class",
|
107
|
+
value: "com.wix.detox.espresso.EspressoDetox"
|
108
|
+
},
|
109
|
+
method: "longPress",
|
110
|
+
args: [{
|
111
|
+
type: "Integer",
|
112
|
+
value: x
|
113
|
+
}, {
|
114
|
+
type: "Integer",
|
115
|
+
value: y
|
116
|
+
}, {
|
117
|
+
type: "boolean",
|
118
|
+
value: shouldIgnoreStatusBar
|
119
|
+
}]
|
120
|
+
};
|
121
|
+
}
|
122
|
+
|
123
|
+
function longPress4(x, y, duration, shouldIgnoreStatusBar) {
|
124
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
125
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
126
|
+
if (typeof duration !== "number") throw new Error("duration should be a number, but got " + (duration + (" (" + (typeof duration + ")"))));
|
127
|
+
if (typeof shouldIgnoreStatusBar !== "boolean") throw new Error("shouldIgnoreStatusBar should be a boolean, but got " + (shouldIgnoreStatusBar + (" (" + (typeof shouldIgnoreStatusBar + ")"))));
|
128
|
+
return {
|
129
|
+
target: {
|
130
|
+
type: "Class",
|
131
|
+
value: "com.wix.detox.espresso.EspressoDetox"
|
132
|
+
},
|
133
|
+
method: "longPress",
|
134
|
+
args: [{
|
135
|
+
type: "Integer",
|
136
|
+
value: x
|
137
|
+
}, {
|
138
|
+
type: "Integer",
|
139
|
+
value: y
|
140
|
+
}, {
|
141
|
+
type: "Integer",
|
142
|
+
value: duration
|
143
|
+
}, {
|
144
|
+
type: "boolean",
|
145
|
+
value: shouldIgnoreStatusBar
|
146
|
+
}]
|
147
|
+
};
|
148
|
+
}
|
149
|
+
|
150
|
+
if (arguments.length === 3) {
|
151
|
+
return longPress3.apply(null, arguments);
|
152
|
+
}
|
153
|
+
|
154
|
+
if (arguments.length === 4) {
|
155
|
+
return longPress4.apply(null, arguments);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
76
159
|
}
|
77
160
|
|
78
161
|
module.exports = EspressoDetox;
|
@@ -18,7 +18,7 @@ const detoxCopilotFrameworkDriver = {
|
|
18
18
|
},
|
19
19
|
{
|
20
20
|
signature: 'by.text(text: string)',
|
21
|
-
description: 'Matches elements by their text.',
|
21
|
+
description: 'Matches elements by their text (value).',
|
22
22
|
example: "element(by.text('Login'))",
|
23
23
|
guidelines: ['Prefer test IDs over text matchers when possible.'],
|
24
24
|
},
|
@@ -34,6 +34,12 @@ const detoxCopilotFrameworkDriver = {
|
|
34
34
|
example: "element(by.id('listItem')).atIndex(2)",
|
35
35
|
guidelines: ['Use when multiple elements match the same matcher.'],
|
36
36
|
},
|
37
|
+
{
|
38
|
+
signature: 'by.label(label: string)',
|
39
|
+
description: 'Match elements with the specified label.',
|
40
|
+
example: "element(by.label('Tuesday, 1 October'));",
|
41
|
+
guidelines: ['Use when there are no other identifiers, such as for date pickers to select specific days.'],
|
42
|
+
},
|
37
43
|
],
|
38
44
|
},
|
39
45
|
{
|
@@ -106,7 +112,7 @@ const detoxCopilotFrameworkDriver = {
|
|
106
112
|
],
|
107
113
|
},
|
108
114
|
{
|
109
|
-
signature: 'waitFor(element: Matcher)
|
115
|
+
signature: 'waitFor(element: Matcher).toBeVisible(percent?: number).whileElement(element: Matcher).scroll(offset: number, direction: string)',
|
110
116
|
description: 'Continuously performs an action while waiting for an expectation to be fulfilled.',
|
111
117
|
example: `
|
112
118
|
await waitFor(element(by.text('Load More')))
|
@@ -185,9 +191,13 @@ jestExpect(attributes.text).toBe('Tap Me');`,
|
|
185
191
|
title: 'Assertions',
|
186
192
|
items: [
|
187
193
|
{
|
188
|
-
signature: 'toBeVisible()',
|
189
|
-
description: 'Asserts that the element is visible.',
|
190
|
-
example: "await expect(element(by.id('loginButton'))).toBeVisible();",
|
194
|
+
signature: 'toBeVisible(percent?: number)',
|
195
|
+
description: 'Asserts that the element is visible with at-least the specified percentage. Default percent is 75%.',
|
196
|
+
example: "await expect(element(by.id('loginButton'))).toBeVisible(38);",
|
197
|
+
guidelines: [
|
198
|
+
'Use the default visibility percent unless a different percentage is required.',
|
199
|
+
'If a percentage value is provided, use the exact percentage required for the test.',
|
200
|
+
],
|
191
201
|
},
|
192
202
|
{
|
193
203
|
signature: 'toExist()',
|
@@ -377,8 +387,8 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
|
|
377
387
|
items: [
|
378
388
|
{
|
379
389
|
signature: 'web.element(matcher: Matcher)',
|
380
|
-
description: 'Selects an element within a web view. Use when there is only one web view on the screen.',
|
381
|
-
example: `
|
390
|
+
description: 'Selects an element within a web view (`WKWebView` or `RNCWebView`). Use when there is only one web view on the screen.',
|
391
|
+
example: `
|
382
392
|
await web.element(by.web.id('email')).typeText('test@example.com');
|
383
393
|
await web.element(by.web.id('password')).typeText('password123');
|
384
394
|
await web.element(by.web.id('login-button')).tap();
|
@@ -387,19 +397,20 @@ await web.element(by.web.id('login-button')).tap();
|
|
387
397
|
'The web view may take time to load; add a delay using `await new Promise(resolve => setTimeout(resolve, milliseconds));` before the first interaction. This wait should happen only once.',
|
388
398
|
'After the initial wait, you can interact with web elements without additional delays.',
|
389
399
|
'Use `by.web.id` matcher when possible for matching web elements, as it is the most reliable.',
|
390
|
-
'Web APIs can only be used with web elements (within web views).
|
400
|
+
'Web APIs can only be used with web elements (within web views). Do not use web APIs for native elements or native APIs for web elements!',
|
401
|
+
'Confirm that you are targeting a web view before using this method.'
|
391
402
|
],
|
392
403
|
},
|
393
404
|
{
|
394
405
|
signature: 'web(nativeMatcher: NativeMatcher).element(matcher: Matcher)',
|
395
|
-
description: 'Selects an element within a specific web view matched by a native matcher. Use when there are multiple web views on the screen.',
|
406
|
+
description: 'Selects an element within a specific web view (`WKWebView` or `RNCWebView`) matched by a native matcher. Use when there are multiple web views on the screen.',
|
396
407
|
example: `
|
397
408
|
// Wait for the specific web view to appear and load (only once before interacting)
|
398
409
|
await expect(element(by.id('checkout-webview'))).toBeVisible();
|
399
410
|
|
400
411
|
// Interact with elements within a specific web view
|
401
412
|
const specificWebView = web(by.id('checkout-webview'));
|
402
|
-
|
413
|
+
|
403
414
|
await specificWebView.element(by.web.id('credit-card-number')).typeText('4111111111111111');
|
404
415
|
await specificWebView.element(by.web.id('expiration-date')).typeText('12/25');
|
405
416
|
await specificWebView.element(by.web.id('cvv')).typeText('123');
|
@@ -411,6 +422,7 @@ await specificWebView.element(by.web.id('pay-button')).tap();
|
|
411
422
|
'After the initial wait, you can interact with elements within the web view without additional delays.',
|
412
423
|
'Webview must be matched with `web(nativeMatcher)` (e.g., `web(by.id(..))` instead of `element(by.id(..))`).',
|
413
424
|
'Prefer the basic `web.element()` if only one web view is present on the screen.',
|
425
|
+
'Confirm that you are targeting a web view before using this method.'
|
414
426
|
],
|
415
427
|
},
|
416
428
|
{
|
@@ -485,8 +497,8 @@ await secondWebView.element(by.web.id('search-button')).tap();
|
|
485
497
|
example: `await web.element(by.web.label('Next')).tap();`,
|
486
498
|
guidelines: [
|
487
499
|
'Available on iOS only.',
|
488
|
-
'Use when the element has a unique label or aria-label.',
|
489
|
-
'Can be used to match buttons and input elements by their inner text content.',
|
500
|
+
'Use when the inner web element has a unique label or aria-label.',
|
501
|
+
'Can be used to match buttons and input elements inside a web view, by their inner text content.',
|
490
502
|
],
|
491
503
|
},
|
492
504
|
{
|
@@ -567,13 +579,13 @@ await web.element(by.web.id('email-input')).focus();
|
|
567
579
|
await web.element(by.web.id('email-input')).typeText('user@example.com');
|
568
580
|
`,
|
569
581
|
guidelines: [
|
570
|
-
'Useful for input fields that require focus before typing.',
|
582
|
+
'Useful for input fields in a web view that require focus before typing.',
|
571
583
|
'No need for secured interactions on iOS.',
|
572
584
|
]
|
573
585
|
},
|
574
586
|
{
|
575
587
|
signature: 'moveCursorToEnd()',
|
576
|
-
description: 'Moves the input cursor to the end of the element\'s content.',
|
588
|
+
description: 'Moves the input cursor in a web view to the end of the element\'s content.',
|
577
589
|
example: `
|
578
590
|
await web.element(by.web.id('message-box')).moveCursorToEnd();
|
579
591
|
await web.element(by.web.id('message-box')).typeText(' Adding more text.');
|
@@ -581,7 +593,7 @@ await web.element(by.web.id('message-box')).typeText(' Adding more text.');
|
|
581
593
|
},
|
582
594
|
{
|
583
595
|
signature: 'runScript(script: string, args?: any[])',
|
584
|
-
description: 'Runs a JavaScript function on the element.',
|
596
|
+
description: 'Runs a JavaScript function on the web view element.',
|
585
597
|
example: `
|
586
598
|
// Click an element using a custom script
|
587
599
|
await web.element(by.web.id('hidden-button')).runScript('el => el.click()');
|
@@ -1,6 +1,7 @@
|
|
1
1
|
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
2
2
|
const debug = require('../../utils/debug'); // debug utils, leave here even if unused
|
3
3
|
const log = require('../../utils/logger').child({ cat: 'device' });
|
4
|
+
const mapDeviceLongPressArguments = require('../../utils/mapDeviceLongPressArguments');
|
4
5
|
const traceMethods = require('../../utils/traceMethods');
|
5
6
|
const wrapWithStackTraceCutter = require('../../utils/wrapWithStackTraceCutter');
|
6
7
|
|
@@ -283,6 +284,16 @@ class RuntimeDevice {
|
|
283
284
|
await this.deviceDriver.setOrientation(orientation);
|
284
285
|
}
|
285
286
|
|
287
|
+
async tap(point, shouldIgnoreStatusBar) {
|
288
|
+
await this.deviceDriver.tap(point, shouldIgnoreStatusBar, this._bundleId);
|
289
|
+
}
|
290
|
+
|
291
|
+
async longPress(arg1, arg2, arg3) {
|
292
|
+
let { point, duration, shouldIgnoreStatusBar } = mapDeviceLongPressArguments(arg1, arg2, arg3);
|
293
|
+
|
294
|
+
await this.deviceDriver.longPress(point, duration, shouldIgnoreStatusBar, this._bundleId);
|
295
|
+
}
|
296
|
+
|
286
297
|
async setLocation(lat, lon) {
|
287
298
|
lat = String(lat);
|
288
299
|
lon = String(lon);
|
@@ -245,6 +245,22 @@ class AndroidDriver extends DeviceDriverBase {
|
|
245
245
|
await this.invocationManager.execute(call);
|
246
246
|
}
|
247
247
|
|
248
|
+
async tap(point, shouldIgnoreStatusBar) {
|
249
|
+
let x = point?.x ?? 100;
|
250
|
+
let y = point?.y ?? 100;
|
251
|
+
let _shouldIgnoreStatusBar = shouldIgnoreStatusBar ?? true;
|
252
|
+
const call = EspressoDetoxApi.tap(x, y, _shouldIgnoreStatusBar);
|
253
|
+
await this.invocationManager.execute(call);
|
254
|
+
}
|
255
|
+
|
256
|
+
async longPress(point, duration, shouldIgnoreStatusBar) {
|
257
|
+
let x = point?.x ?? 100;
|
258
|
+
let y = point?.y ?? 100;
|
259
|
+
let _shouldIgnoreStatusBar = shouldIgnoreStatusBar ?? true;
|
260
|
+
const call = duration ? EspressoDetoxApi.longPress(x, y, duration, _shouldIgnoreStatusBar): EspressoDetoxApi.longPress(x, y, _shouldIgnoreStatusBar);
|
261
|
+
await this.invocationManager.execute(call);
|
262
|
+
}
|
263
|
+
|
248
264
|
async generateViewHierarchyXml(shouldInjectTestIds) {
|
249
265
|
const hierarchy = await this.invocationManager.execute(DetoxApi.generateViewHierarchyXml(shouldInjectTestIds));
|
250
266
|
return hierarchy.result;
|
@@ -6,12 +6,17 @@ const _ = require('lodash');
|
|
6
6
|
|
7
7
|
const temporaryPath = require('../../../../artifacts/utils/temporaryPath');
|
8
8
|
const DetoxRuntimeError = require('../../../../errors/DetoxRuntimeError');
|
9
|
+
const XCUITestRunner = require('../../../../ios/XCUITestRunner');
|
10
|
+
const { assertTraceDescription } = require('../../../../utils/assertArgument');
|
9
11
|
const getAbsoluteBinaryPath = require('../../../../utils/getAbsoluteBinaryPath');
|
12
|
+
const { actionDescription } = require('../../../../utils/invocationTraceDescriptions');
|
10
13
|
const log = require('../../../../utils/logger').child({ cat: 'device' });
|
11
14
|
const pressAnyKey = require('../../../../utils/pressAnyKey');
|
15
|
+
const traceInvocationCall = require('../../../../utils/traceInvocationCall').bind(null, log);
|
12
16
|
|
13
17
|
const IosDriver = require('./IosDriver');
|
14
18
|
|
19
|
+
|
15
20
|
/**
|
16
21
|
* @typedef SimulatorDriverDeps { DeviceDriverDeps }
|
17
22
|
* @property applesimutils { AppleSimUtils }
|
@@ -40,6 +45,19 @@ class SimulatorDriver extends IosDriver {
|
|
40
45
|
this._applesimutils = deps.applesimutils;
|
41
46
|
}
|
42
47
|
|
48
|
+
withAction(xcuitestRunner, action, traceDescription, ...params) {
|
49
|
+
assertTraceDescription(traceDescription);
|
50
|
+
|
51
|
+
const invocation = {
|
52
|
+
...(params.length !== 0 && { params }),
|
53
|
+
type: 'systemAction',
|
54
|
+
...(this.index !== undefined && { systemAtIndex: this.index }),
|
55
|
+
systemAction: action
|
56
|
+
};
|
57
|
+
|
58
|
+
return traceInvocationCall(traceDescription, invocation, xcuitestRunner.execute(invocation));
|
59
|
+
}
|
60
|
+
|
43
61
|
getExternalId() {
|
44
62
|
return this.udid;
|
45
63
|
}
|
@@ -111,6 +129,23 @@ class SimulatorDriver extends IosDriver {
|
|
111
129
|
await this.emitter.emit('terminateApp', { deviceId: udid, bundleId });
|
112
130
|
}
|
113
131
|
|
132
|
+
async tap(point, shouldIgnoreStatusBar, _bundleId) {
|
133
|
+
const xcuitestRunner = new XCUITestRunner({ runtimeDevice: { id: this.getExternalId(), _bundleId } });
|
134
|
+
let x = point?.x ?? 100;
|
135
|
+
let y = point?.y ?? 100;
|
136
|
+
const traceDescription = actionDescription.tap({ x, y });
|
137
|
+
return this.withAction(xcuitestRunner, 'coordinateTap', traceDescription, x.toString(), y.toString());
|
138
|
+
}
|
139
|
+
|
140
|
+
async longPress(point, pressDuration, shouldIgnoreStatusBar, _bundleId) {
|
141
|
+
const xcuitestRunner = new XCUITestRunner({ runtimeDevice: { id: this.getExternalId(), _bundleId } });
|
142
|
+
let x = point?.x ?? 100;
|
143
|
+
let y = point?.y ?? 100;
|
144
|
+
let _pressDuration = pressDuration ? (pressDuration / 1000) : 1;
|
145
|
+
const traceDescription = actionDescription.longPress({ x, y }, _pressDuration);
|
146
|
+
return this.withAction(xcuitestRunner, 'coordinateLongPress', traceDescription, x.toString(), y.toString(), _pressDuration.toString());
|
147
|
+
}
|
148
|
+
|
114
149
|
async setBiometricEnrollment(yesOrNo) {
|
115
150
|
await this._applesimutils.setBiometricEnrollment(this.udid, yesOrNo);
|
116
151
|
}
|
@@ -52,6 +52,14 @@ function assertPoint(point) {
|
|
52
52
|
throw new DetoxRuntimeError(`point should be an object with x and y properties, but got ${JSON.stringify(point)}`);
|
53
53
|
}
|
54
54
|
|
55
|
+
function assertShouldIgnoreStatusBar(shouldIgnoreStatusBar) {
|
56
|
+
if (typeof shouldIgnoreStatusBar === 'boolean') {
|
57
|
+
return true;
|
58
|
+
}
|
59
|
+
|
60
|
+
throw new DetoxRuntimeError('shouldIgnoreStatusBar should be a boolean, but got ' + (shouldIgnoreStatusBar + (' (' + (typeof shouldIgnoreStatusBar + ')'))));
|
61
|
+
}
|
62
|
+
|
55
63
|
function assertUndefined(arg) {
|
56
64
|
if (arg === undefined) {
|
57
65
|
return true;
|
@@ -76,6 +84,7 @@ module.exports = {
|
|
76
84
|
assertString,
|
77
85
|
assertDuration,
|
78
86
|
assertPoint,
|
87
|
+
assertShouldIgnoreStatusBar,
|
79
88
|
assertUndefined,
|
80
89
|
assertTraceDescription
|
81
90
|
};
|
@@ -3,6 +3,7 @@ module.exports = {
|
|
3
3
|
adjustSliderToPosition: (newPosition) => `adjust slider to position ${newPosition}`,
|
4
4
|
clearText: () => 'clear input text',
|
5
5
|
getAttributes: () => 'get element attributes',
|
6
|
+
tap: (point) => `tap at ${JSON.stringify(point)}`,
|
6
7
|
longPress: (point, duration) => `long press${duration !== null ? ` for ${duration}ms` : ''}${point !== null ? ` at ${JSON.stringify(point)}` : ''}`,
|
7
8
|
longPressAndDrag: (duration, startX, startY, targetElement, endX, endY, speed, holdDuration) =>
|
8
9
|
`long press and drag from ${startX}, ${startY} to ${endX}, ${endY} with speed ${speed} and hold duration ${holdDuration}`,
|
@@ -0,0 +1,56 @@
|
|
1
|
+
const { DetoxRuntimeError } = require('../errors');
|
2
|
+
|
3
|
+
const { assertPoint, assertDuration, assertUndefined, assertShouldIgnoreStatusBar } = require('./assertArgument');
|
4
|
+
|
5
|
+
function mapDeviceLongPressArguments(optionalAllParams, optionalDurationOrIgnoreStatusBar, optionalIgnoreStatusBar) {
|
6
|
+
let point = null;
|
7
|
+
let duration = null;
|
8
|
+
let shouldIgnoreStatusBar = null;
|
9
|
+
|
10
|
+
try {
|
11
|
+
if (optionalAllParams === undefined) {
|
12
|
+
// Do nothing.
|
13
|
+
} else if (typeof optionalAllParams === 'number') {
|
14
|
+
duration = optionalAllParams;
|
15
|
+
if (typeof optionalDurationOrIgnoreStatusBar === 'boolean') {
|
16
|
+
shouldIgnoreStatusBar = optionalDurationOrIgnoreStatusBar;
|
17
|
+
} else {
|
18
|
+
assertUndefined(optionalDurationOrIgnoreStatusBar);
|
19
|
+
}
|
20
|
+
assertUndefined(optionalIgnoreStatusBar);
|
21
|
+
} else if (typeof optionalAllParams === 'boolean') {
|
22
|
+
shouldIgnoreStatusBar = optionalAllParams;
|
23
|
+
assertUndefined(optionalDurationOrIgnoreStatusBar);
|
24
|
+
assertUndefined(optionalIgnoreStatusBar);
|
25
|
+
} else {
|
26
|
+
assertPoint(optionalAllParams);
|
27
|
+
point = optionalAllParams;
|
28
|
+
|
29
|
+
if (typeof optionalDurationOrIgnoreStatusBar === 'number') {
|
30
|
+
assertDuration(optionalDurationOrIgnoreStatusBar);
|
31
|
+
duration = optionalDurationOrIgnoreStatusBar;
|
32
|
+
} else if (typeof optionalDurationOrIgnoreStatusBar === 'boolean') {
|
33
|
+
assertShouldIgnoreStatusBar(optionalDurationOrIgnoreStatusBar);
|
34
|
+
shouldIgnoreStatusBar = optionalDurationOrIgnoreStatusBar;
|
35
|
+
assertUndefined(optionalIgnoreStatusBar);
|
36
|
+
} else if (optionalDurationOrIgnoreStatusBar !== undefined) {
|
37
|
+
assertDuration(optionalDurationOrIgnoreStatusBar);
|
38
|
+
} else {
|
39
|
+
assertUndefined(optionalDurationOrIgnoreStatusBar);
|
40
|
+
assertUndefined(optionalIgnoreStatusBar);
|
41
|
+
}
|
42
|
+
|
43
|
+
if (optionalIgnoreStatusBar !== undefined) {
|
44
|
+
assertShouldIgnoreStatusBar(optionalIgnoreStatusBar);
|
45
|
+
shouldIgnoreStatusBar = optionalIgnoreStatusBar;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
} catch (e) {
|
49
|
+
throw new DetoxRuntimeError(`longPress accepts either a duration (number) or a point ({x: number, y: number}) as ` +
|
50
|
+
`its first argument, optionally a duration (number) as its second argument, and optionally a ignoreStatusBar (boolean) as its third argument. Error: ${e.message}`);
|
51
|
+
}
|
52
|
+
|
53
|
+
return { point, duration, shouldIgnoreStatusBar };
|
54
|
+
}
|
55
|
+
|
56
|
+
module.exports = mapDeviceLongPressArguments;
|
@@ -1 +0,0 @@
|
|
1
|
-
c517cf62a949c264ce5aa29dbe7eb0b3
|
@@ -1 +0,0 @@
|
|
1
|
-
0fd30160288562361e27f4dae15e88dd8c063321
|
@@ -1 +0,0 @@
|
|
1
|
-
43af12e399f647d3c726f03f03c6d5e9953ab473bc565018672c1dd6f9c23fa6
|
@@ -1 +0,0 @@
|
|
1
|
-
7eb38a3cfc446ee433478167eefe863d2faacfa5b2102685702d83d0b944236d3e4be9d89ad653134402872945bb122db884470d327bf99f7ecd769dacf437bc
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
cf8dd3a0b09c20f6536c73bb9b643c19
|
@@ -1 +0,0 @@
|
|
1
|
-
087bb87ec12653d348901f95966ed16f46f870b2
|
@@ -1 +0,0 @@
|
|
1
|
-
77ee8830fdf301ef8a7895575a4f0f3b76db9614b61942979b73d3b5001fac57
|
@@ -1 +0,0 @@
|
|
1
|
-
3eb1ffc33ecae7c14b6ff36a525abacb4aa05f6d05083d2dc79bad26b63badecc5d22d45bf7dc97cc90804e4245db826e14c86d86fa49540be209708a6f854d1
|
@@ -1 +0,0 @@
|
|
1
|
-
b1fa5d53cea5a7597921246ec09f437f
|
@@ -1 +0,0 @@
|
|
1
|
-
d28ba67e5c3648d25e9c592b78803d33a1805ed8
|
@@ -1 +0,0 @@
|
|
1
|
-
9563aa36da9534de48b62cdfc7ff3b14782e260a29fbbff7189a220e1d74eaf7
|
@@ -1 +0,0 @@
|
|
1
|
-
ff322f7d952260e532f7678a490b6672136925f9d77420203d6038cde5a38a2fa2af2db6fbe5ba8005fe3668074228efdca4ea8f2f3e8077fc9386ded37e1642
|
@@ -1 +0,0 @@
|
|
1
|
-
367dd3d7936f459a3d2b84a90a4d4277
|
@@ -1 +0,0 @@
|
|
1
|
-
bc18b82a4beeee1569c3cfae9ccbbd11ab133d21
|
@@ -1 +0,0 @@
|
|
1
|
-
31152c35e9eac0a236cb5d016c3200ecd5181f7639c376f02d04289a06c76930
|
@@ -1 +0,0 @@
|
|
1
|
-
7a911e94257c299c2d560fe6d84ddc2d5264bec7953e39ae64bcafbe5041e43ffbb5bffcfd6c04bcbf62e62b4b764e609e35d37d5e4903266ace32fa214a0726
|
@@ -1 +0,0 @@
|
|
1
|
-
768c2187e364924f92a9b6ccf3c7d0a2
|
@@ -1 +0,0 @@
|
|
1
|
-
7e17fc60050feb2ea5e7dc9a93bf8b2fba13486d
|
@@ -1 +0,0 @@
|
|
1
|
-
a64ce40bbbf3b827d598206f3829f34072b1d6bcd0115d930e7aabadf7477534
|
@@ -1 +0,0 @@
|
|
1
|
-
60d8f60ededcfdd91034b452971b511a40a99a5a4afb42ae6fa88261cf5d29b8493b824eb2e8f453653bf723668b417943177f02fb0dcc9d58501563e7c10b54
|
@@ -1 +0,0 @@
|
|
1
|
-
acec75d4c28b08969fcdf94aff6253d3
|
@@ -1 +0,0 @@
|
|
1
|
-
c9739dec1a97e33efb975a87083b618963b98ed7
|
@@ -1 +0,0 @@
|
|
1
|
-
652c04a47a8ffb644d3e6085070a0b7401f2cb5ab5bc09d5a7a73f21d4a9fb9d
|
@@ -1 +0,0 @@
|
|
1
|
-
913e879197e5d3622aee6c3db2444ce453912f3ab383bebae3b0fd09e518b8c301e377666a13a3359f841307e895094b5a82e6eafda83e69abd43c3f10eec484
|