detox 20.20.3 → 20.22.0-smoke.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.20.3/detox-20.20.3-sources.jar → 20.22.0-smoke.0/detox-20.22.0-smoke.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.20.3/detox-20.20.3.pom → 20.22.0-smoke.0/detox-20.22.0-smoke.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.22.0-smoke.0/detox-20.22.0-smoke.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.20.3/detox-legacy-20.20.3-sources.jar → 20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/{20.20.3/detox-legacy-20.20.3.pom → 20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.pom} +1 -1
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.22.0-smoke.0/detox-legacy-20.22.0-smoke.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/coreNative/java/com/wix/detox/actions/DetoxViewActions.kt +2 -2
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +39 -15
- package/android/detox/src/full/java/com/wix/detox/espresso/action/RNClickAction.java +13 -11
- package/android/detox/src/main/java/com/wix/detox/espresso/action/{DetoxMultiTap.kt → DetoxCustomTapper.kt} +8 -6
- package/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSingleTap.kt +1 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/action/common/DetoxViewConfiguration.kt +10 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/action/common/TapEvents.kt +12 -4
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxScrollActions.kt +3 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwipe.kt +1 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollHelper.java +2 -2
- package/android/detox/src/testFull/java/com/wix/detox/common/TapEventsSpec.kt +15 -3
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/{DetoxMultiTapSpec.kt → DetoxCustomTapperSpec.kt} +21 -11
- package/detox.d.ts +36 -22
- package/jest.config.js +1 -1
- package/package.json +3 -3
- package/src/android/actions/native.js +4 -2
- package/src/android/core/NativeElement.js +6 -3
- package/src/android/espressoapi/DetoxAction.js +105 -0
- package/src/client/Client.js +4 -0
- package/src/client/actions/actions.js +19 -0
- package/src/devices/runtime/RuntimeDevice.js +5 -0
- package/src/devices/runtime/drivers/DeviceDriverBase.js +4 -0
- package/src/devices/runtime/drivers/ios/SimulatorDriver.js +11 -0
- package/src/ios/expectTwo.js +23 -12
- package/src/utils/assertArgument.js +28 -0
- package/src/utils/invocationTraceDescriptions.js +1 -1
- package/src/utils/mapLongPressArguments.js +32 -0
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.aar +0 -0
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.20.3/detox-20.20.3.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.aar +0 -0
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.aar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.20.3/detox-legacy-20.20.3.pom.sha512 +0 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt +0 -50
- package/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt +0 -237
package/detox.d.ts
CHANGED
@@ -903,6 +903,8 @@ declare global {
|
|
903
903
|
*/
|
904
904
|
captureViewHierarchy(name?: string): Promise<string>;
|
905
905
|
|
906
|
+
getUIHierarchy(): Promise<string>;
|
907
|
+
|
906
908
|
/**
|
907
909
|
* Simulate shake (iOS Only)
|
908
910
|
*/
|
@@ -1279,15 +1281,34 @@ declare global {
|
|
1279
1281
|
* Performs the action repeatedly on the element until an expectation is met
|
1280
1282
|
* @example await waitFor(element(by.text('Item #5'))).toBeVisible().whileElement(by.id('itemsList')).scroll(50, 'down');
|
1281
1283
|
*/
|
1282
|
-
whileElement(by: NativeMatcher):
|
1284
|
+
whileElement(by: NativeMatcher): NativeElementWaitableActions & WaitFor;
|
1283
1285
|
|
1284
1286
|
// TODO: not sure about & WaitFor - check if we can chain whileElement multiple times
|
1285
1287
|
}
|
1286
1288
|
|
1287
|
-
interface
|
1289
|
+
interface NativeElementWaitableActions {
|
1290
|
+
|
1291
|
+
/**
|
1292
|
+
* Scrolls a given amount of pixels in the provided direction, starting from the provided start positions.
|
1293
|
+
* @param pixels - independent device pixels
|
1294
|
+
* @param direction - left/right/up/down
|
1295
|
+
* @param startPositionX - the X starting scroll position, in percentage; valid input: `[0.0, 1.0]`, `NaN`; default: `NaN`—choose the best value automatically
|
1296
|
+
* @param startPositionY - the Y starting scroll position, in percentage; valid input: `[0.0, 1.0]`, `NaN`; default: `NaN`—choose the best value automatically
|
1297
|
+
* @example await element(by.id('scrollView')).scroll(100, 'down', NaN, 0.85);
|
1298
|
+
* @example await element(by.id('scrollView')).scroll(100, 'up');
|
1299
|
+
*/
|
1300
|
+
scroll(
|
1301
|
+
pixels: number,
|
1302
|
+
direction: Direction,
|
1303
|
+
startPositionX?: number,
|
1304
|
+
startPositionY?: number
|
1305
|
+
): Promise<void>;
|
1306
|
+
}
|
1307
|
+
|
1308
|
+
interface NativeElementActions extends NativeElementWaitableActions{
|
1288
1309
|
/**
|
1289
1310
|
* Simulate tap on an element
|
1290
|
-
* @param point
|
1311
|
+
* @param point coordinates in the element's coordinate space. Optional (default is the center of the element).
|
1291
1312
|
* @example await element(by.id('tappable')).tap();
|
1292
1313
|
* @example await element(by.id('tappable')).tap({ x:5, y:10 });
|
1293
1314
|
*/
|
@@ -1295,10 +1316,19 @@ declare global {
|
|
1295
1316
|
|
1296
1317
|
/**
|
1297
1318
|
* Simulate long press on an element
|
1298
|
-
* @param
|
1319
|
+
* @param point coordinates in the element's coordinate space. Optional (default is the center of the element).
|
1320
|
+
* @param duration custom press duration time, in milliseconds. Optional (defaults to the standard long-press duration for the platform).
|
1321
|
+
* Custom durations should be used cautiously, as they can affect test consistency and user experience expectations.
|
1322
|
+
* They are typically necessary when testing components that behave differently from the platform's defaults or when simulating unique user interactions.
|
1299
1323
|
* @example await element(by.id('tappable')).longPress();
|
1324
|
+
* @example await element(by.id('tappable')).longPress(2000);
|
1325
|
+
* @example await element(by.id('tappable')).longPress({ x:5, y:10 });
|
1326
|
+
* @example await element(by.id('tappable')).longPress({ x:5, y:10 }, 1500);
|
1300
1327
|
*/
|
1301
|
-
longPress(
|
1328
|
+
longPress(): Promise<void>;
|
1329
|
+
longPress(point: Point2D): Promise<void>;
|
1330
|
+
longPress(duration: number): Promise<void>;
|
1331
|
+
longPress(point: Point2D, duration: number): Promise<void>;
|
1302
1332
|
|
1303
1333
|
/**
|
1304
1334
|
* Simulate long press on an element and then drag it to the position of the target element. (iOS Only)
|
@@ -1316,7 +1346,7 @@ declare global {
|
|
1316
1346
|
|
1317
1347
|
/**
|
1318
1348
|
* Simulate tap at a specific point on an element.
|
1319
|
-
* Note: The point coordinates are relative to the matched element and the element size could
|
1349
|
+
* Note: The point coordinates are relative to the matched element and the element size could change on different devices or even when changing the device font size.
|
1320
1350
|
* @example await element(by.id('tappable')).tapAtPoint({ x:5, y:10 });
|
1321
1351
|
* @deprecated Use `.tap()` instead.
|
1322
1352
|
*/
|
@@ -1352,22 +1382,6 @@ declare global {
|
|
1352
1382
|
*/
|
1353
1383
|
tapReturnKey(): Promise<void>;
|
1354
1384
|
|
1355
|
-
/**
|
1356
|
-
* Scrolls a given amount of pixels in the provided direction, starting from the provided start positions.
|
1357
|
-
* @param pixels - independent device pixels
|
1358
|
-
* @param direction - left/right/up/down
|
1359
|
-
* @param startPositionX - the X starting scroll position, in percentage; valid input: `[0.0, 1.0]`, `NaN`; default: `NaN`—choose the best value automatically
|
1360
|
-
* @param startPositionY - the Y starting scroll position, in percentage; valid input: `[0.0, 1.0]`, `NaN`; default: `NaN`—choose the best value automatically
|
1361
|
-
* @example await element(by.id('scrollView')).scroll(100, 'down', NaN, 0.85);
|
1362
|
-
* @example await element(by.id('scrollView')).scroll(100, 'up');
|
1363
|
-
*/
|
1364
|
-
scroll(
|
1365
|
-
pixels: number,
|
1366
|
-
direction: Direction,
|
1367
|
-
startPositionX?: number,
|
1368
|
-
startPositionY?: number
|
1369
|
-
): Promise<void>;
|
1370
|
-
|
1371
1385
|
/**
|
1372
1386
|
* Scroll to index.
|
1373
1387
|
* @example await element(by.id('scrollView')).scrollToIndex(10);
|
package/jest.config.js
CHANGED
@@ -4,7 +4,7 @@ const DEBUG = process.argv.includes('--reporters');
|
|
4
4
|
const jestAllure2ReporterOptions = {
|
5
5
|
testCase: {
|
6
6
|
labels: {
|
7
|
-
package: ({ filePath }) => filePath.slice(1).join('
|
7
|
+
package: ({ filePath }) => `unit.${filePath.slice(1, -1).join('.')}`,
|
8
8
|
testMethod: ({ testCase }) => testCase.fullName,
|
9
9
|
tag: ['unit'],
|
10
10
|
},
|
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.22.0-smoke.0",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -56,7 +56,7 @@
|
|
56
56
|
"eslint-plugin-node": "^11.1.0",
|
57
57
|
"eslint-plugin-unicorn": "^50.0.1",
|
58
58
|
"jest": "^29.6.3",
|
59
|
-
"jest-allure2-reporter": "^2.0.0-beta.
|
59
|
+
"jest-allure2-reporter": "^2.0.0-beta.15",
|
60
60
|
"metro-react-native-babel-preset": "0.76.8",
|
61
61
|
"prettier": "^3.1.1",
|
62
62
|
"react-native": "0.73.2",
|
@@ -115,5 +115,5 @@
|
|
115
115
|
"browserslist": [
|
116
116
|
"node 14"
|
117
117
|
],
|
118
|
-
"gitHead": "
|
118
|
+
"gitHead": "ef55a3cdc2c199fb501fa660e3f691b2565af5e2"
|
119
119
|
}
|
@@ -25,9 +25,11 @@ class TapAtPointAction extends Action {
|
|
25
25
|
}
|
26
26
|
|
27
27
|
class LongPressAction extends Action {
|
28
|
-
constructor() {
|
28
|
+
constructor(point, duration) {
|
29
29
|
super();
|
30
|
-
|
30
|
+
|
31
|
+
const filteredArgs = (point ? [point.x, point.y] : []).concat(duration ? [duration] : []);
|
32
|
+
this._call = invoke.callDirectly(DetoxActionApi.longPress(...filteredArgs));
|
31
33
|
}
|
32
34
|
}
|
33
35
|
|
@@ -7,6 +7,7 @@ const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
|
7
7
|
const invoke = require('../../invoke');
|
8
8
|
const { removeMilliseconds } = require('../../utils/dateUtils');
|
9
9
|
const { actionDescription } = require('../../utils/invocationTraceDescriptions');
|
10
|
+
const mapLongPressArguments = require('../../utils/mapLongPressArguments');
|
10
11
|
const actions = require('../actions/native');
|
11
12
|
const DetoxMatcherApi = require('../espressoapi/DetoxMatcher');
|
12
13
|
const { ActionInteraction } = require('../interactions/native');
|
@@ -42,9 +43,11 @@ class NativeElement {
|
|
42
43
|
return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
|
43
44
|
}
|
44
45
|
|
45
|
-
async longPress() {
|
46
|
-
const
|
47
|
-
|
46
|
+
async longPress(optionalPointOrDuration, optionalDuration) {
|
47
|
+
const { point, duration } = mapLongPressArguments(optionalPointOrDuration, optionalDuration);
|
48
|
+
|
49
|
+
const action = new actions.LongPressAction(point, duration);
|
50
|
+
const traceDescription = actionDescription.longPress(point, duration);
|
48
51
|
return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
|
49
52
|
}
|
50
53
|
|
@@ -68,6 +68,25 @@ class DetoxAction {
|
|
68
68
|
};
|
69
69
|
}
|
70
70
|
|
71
|
+
static createCoordinatesProvider(x, y) {
|
72
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
73
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
74
|
+
return {
|
75
|
+
target: {
|
76
|
+
type: "Class",
|
77
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
78
|
+
},
|
79
|
+
method: "createCoordinatesProvider",
|
80
|
+
args: [{
|
81
|
+
type: "Integer",
|
82
|
+
value: x
|
83
|
+
}, {
|
84
|
+
type: "Integer",
|
85
|
+
value: y
|
86
|
+
}]
|
87
|
+
};
|
88
|
+
}
|
89
|
+
|
71
90
|
static scrollToEdge(edge, startOffsetPercentX, startOffsetPercentY) {
|
72
91
|
if (typeof edge !== "string") throw new Error("edge should be a string, but got " + (edge + (" (" + (typeof edge + ")"))));
|
73
92
|
if (typeof startOffsetPercentX !== "number") throw new Error("startOffsetPercentX should be a number, but got " + (startOffsetPercentX + (" (" + (typeof startOffsetPercentX + ")"))));
|
@@ -271,6 +290,92 @@ class DetoxAction {
|
|
271
290
|
};
|
272
291
|
}
|
273
292
|
|
293
|
+
static longPress() {
|
294
|
+
function longPress0() {
|
295
|
+
return {
|
296
|
+
target: {
|
297
|
+
type: "Class",
|
298
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
299
|
+
},
|
300
|
+
method: "longPress",
|
301
|
+
args: []
|
302
|
+
};
|
303
|
+
}
|
304
|
+
|
305
|
+
function longPress1(duration) {
|
306
|
+
if (typeof duration !== "number") throw new Error("duration should be a number, but got " + (duration + (" (" + (typeof duration + ")"))));
|
307
|
+
return {
|
308
|
+
target: {
|
309
|
+
type: "Class",
|
310
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
311
|
+
},
|
312
|
+
method: "longPress",
|
313
|
+
args: [{
|
314
|
+
type: "Integer",
|
315
|
+
value: duration
|
316
|
+
}]
|
317
|
+
};
|
318
|
+
}
|
319
|
+
|
320
|
+
function longPress2(x, y) {
|
321
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
322
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
323
|
+
return {
|
324
|
+
target: {
|
325
|
+
type: "Class",
|
326
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
327
|
+
},
|
328
|
+
method: "longPress",
|
329
|
+
args: [{
|
330
|
+
type: "Integer",
|
331
|
+
value: x
|
332
|
+
}, {
|
333
|
+
type: "Integer",
|
334
|
+
value: y
|
335
|
+
}]
|
336
|
+
};
|
337
|
+
}
|
338
|
+
|
339
|
+
function longPress3(x, y, duration) {
|
340
|
+
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
|
341
|
+
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
|
342
|
+
if (typeof duration !== "number") throw new Error("duration should be a number, but got " + (duration + (" (" + (typeof duration + ")"))));
|
343
|
+
return {
|
344
|
+
target: {
|
345
|
+
type: "Class",
|
346
|
+
value: "com.wix.detox.espresso.DetoxAction"
|
347
|
+
},
|
348
|
+
method: "longPress",
|
349
|
+
args: [{
|
350
|
+
type: "Integer",
|
351
|
+
value: x
|
352
|
+
}, {
|
353
|
+
type: "Integer",
|
354
|
+
value: y
|
355
|
+
}, {
|
356
|
+
type: "Integer",
|
357
|
+
value: duration
|
358
|
+
}]
|
359
|
+
};
|
360
|
+
}
|
361
|
+
|
362
|
+
if (arguments.length === 0) {
|
363
|
+
return longPress0.apply(null, arguments);
|
364
|
+
}
|
365
|
+
|
366
|
+
if (arguments.length === 1) {
|
367
|
+
return longPress1.apply(null, arguments);
|
368
|
+
}
|
369
|
+
|
370
|
+
if (arguments.length === 2) {
|
371
|
+
return longPress2.apply(null, arguments);
|
372
|
+
}
|
373
|
+
|
374
|
+
if (arguments.length === 3) {
|
375
|
+
return longPress3.apply(null, arguments);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
274
379
|
static takeViewScreenshot() {
|
275
380
|
return {
|
276
381
|
target: {
|
package/src/client/Client.js
CHANGED
@@ -292,6 +292,24 @@ class SetInstrumentsRecordingState extends Action {
|
|
292
292
|
}
|
293
293
|
}
|
294
294
|
|
295
|
+
class GetUIHierarchy extends Action {
|
296
|
+
constructor(params) {
|
297
|
+
super('getUIHierarchy', params);
|
298
|
+
}
|
299
|
+
|
300
|
+
get isAtomic() {
|
301
|
+
return false;
|
302
|
+
}
|
303
|
+
|
304
|
+
get timeout() {
|
305
|
+
return 0;
|
306
|
+
}
|
307
|
+
|
308
|
+
async handle(response) {
|
309
|
+
throw response.params.viewHierarchy;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
|
295
313
|
class CaptureViewHierarchy extends Action {
|
296
314
|
constructor(params) {
|
297
315
|
super('captureViewHierarchy', params);
|
@@ -336,4 +354,5 @@ module.exports = {
|
|
336
354
|
SetOrientation,
|
337
355
|
SetInstrumentsRecordingState,
|
338
356
|
CaptureViewHierarchy,
|
357
|
+
GetUIHierarchy
|
339
358
|
};
|
@@ -17,6 +17,7 @@ class RuntimeDevice {
|
|
17
17
|
}, deviceDriver) {
|
18
18
|
const methodNames = [
|
19
19
|
'captureViewHierarchy',
|
20
|
+
'getUIHierarchy',
|
20
21
|
'clearKeychain',
|
21
22
|
'disableSynchronization',
|
22
23
|
'enableSynchronization',
|
@@ -195,6 +196,10 @@ class RuntimeDevice {
|
|
195
196
|
return this.deviceDriver.captureViewHierarchy(name);
|
196
197
|
}
|
197
198
|
|
199
|
+
async getUIHierarchy() {
|
200
|
+
return this.deviceDriver.getUIHierarchy();
|
201
|
+
}
|
202
|
+
|
198
203
|
async sendToHome() {
|
199
204
|
await this.deviceDriver.sendToHome();
|
200
205
|
await this.deviceDriver.waitForBackground();
|
@@ -194,6 +194,17 @@ class SimulatorDriver extends IosDriver {
|
|
194
194
|
return viewHierarchyURL;
|
195
195
|
}
|
196
196
|
|
197
|
+
async getUIHierarchy() {
|
198
|
+
try {
|
199
|
+
await this.client.getUIHierarchy();
|
200
|
+
} catch (e) {
|
201
|
+
const stringError = e.toString();
|
202
|
+
return stringError.replace('Error: ', '');
|
203
|
+
}
|
204
|
+
|
205
|
+
return 'Failed to get UI hierarchy.';
|
206
|
+
}
|
207
|
+
|
197
208
|
async setStatusBar(flags) {
|
198
209
|
await this._applesimutils.statusBarOverride(this.udid, flags);
|
199
210
|
}
|
package/src/ios/expectTwo.js
CHANGED
@@ -12,6 +12,7 @@ const { removeMilliseconds } = require('../utils/dateUtils');
|
|
12
12
|
const { actionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
|
13
13
|
const { isRegExp } = require('../utils/isRegExp');
|
14
14
|
const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
|
15
|
+
const mapLongPressArguments = require('../utils/mapLongPressArguments');
|
15
16
|
const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
|
16
17
|
|
17
18
|
const { webElement, webMatcher, webExpect, isWebElement } = require('./web');
|
@@ -155,21 +156,17 @@ class Element {
|
|
155
156
|
}
|
156
157
|
|
157
158
|
tap(point) {
|
158
|
-
|
159
|
-
if (typeof point !== 'object') throw new Error('point should be a object, but got ' + (point + (' (' + (typeof point + ')'))));
|
160
|
-
if (typeof point.x !== 'number') throw new Error('point.x should be a number, but got ' + (point.x + (' (' + (typeof point.x + ')'))));
|
161
|
-
if (typeof point.y !== 'number') throw new Error('point.y should be a number, but got ' + (point.y + (' (' + (typeof point.y + ')'))));
|
162
|
-
}
|
159
|
+
_assertValidPoint(point);
|
163
160
|
|
164
161
|
const traceDescription = actionDescription.tapAtPoint(point);
|
165
162
|
return this.withAction('tap', traceDescription, point);
|
166
163
|
}
|
167
164
|
|
168
|
-
longPress(
|
169
|
-
|
165
|
+
longPress(arg1, arg2) {
|
166
|
+
let { point, duration } = mapLongPressArguments(arg1, arg2);
|
170
167
|
|
171
|
-
const traceDescription = actionDescription.longPress(duration);
|
172
|
-
return this.withAction('longPress', traceDescription, duration);
|
168
|
+
const traceDescription = actionDescription.longPress(point, duration);
|
169
|
+
return this.withAction('longPress', traceDescription, point, duration);
|
173
170
|
}
|
174
171
|
|
175
172
|
longPressAndDrag(duration, normalizedPositionX, normalizedPositionY, targetElement,
|
@@ -595,9 +592,12 @@ class WaitFor {
|
|
595
592
|
return this.waitForWithAction(traceDescription);
|
596
593
|
}
|
597
594
|
|
598
|
-
longPress(
|
599
|
-
this.action = this.actionableElement.longPress(
|
600
|
-
|
595
|
+
longPress(arg1, arg2) {
|
596
|
+
this.action = this.actionableElement.longPress(arg1, arg2);
|
597
|
+
|
598
|
+
let { point, duration } = mapLongPressArguments(arg1, arg2);
|
599
|
+
const traceDescription = actionDescription.longPress(point, duration);
|
600
|
+
|
601
601
|
return this.waitForWithAction(traceDescription);
|
602
602
|
}
|
603
603
|
|
@@ -800,6 +800,17 @@ class IosExpect {
|
|
800
800
|
}
|
801
801
|
}
|
802
802
|
|
803
|
+
function _assertValidPoint(point) {
|
804
|
+
if (!point) {
|
805
|
+
// point is optional
|
806
|
+
return;
|
807
|
+
}
|
808
|
+
|
809
|
+
if (typeof point !== 'object') throw new Error('point should be a object, but got ' + (point + (' (' + (typeof point + ')'))));
|
810
|
+
if (typeof point.x !== 'number') throw new Error('point.x should be a number, but got ' + (point.x + (' (' + (typeof point.x + ')'))));
|
811
|
+
if (typeof point.y !== 'number') throw new Error('point.y should be a number, but got ' + (point.y + (' (' + (typeof point.y + ')'))));
|
812
|
+
}
|
813
|
+
|
803
814
|
function throwMatcherError(param) {
|
804
815
|
throw new Error(`${param} is not a Detox matcher. More about Detox matchers here: https://wix.github.io/Detox/docs/api/matchers`);
|
805
816
|
}
|
@@ -36,9 +36,37 @@ function assertEnum(allowedValues) {
|
|
36
36
|
};
|
37
37
|
}
|
38
38
|
|
39
|
+
function assertDuration(duration) {
|
40
|
+
if (typeof duration === 'number') {
|
41
|
+
return true;
|
42
|
+
}
|
43
|
+
|
44
|
+
throw new DetoxRuntimeError('duration should be a number, but got ' + (duration + (' (' + (typeof duration + ')'))));
|
45
|
+
}
|
46
|
+
|
47
|
+
function assertPoint(point) {
|
48
|
+
if (typeof point === 'object' && typeof point.x === 'number' && typeof point.y === 'number') {
|
49
|
+
return true;
|
50
|
+
}
|
51
|
+
|
52
|
+
throw new DetoxRuntimeError(`point should be an object with x and y properties, but got ${JSON.stringify(point)}`);
|
53
|
+
}
|
54
|
+
|
55
|
+
function assertUndefined(arg) {
|
56
|
+
if (arg === undefined) {
|
57
|
+
return true;
|
58
|
+
}
|
59
|
+
|
60
|
+
const [key, value] = firstEntry(arg);
|
61
|
+
throw new DetoxRuntimeError(`${key} expected to be undefined, but got ${value} (${typeof value})`);
|
62
|
+
}
|
63
|
+
|
39
64
|
module.exports = {
|
40
65
|
assertEnum,
|
41
66
|
assertNormalized,
|
42
67
|
assertNumber,
|
43
68
|
assertString,
|
69
|
+
assertDuration,
|
70
|
+
assertPoint,
|
71
|
+
assertUndefined
|
44
72
|
};
|
@@ -3,7 +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
|
-
longPress: (duration) => `long press${duration !==
|
6
|
+
longPress: (point, duration) => `long press${duration !== null ? ` for ${duration}ms` : ''}${point !== null ? ` at ${JSON.stringify(point)}` : ''}`,
|
7
7
|
longPressAndDrag: (duration, startX, startY, targetElement, endX, endY, speed, holdDuration) =>
|
8
8
|
`long press and drag from ${startX}, ${startY} to ${endX}, ${endY} with speed ${speed} and hold duration ${holdDuration}`,
|
9
9
|
multiTap: (times) => `tap ${times} times`,
|
@@ -0,0 +1,32 @@
|
|
1
|
+
const { DetoxRuntimeError } = require('../errors');
|
2
|
+
|
3
|
+
const { assertPoint, assertDuration, assertUndefined } = require('./assertArgument');
|
4
|
+
|
5
|
+
function mapLongPressArguments(optionalPointOrDuration, optionalDuration) {
|
6
|
+
let point = null;
|
7
|
+
let duration = null;
|
8
|
+
|
9
|
+
try {
|
10
|
+
if (optionalPointOrDuration === undefined) {
|
11
|
+
// Do nothing.
|
12
|
+
} else if (typeof optionalPointOrDuration === 'number') {
|
13
|
+
duration = optionalPointOrDuration;
|
14
|
+
assertUndefined(optionalDuration);
|
15
|
+
} else {
|
16
|
+
assertPoint(optionalPointOrDuration);
|
17
|
+
point = optionalPointOrDuration;
|
18
|
+
|
19
|
+
if (optionalDuration !== undefined) {
|
20
|
+
assertDuration(optionalDuration);
|
21
|
+
duration = optionalDuration;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
} catch (e) {
|
25
|
+
throw new DetoxRuntimeError(`longPress accepts either a duration (number) or a point ({x: number, y: number}) as ` +
|
26
|
+
`its first argument, and optionally a duration (number) as its second argument. Error: ${e.message}`);
|
27
|
+
}
|
28
|
+
|
29
|
+
return { point, duration };
|
30
|
+
}
|
31
|
+
|
32
|
+
module.exports = mapLongPressArguments;
|
@@ -1 +0,0 @@
|
|
1
|
-
13d47bf51e03d6d5a7efef22aa1e1d06
|
@@ -1 +0,0 @@
|
|
1
|
-
5c2641aa0a34037e687f7c9bb6e8e43f65569f01
|
@@ -1 +0,0 @@
|
|
1
|
-
3cd5b01f0afbe9d7423ca2f0dc3bf92f6ed9400e5ca3f8acd0a29836c4d4aaa0
|
@@ -1 +0,0 @@
|
|
1
|
-
a63a2e641f34deff967c967affacb6a158c91218f220649763804b8bf288082e3c70dd38fea04880f45bca7143c4c902a38ac67fdca0eb0f440bab0889b002d7
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
1f4bc018a73441d6dbe0e850c83ab48b
|
@@ -1 +0,0 @@
|
|
1
|
-
b2c1f789bca51d0b0ac695c72299a362797569ba
|
@@ -1 +0,0 @@
|
|
1
|
-
48ca834834e55c0448da811cfd22e7bb11b2edda3f1958357ad762266f9cc57e
|
@@ -1 +0,0 @@
|
|
1
|
-
de235d3a6cf3bf6a4e2030456b7229c2ebbfa8b26a6ae580bcb44037c4db0b80d617914700141efc3c1d4d3f2db48b80f8235f4e9df98869c94a3e0d059b7c3a
|
@@ -1 +0,0 @@
|
|
1
|
-
0d9b54c7887f4b8b8fae67976660ac51
|
@@ -1 +0,0 @@
|
|
1
|
-
1783b6a642fb6487d57f5cbe43df61b17e7149e9
|
@@ -1 +0,0 @@
|
|
1
|
-
1dc0921c584fbf2a6db8d71deed1f6af0258e4601a96bf518c15982c14713dce
|
@@ -1 +0,0 @@
|
|
1
|
-
ce52ad64a4521883d9cfc3c1692d29956f637ac4869815f7de554c3321cf1165968f7a640e3164fd53f46a719f54e1da86a1595a4713a05b7ae16eb36f31f716
|
@@ -1 +0,0 @@
|
|
1
|
-
1302f2351eaa020fe7cce038c423614a
|
@@ -1 +0,0 @@
|
|
1
|
-
fdbce41180eb621925063a7f6dfadf265d14defd
|
@@ -1 +0,0 @@
|
|
1
|
-
2f0924a31c4c3c4d57cd02e6c0624cf9c71bfa0992cfa1cecfcc37e254271c2f
|
@@ -1 +0,0 @@
|
|
1
|
-
7d41c5de1640feaa39488751016146815144f0ba5487edef398b388665cdfeae492705f382555f48f0ffe518622c44979f7b4e8fd4db0fa889af52cdfea3375f
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
660d4c94e1bbcc951b7fe49a3c3bf66b
|
@@ -1 +0,0 @@
|
|
1
|
-
3c6ea500a52d41f5e1a2de4a2f7b94b810f29329
|
@@ -1 +0,0 @@
|
|
1
|
-
904d4c8d7526ae784e39e77b2cd578760b460402ae2025505c40d72902d77c55
|
@@ -1 +0,0 @@
|
|
1
|
-
125a23b13aa18865ff2479545509ace8205a4c7a26461879bc6976db26463e5c8efc72e10251c99237fc800fff0e910ae9c79ffaf412dc1ef58a5d481c28aa08
|
@@ -1 +0,0 @@
|
|
1
|
-
c2b902057ff844a6f12b3630d096fa23
|
@@ -1 +0,0 @@
|
|
1
|
-
fa0734abbeb851c271812ab0234bad1535e09cc6
|
@@ -1 +0,0 @@
|
|
1
|
-
339183353fd0a651f59116482f5d3f2be0a8f78e7c11535f13e91d345670d065
|
@@ -1 +0,0 @@
|
|
1
|
-
feaf8dc8f0f594344d7973633e6ab4151a65bc48dbe4bc80f41489aad54c1c0a824ae0484428d14ef6dbebea5139ea57544d5f9d72e23ee404968e60adbed1b5
|