@limrun/appium-xcuitest-driver 10.11.0-lim.4 → 10.14.6-lim.1
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/CHANGELOG.md +94 -0
- package/build/lib/commands/active-app-info.d.ts +4 -3
- package/build/lib/commands/active-app-info.d.ts.map +1 -1
- package/build/lib/commands/active-app-info.js +2 -3
- package/build/lib/commands/active-app-info.js.map +1 -1
- package/build/lib/commands/alert.d.ts +26 -31
- package/build/lib/commands/alert.d.ts.map +1 -1
- package/build/lib/commands/alert.js +20 -29
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-management.d.ts +99 -76
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +83 -73
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/app-strings.d.ts +6 -7
- package/build/lib/commands/app-strings.d.ts.map +1 -1
- package/build/lib/commands/app-strings.js +3 -8
- package/build/lib/commands/app-strings.js.map +1 -1
- package/build/lib/commands/appearance.d.ts +7 -9
- package/build/lib/commands/appearance.d.ts.map +1 -1
- package/build/lib/commands/appearance.js +13 -19
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/audit.d.ts +5 -33
- package/build/lib/commands/audit.d.ts.map +1 -1
- package/build/lib/commands/audit.js +3 -16
- package/build/lib/commands/audit.js.map +1 -1
- package/build/lib/commands/battery.d.ts +4 -4
- package/build/lib/commands/battery.d.ts.map +1 -1
- package/build/lib/commands/battery.js +3 -7
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/biometric.d.ts +12 -14
- package/build/lib/commands/biometric.d.ts.map +1 -1
- package/build/lib/commands/biometric.js +10 -19
- package/build/lib/commands/biometric.js.map +1 -1
- package/build/lib/commands/certificate.d.ts +14 -19
- package/build/lib/commands/certificate.d.ts.map +1 -1
- package/build/lib/commands/certificate.js +24 -31
- package/build/lib/commands/certificate.js.map +1 -1
- package/build/lib/commands/clipboard.d.ts +9 -11
- package/build/lib/commands/clipboard.d.ts.map +1 -1
- package/build/lib/commands/clipboard.js +8 -13
- package/build/lib/commands/clipboard.js.map +1 -1
- package/build/lib/commands/condition.d.ts +9 -72
- package/build/lib/commands/condition.d.ts.map +1 -1
- package/build/lib/commands/condition.js +5 -66
- package/build/lib/commands/condition.js.map +1 -1
- package/build/lib/commands/content-size.d.ts +16 -19
- package/build/lib/commands/content-size.d.ts.map +1 -1
- package/build/lib/commands/content-size.js +14 -22
- package/build/lib/commands/content-size.js.map +1 -1
- package/build/lib/commands/context.d.ts +130 -161
- package/build/lib/commands/context.d.ts.map +1 -1
- package/build/lib/commands/context.js +123 -108
- package/build/lib/commands/context.js.map +1 -1
- package/build/lib/commands/device-info.d.ts +13 -0
- package/build/lib/commands/device-info.d.ts.map +1 -0
- package/build/lib/commands/device-info.js +20 -0
- package/build/lib/commands/device-info.js.map +1 -0
- package/build/lib/commands/element.d.ts +83 -67
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +111 -134
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/execute.d.ts +10 -22
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +13 -29
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-movement.d.ts +31 -42
- package/build/lib/commands/file-movement.d.ts.map +1 -1
- package/build/lib/commands/file-movement.js +146 -205
- package/build/lib/commands/file-movement.js.map +1 -1
- package/build/lib/commands/find.d.ts +20 -12
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +27 -65
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +84 -80
- package/build/lib/commands/general.d.ts.map +1 -1
- package/build/lib/commands/general.js +67 -54
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/geolocation.d.ts +16 -36
- package/build/lib/commands/geolocation.d.ts.map +1 -1
- package/build/lib/commands/geolocation.js +8 -25
- package/build/lib/commands/geolocation.js.map +1 -1
- package/build/lib/commands/gesture.d.ts +103 -119
- package/build/lib/commands/gesture.d.ts.map +1 -1
- package/build/lib/commands/gesture.js +98 -138
- package/build/lib/commands/gesture.js.map +1 -1
- package/build/lib/commands/increase-contrast.d.ts +10 -13
- package/build/lib/commands/increase-contrast.d.ts.map +1 -1
- package/build/lib/commands/increase-contrast.js +8 -16
- package/build/lib/commands/increase-contrast.js.map +1 -1
- package/build/lib/commands/iohid.d.ts +6 -1359
- package/build/lib/commands/iohid.d.ts.map +1 -1
- package/build/lib/commands/iohid.js +5 -10
- package/build/lib/commands/iohid.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +16 -13
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +14 -18
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/keychains.d.ts +2 -2
- package/build/lib/commands/keychains.d.ts.map +1 -1
- package/build/lib/commands/keychains.js +1 -4
- package/build/lib/commands/keychains.js.map +1 -1
- package/build/lib/commands/localization.d.ts +7 -6
- package/build/lib/commands/localization.d.ts.map +1 -1
- package/build/lib/commands/localization.js +7 -8
- package/build/lib/commands/localization.js.map +1 -1
- package/build/lib/commands/location.d.ts +8 -11
- package/build/lib/commands/location.d.ts.map +1 -1
- package/build/lib/commands/location.js +7 -15
- package/build/lib/commands/location.js.map +1 -1
- package/build/lib/commands/lock.d.ts +6 -10
- package/build/lib/commands/lock.d.ts.map +1 -1
- package/build/lib/commands/lock.js +3 -10
- package/build/lib/commands/lock.js.map +1 -1
- package/build/lib/commands/log.d.ts +42 -44
- package/build/lib/commands/log.d.ts.map +1 -1
- package/build/lib/commands/log.js +32 -53
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/memory.d.ts +4 -5
- package/build/lib/commands/memory.d.ts.map +1 -1
- package/build/lib/commands/memory.js +3 -8
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/navigation.d.ts +14 -26
- package/build/lib/commands/navigation.d.ts.map +1 -1
- package/build/lib/commands/navigation.js +22 -32
- package/build/lib/commands/navigation.js.map +1 -1
- package/build/lib/commands/notifications.d.ts +10 -10
- package/build/lib/commands/notifications.d.ts.map +1 -1
- package/build/lib/commands/notifications.js +8 -12
- package/build/lib/commands/notifications.js.map +1 -1
- package/build/lib/commands/pasteboard.d.ts +9 -10
- package/build/lib/commands/pasteboard.d.ts.map +1 -1
- package/build/lib/commands/pasteboard.js +8 -13
- package/build/lib/commands/pasteboard.js.map +1 -1
- package/build/lib/commands/pcap.d.ts +18 -38
- package/build/lib/commands/pcap.d.ts.map +1 -1
- package/build/lib/commands/pcap.js +9 -14
- package/build/lib/commands/pcap.js.map +1 -1
- package/build/lib/commands/performance.d.ts +36 -55
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +93 -86
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +15 -17
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +12 -18
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/proxy-helper.d.ts +11 -11
- package/build/lib/commands/proxy-helper.d.ts.map +1 -1
- package/build/lib/commands/proxy-helper.js +15 -24
- package/build/lib/commands/proxy-helper.js.map +1 -1
- package/build/lib/commands/record-audio.d.ts +25 -52
- package/build/lib/commands/record-audio.d.ts.map +1 -1
- package/build/lib/commands/record-audio.js +17 -19
- package/build/lib/commands/record-audio.js.map +1 -1
- package/build/lib/commands/recordscreen.d.ts +31 -62
- package/build/lib/commands/recordscreen.d.ts.map +1 -1
- package/build/lib/commands/recordscreen.js +29 -28
- package/build/lib/commands/recordscreen.js.map +1 -1
- package/build/lib/commands/screenshots.d.ts +15 -9
- package/build/lib/commands/screenshots.d.ts.map +1 -1
- package/build/lib/commands/screenshots.js +16 -16
- package/build/lib/commands/screenshots.js.map +1 -1
- package/build/lib/commands/simctl.d.ts +16 -22
- package/build/lib/commands/simctl.d.ts.map +1 -1
- package/build/lib/commands/simctl.js +13 -17
- package/build/lib/commands/simctl.js.map +1 -1
- package/build/lib/commands/source.d.ts +10 -8
- package/build/lib/commands/source.d.ts.map +1 -1
- package/build/lib/commands/source.js +11 -14
- package/build/lib/commands/source.js.map +1 -1
- package/build/lib/commands/timeouts.d.ts +25 -32
- package/build/lib/commands/timeouts.d.ts.map +1 -1
- package/build/lib/commands/timeouts.js +19 -15
- package/build/lib/commands/timeouts.js.map +1 -1
- package/build/lib/commands/types.d.ts +80 -0
- package/build/lib/commands/types.d.ts.map +1 -1
- package/build/lib/commands/web.d.ts +199 -202
- package/build/lib/commands/web.d.ts.map +1 -1
- package/build/lib/commands/web.js +216 -175
- package/build/lib/commands/web.js.map +1 -1
- package/build/lib/commands/xctest-record-screen.d.ts +17 -47
- package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
- package/build/lib/commands/xctest-record-screen.js +28 -59
- package/build/lib/commands/xctest-record-screen.js.map +1 -1
- package/build/lib/commands/xctest.d.ts +37 -37
- package/build/lib/commands/xctest.d.ts.map +1 -1
- package/build/lib/commands/xctest.js +38 -50
- package/build/lib/commands/xctest.js.map +1 -1
- package/build/lib/desired-caps.js +1 -1
- package/build/lib/device/log/ios-simulator-log.d.ts.map +1 -1
- package/build/lib/device/log/ios-simulator-log.js +2 -0
- package/build/lib/device/log/ios-simulator-log.js.map +1 -1
- package/build/lib/device/simulator-management.d.ts.map +1 -1
- package/build/lib/device/simulator-management.js +0 -2
- package/build/lib/device/simulator-management.js.map +1 -1
- package/build/lib/doctor/optional-checks.d.ts +0 -9
- package/build/lib/doctor/optional-checks.d.ts.map +1 -1
- package/build/lib/doctor/optional-checks.js +1 -30
- package/build/lib/doctor/optional-checks.js.map +1 -1
- package/build/lib/driver.d.ts +6 -5
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +16 -14
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts.map +1 -1
- package/build/lib/execute-method-map.js +0 -9
- package/build/lib/execute-method-map.js.map +1 -1
- package/lib/commands/active-app-info.ts +15 -0
- package/lib/commands/alert.ts +98 -0
- package/lib/commands/app-management.ts +414 -0
- package/lib/commands/{app-strings.js → app-strings.ts} +10 -9
- package/lib/commands/appearance.ts +70 -0
- package/lib/commands/audit.ts +25 -0
- package/lib/commands/{battery.js → battery.ts} +10 -12
- package/lib/commands/biometric.ts +52 -0
- package/lib/commands/{certificate.js → certificate.ts} +55 -50
- package/lib/commands/clipboard.ts +37 -0
- package/lib/commands/{condition.js → condition.ts} +21 -77
- package/lib/commands/content-size.ts +67 -0
- package/lib/commands/{context.js → context.ts} +174 -146
- package/lib/commands/device-info.ts +24 -0
- package/lib/commands/element.ts +419 -0
- package/lib/commands/{execute.js → execute.ts} +42 -38
- package/lib/commands/{file-movement.js → file-movement.ts} +212 -235
- package/lib/commands/find.ts +277 -0
- package/lib/commands/{general.js → general.ts} +102 -77
- package/lib/commands/geolocation.ts +55 -0
- package/lib/commands/{gesture.js → gesture.ts} +225 -183
- package/lib/commands/increase-contrast.ts +49 -0
- package/lib/commands/{iohid.js → iohid.ts} +15 -13
- package/lib/commands/keyboard.ts +70 -0
- package/lib/commands/keychains.ts +16 -0
- package/lib/commands/{localization.js → localization.ts} +22 -12
- package/lib/commands/{location.js → location.ts} +19 -22
- package/lib/commands/lock.ts +43 -0
- package/lib/commands/{log.js → log.ts} +68 -68
- package/lib/commands/{memory.js → memory.ts} +9 -9
- package/lib/commands/{navigation.js → navigation.ts} +42 -39
- package/lib/commands/{notifications.js → notifications.ts} +22 -14
- package/lib/commands/pasteboard.ts +44 -0
- package/lib/commands/{pcap.js → pcap.ts} +28 -28
- package/lib/commands/{performance.js → performance.ts} +133 -114
- package/lib/commands/permissions.ts +90 -0
- package/lib/commands/{proxy-helper.js → proxy-helper.ts} +26 -26
- package/lib/commands/{record-audio.js → record-audio.ts} +35 -33
- package/lib/commands/{recordscreen.js → recordscreen.ts} +78 -50
- package/lib/commands/{screenshots.js → screenshots.ts} +27 -21
- package/lib/commands/simctl.ts +82 -0
- package/lib/commands/{source.js → source.ts} +23 -20
- package/lib/commands/timeouts.ts +95 -0
- package/lib/commands/types.ts +86 -0
- package/lib/commands/{web.js → web.ts} +314 -264
- package/lib/commands/{xctest-record-screen.js → xctest-record-screen.ts} +54 -71
- package/lib/commands/{xctest.js → xctest.ts} +78 -71
- package/lib/desired-caps.ts +1 -1
- package/lib/device/log/ios-simulator-log.ts +2 -0
- package/lib/device/simulator-management.ts +0 -2
- package/lib/doctor/optional-checks.ts +0 -33
- package/lib/driver.ts +19 -17
- package/lib/execute-method-map.ts +0 -9
- package/package.json +6 -6
- package/lib/commands/active-app-info.js +0 -12
- package/lib/commands/alert.js +0 -88
- package/lib/commands/app-management.js +0 -346
- package/lib/commands/appearance.js +0 -71
- package/lib/commands/audit.js +0 -31
- package/lib/commands/biometric.js +0 -52
- package/lib/commands/clipboard.js +0 -35
- package/lib/commands/content-size.js +0 -68
- package/lib/commands/deviceInfo.js +0 -27
- package/lib/commands/element.js +0 -423
- package/lib/commands/find.js +0 -205
- package/lib/commands/geolocation.js +0 -56
- package/lib/commands/increase-contrast.js +0 -50
- package/lib/commands/keyboard.js +0 -62
- package/lib/commands/keychains.js +0 -17
- package/lib/commands/lock.js +0 -46
- package/lib/commands/pasteboard.js +0 -43
- package/lib/commands/permissions.js +0 -85
- package/lib/commands/simctl.js +0 -71
- package/lib/commands/timeouts.js +0 -68
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import {errors} from 'appium/driver';
|
|
3
|
+
import {util} from 'appium/support';
|
|
4
|
+
import type {Element, Position, Size, Rect} from '@appium/types';
|
|
5
|
+
import type {XCUITestDriver} from '../driver';
|
|
6
|
+
import type {AtomsElement} from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks whether an element is displayed.
|
|
10
|
+
*
|
|
11
|
+
* @param el - Element or element ID
|
|
12
|
+
*/
|
|
13
|
+
export async function elementDisplayed(this: XCUITestDriver, el: Element | string): Promise<boolean> {
|
|
14
|
+
const elementId = util.unwrapElement(el);
|
|
15
|
+
if (this.isWebContext()) {
|
|
16
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
17
|
+
return await this.executeAtom('is_displayed', [atomsElement]) as boolean;
|
|
18
|
+
}
|
|
19
|
+
return await this.proxyCommand(`/element/${elementId}/displayed`, 'GET') as boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Checks whether an element is enabled.
|
|
24
|
+
*
|
|
25
|
+
* @param el - Element or element ID
|
|
26
|
+
*/
|
|
27
|
+
export async function elementEnabled(this: XCUITestDriver, el: Element | string): Promise<boolean> {
|
|
28
|
+
const elementId = util.unwrapElement(el);
|
|
29
|
+
if (this.isWebContext()) {
|
|
30
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
31
|
+
return await this.executeAtom('is_enabled', [atomsElement]) as boolean;
|
|
32
|
+
}
|
|
33
|
+
return await this.proxyCommand(`/element/${elementId}/enabled`, 'GET') as boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Checks whether an element is selected.
|
|
38
|
+
*
|
|
39
|
+
* @param el - Element or element ID
|
|
40
|
+
*/
|
|
41
|
+
export async function elementSelected(this: XCUITestDriver, el: Element | string): Promise<boolean> {
|
|
42
|
+
const elementId = util.unwrapElement(el);
|
|
43
|
+
if (this.isWebContext()) {
|
|
44
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
45
|
+
return await this.executeAtom('is_selected', [atomsElement]) as boolean;
|
|
46
|
+
}
|
|
47
|
+
return await this.proxyCommand(`/element/${elementId}/selected`, 'GET') as boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Gets the tag/name of an element.
|
|
52
|
+
*
|
|
53
|
+
* @param el - Element or element ID
|
|
54
|
+
*/
|
|
55
|
+
export async function getName(this: XCUITestDriver, el: Element | string): Promise<string> {
|
|
56
|
+
const elementId = util.unwrapElement(el);
|
|
57
|
+
if (this.isWebContext()) {
|
|
58
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
59
|
+
const script = 'return arguments[0].tagName.toLowerCase()';
|
|
60
|
+
return await this.executeAtom('execute_script', [script, [atomsElement]]) as string;
|
|
61
|
+
}
|
|
62
|
+
return await this.proxyCommand(`/element/${elementId}/name`, 'GET') as string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Gets a native attribute (non-web) from an element.
|
|
67
|
+
*
|
|
68
|
+
* @param attribute - Attribute name
|
|
69
|
+
* @param el - Element or element ID
|
|
70
|
+
*/
|
|
71
|
+
export async function getNativeAttribute(
|
|
72
|
+
this: XCUITestDriver,
|
|
73
|
+
attribute: string,
|
|
74
|
+
el: Element | string,
|
|
75
|
+
): Promise<string | null> {
|
|
76
|
+
if (attribute === 'contentSize') {
|
|
77
|
+
return await this.getContentSize(el);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const elementId = util.unwrapElement(el);
|
|
81
|
+
let value = await this.proxyCommand(`/element/${elementId}/attribute/${attribute}`, 'GET') as
|
|
82
|
+
| string
|
|
83
|
+
| number
|
|
84
|
+
| null
|
|
85
|
+
| undefined
|
|
86
|
+
| boolean;
|
|
87
|
+
if ([0, 1].includes(value as number)) {
|
|
88
|
+
value = !!value;
|
|
89
|
+
}
|
|
90
|
+
return _.isNull(value) || _.isString(value) ? value : JSON.stringify(value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Gets an element attribute (web or native).
|
|
95
|
+
*
|
|
96
|
+
* @param attribute - Attribute name
|
|
97
|
+
* @param el - Element or element ID
|
|
98
|
+
*/
|
|
99
|
+
export async function getAttribute(
|
|
100
|
+
this: XCUITestDriver,
|
|
101
|
+
attribute: string,
|
|
102
|
+
el: Element | string,
|
|
103
|
+
): Promise<string | null> {
|
|
104
|
+
const elementId = util.unwrapElement(el);
|
|
105
|
+
if (!this.isWebContext()) {
|
|
106
|
+
return await this.getNativeAttribute(attribute, elementId);
|
|
107
|
+
}
|
|
108
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
109
|
+
return await this.executeAtom('get_attribute_value', [atomsElement, attribute]) as string | null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Gets an element property (web) or native attribute fallback.
|
|
114
|
+
*
|
|
115
|
+
* @param property - Property name
|
|
116
|
+
* @param el - Element or element ID
|
|
117
|
+
*/
|
|
118
|
+
export async function getProperty(
|
|
119
|
+
this: XCUITestDriver,
|
|
120
|
+
property: string,
|
|
121
|
+
el: Element | string,
|
|
122
|
+
): Promise<string | null> {
|
|
123
|
+
const elementId = util.unwrapElement(el);
|
|
124
|
+
if (!this.isWebContext()) {
|
|
125
|
+
return await this.getNativeAttribute(property, elementId);
|
|
126
|
+
}
|
|
127
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
128
|
+
return await this.executeAtom('get_attribute_value', [atomsElement, property]) as string | null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Gets the text content of an element.
|
|
133
|
+
*
|
|
134
|
+
* @param el - Element or element ID
|
|
135
|
+
*/
|
|
136
|
+
export async function getText(this: XCUITestDriver, el: Element | string): Promise<string> {
|
|
137
|
+
const elementId = util.unwrapElement(el);
|
|
138
|
+
if (!this.isWebContext()) {
|
|
139
|
+
return await this.proxyCommand(`/element/${elementId}/text`, 'GET') as string;
|
|
140
|
+
}
|
|
141
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
142
|
+
return await this.executeAtom('get_text', [atomsElement]) as string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Gets the bounding rect of an element.
|
|
147
|
+
*
|
|
148
|
+
* @param el - Element or element ID
|
|
149
|
+
*/
|
|
150
|
+
export async function getElementRect(this: XCUITestDriver, el: Element | string): Promise<Rect> {
|
|
151
|
+
if (this.isWebContext()) {
|
|
152
|
+
const {x, y} = await this.getLocation(el);
|
|
153
|
+
const {width, height} = await this.getSize(el);
|
|
154
|
+
return {x, y, width, height};
|
|
155
|
+
}
|
|
156
|
+
const elementId = util.unwrapElement(el);
|
|
157
|
+
return await this.getNativeRect(elementId);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Gets the top-left location of an element.
|
|
162
|
+
*
|
|
163
|
+
* @param elementId - Element or element ID
|
|
164
|
+
*/
|
|
165
|
+
export async function getLocation(this: XCUITestDriver, elementId: Element | string): Promise<Position> {
|
|
166
|
+
const el = util.unwrapElement(elementId);
|
|
167
|
+
if (this.isWebContext()) {
|
|
168
|
+
const atomsElement = this.getAtomsElement(el);
|
|
169
|
+
const loc = await this.executeAtom('get_top_left_coordinates', [atomsElement]) as Position;
|
|
170
|
+
if (this.opts.absoluteWebLocations) {
|
|
171
|
+
const script =
|
|
172
|
+
'return [' +
|
|
173
|
+
'Math.max(window.pageXOffset,document.documentElement.scrollLeft,document.body.scrollLeft),' +
|
|
174
|
+
'Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop)];';
|
|
175
|
+
const [xOffset, yOffset] = await this.execute(script) as [number, number];
|
|
176
|
+
loc.x += xOffset;
|
|
177
|
+
loc.y += yOffset;
|
|
178
|
+
}
|
|
179
|
+
return loc;
|
|
180
|
+
}
|
|
181
|
+
const rect = await this.getElementRect(el);
|
|
182
|
+
return {x: rect.x, y: rect.y};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Alias for getLocation.
|
|
187
|
+
*
|
|
188
|
+
* @param elementId - Element or element ID
|
|
189
|
+
*/
|
|
190
|
+
export async function getLocationInView(this: XCUITestDriver, elementId: Element | string): Promise<Position> {
|
|
191
|
+
return await this.getLocation(elementId);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Gets the size of an element.
|
|
196
|
+
*
|
|
197
|
+
* @param el - Element or element ID
|
|
198
|
+
*/
|
|
199
|
+
export async function getSize(this: XCUITestDriver, el: Element | string): Promise<Size> {
|
|
200
|
+
const elementId = util.unwrapElement(el);
|
|
201
|
+
if (this.isWebContext()) {
|
|
202
|
+
return await this.executeAtom('get_size', [this.getAtomsElement(elementId)]) as Size;
|
|
203
|
+
}
|
|
204
|
+
const rect = await this.getElementRect(elementId);
|
|
205
|
+
return {width: rect.width, height: rect.height};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Legacy alias for setValue; always types via keyboard.
|
|
210
|
+
*
|
|
211
|
+
* @param value - Value to set
|
|
212
|
+
* @param el - Element or element ID
|
|
213
|
+
*/
|
|
214
|
+
export async function setValueImmediate(
|
|
215
|
+
this: XCUITestDriver,
|
|
216
|
+
value: string | string[] | number,
|
|
217
|
+
el: Element | string,
|
|
218
|
+
): Promise<void> {
|
|
219
|
+
this.log.info(
|
|
220
|
+
'There is currently no way to bypass typing using XCUITest. Setting value through keyboard',
|
|
221
|
+
);
|
|
222
|
+
await this.setValue(value, el);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Sets an element value (native or web).
|
|
227
|
+
*
|
|
228
|
+
* @param value - Value to set
|
|
229
|
+
* @param el - Element or element ID
|
|
230
|
+
*/
|
|
231
|
+
export async function setValue(
|
|
232
|
+
this: XCUITestDriver,
|
|
233
|
+
value: string | string[] | number,
|
|
234
|
+
el: Element | string,
|
|
235
|
+
): Promise<void> {
|
|
236
|
+
const elementId = util.unwrapElement(el);
|
|
237
|
+
if (!this.isWebContext()) {
|
|
238
|
+
await this.proxyCommand(`/element/${elementId}/value`, 'POST', {
|
|
239
|
+
value: prepareInputValue(value),
|
|
240
|
+
});
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
245
|
+
await this.executeAtom('click', [atomsElement]);
|
|
246
|
+
|
|
247
|
+
if (this.opts.sendKeyStrategy !== 'oneByOne') {
|
|
248
|
+
await this.setValueWithWebAtom(atomsElement, value);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
for (const char of prepareInputValue(value)) {
|
|
252
|
+
await this.setValueWithWebAtom(atomsElement, char);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Types text into a web element using atoms.
|
|
258
|
+
*
|
|
259
|
+
* @param atomsElement - Target atoms element
|
|
260
|
+
* @param value - Text to type
|
|
261
|
+
*/
|
|
262
|
+
export async function setValueWithWebAtom(
|
|
263
|
+
this: XCUITestDriver,
|
|
264
|
+
atomsElement: AtomsElement<string>,
|
|
265
|
+
value: string | string[] | number,
|
|
266
|
+
): Promise<void> {
|
|
267
|
+
await this.executeAtom('type', [atomsElement, value]);
|
|
268
|
+
|
|
269
|
+
if (this.opts.skipTriggerInputEventAfterSendkeys) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function triggerInputEvent(input: EventTarget & {_valueTracker?: any}) {
|
|
274
|
+
const lastValue = '';
|
|
275
|
+
const event = new Event('input', {bubbles: true});
|
|
276
|
+
const tracker = input._valueTracker;
|
|
277
|
+
if (tracker) {
|
|
278
|
+
tracker.setValue(lastValue);
|
|
279
|
+
}
|
|
280
|
+
input.dispatchEvent(event);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const scriptAsString = `return (${triggerInputEvent}).apply(null, arguments)`;
|
|
284
|
+
await this.executeAtom('execute_script', [scriptAsString, [atomsElement]]);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Sends raw key sequences via WDA.
|
|
289
|
+
*
|
|
290
|
+
* @param value - Keys to send
|
|
291
|
+
*/
|
|
292
|
+
export async function keys(this: XCUITestDriver, value: string[] | string | number): Promise<void> {
|
|
293
|
+
await this.proxyCommand('/wda/keys', 'POST', {
|
|
294
|
+
value: prepareInputValue(value),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Clears the contents of an element.
|
|
300
|
+
*
|
|
301
|
+
* @param el - Element or element ID
|
|
302
|
+
*/
|
|
303
|
+
export async function clear(this: XCUITestDriver, el: Element | string): Promise<void> {
|
|
304
|
+
const elementId = util.unwrapElement(el);
|
|
305
|
+
if (this.isWebContext()) {
|
|
306
|
+
const atomsElement = this.getAtomsElement(elementId);
|
|
307
|
+
await this.executeAtom('clear', [atomsElement]);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
await this.proxyCommand(`/element/${elementId}/clear`, 'POST');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Gets content size for table/collection views (native only).
|
|
315
|
+
*
|
|
316
|
+
* @param el - Element or element ID
|
|
317
|
+
*/
|
|
318
|
+
export async function getContentSize(this: XCUITestDriver, el: Element | string): Promise<string> {
|
|
319
|
+
if (this.isWebContext()) {
|
|
320
|
+
throw new errors.NotYetImplementedError(
|
|
321
|
+
'Support for getContentSize for web context is not yet implemented. Please contact an Appium dev',
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const type = await this.getAttribute('type', el);
|
|
326
|
+
|
|
327
|
+
if (type !== 'XCUIElementTypeTable' && type !== 'XCUIElementTypeCollectionView') {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Can't get content size for type '${type}', only for tables and collection views`,
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
let locator = '*';
|
|
333
|
+
if (type === 'XCUIElementTypeTable') {
|
|
334
|
+
locator = 'XCUIElementTypeCell';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
let contentHeight = 0;
|
|
338
|
+
const children = await this.findElOrEls('class chain', locator, true, el);
|
|
339
|
+
if (children.length === 1) {
|
|
340
|
+
const rect = await this.getElementRect(children[0]);
|
|
341
|
+
contentHeight = rect.height;
|
|
342
|
+
} else if (children.length) {
|
|
343
|
+
switch (type) {
|
|
344
|
+
case 'XCUIElementTypeTable': {
|
|
345
|
+
const firstRect = await this.getElementRect(_.head(children) as Element);
|
|
346
|
+
const lastRect = await this.getElementRect(_.last(children) as Element);
|
|
347
|
+
contentHeight = lastRect.y + lastRect.height - firstRect.y;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 'XCUIElementTypeCollectionView': {
|
|
351
|
+
let elsInRow = 1;
|
|
352
|
+
const firstRect = await this.getElementRect(_.head(children) as Element);
|
|
353
|
+
const initialRects = [firstRect];
|
|
354
|
+
for (let i = 1; i < children.length; i++) {
|
|
355
|
+
const rect = await this.getElementRect(children[i] as Element);
|
|
356
|
+
initialRects.push(rect);
|
|
357
|
+
if (rect.y !== firstRect.y) {
|
|
358
|
+
elsInRow = i;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const spaceBetweenEls =
|
|
363
|
+
initialRects[elsInRow].y -
|
|
364
|
+
initialRects[elsInRow - 1].y -
|
|
365
|
+
initialRects[elsInRow - 1].height;
|
|
366
|
+
const numRows = Math.ceil(children.length / elsInRow);
|
|
367
|
+
contentHeight = numRows * firstRect.height + spaceBetweenEls * (numRows - 1);
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
default:
|
|
371
|
+
throw new Error(
|
|
372
|
+
`Programming error: type '${type}' was not valid but should have already been rejected`,
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const size = await this.getSize(el);
|
|
377
|
+
const origin = await this.getLocationInView(el);
|
|
378
|
+
return JSON.stringify({
|
|
379
|
+
width: size.width,
|
|
380
|
+
height: size.height,
|
|
381
|
+
top: origin.y,
|
|
382
|
+
left: origin.x,
|
|
383
|
+
scrollableOffset: contentHeight,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Gets the native rect of an element (no web fallback).
|
|
389
|
+
*
|
|
390
|
+
* @param el - Element or element ID
|
|
391
|
+
*/
|
|
392
|
+
export async function getNativeRect(this: XCUITestDriver, el: Element | string): Promise<Rect> {
|
|
393
|
+
const elementId = util.unwrapElement(el);
|
|
394
|
+
return await this.proxyCommand(`/element/${elementId}/rect`, 'GET') as Rect;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function prepareInputValue(inp: string | string[] | number): string[] {
|
|
398
|
+
if (![_.isArray, _.isString, _.isFinite].some((f) => f(inp))) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
`Only strings, numbers and arrays are supported as input arguments. ` +
|
|
401
|
+
`Received: ${JSON.stringify(inp)}`,
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (_.isArray(inp)) {
|
|
406
|
+
inp = inp.join('');
|
|
407
|
+
} else if (_.isFinite(inp)) {
|
|
408
|
+
inp = `${inp}`;
|
|
409
|
+
}
|
|
410
|
+
return [...String(inp)].map((k) => {
|
|
411
|
+
if (['\uE006', '\uE007'].includes(k)) {
|
|
412
|
+
return '\n';
|
|
413
|
+
}
|
|
414
|
+
if (['\uE003', '\ue017'].includes(k)) {
|
|
415
|
+
return '\b';
|
|
416
|
+
}
|
|
417
|
+
return k;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
@@ -2,14 +2,18 @@ import _ from 'lodash';
|
|
|
2
2
|
import {XCUITestDriver} from '../driver';
|
|
3
3
|
import {errors, errorFromCode, errorFromW3CJsonCode} from 'appium/driver';
|
|
4
4
|
import {util} from 'appium/support';
|
|
5
|
+
import type {Element, StringRecord} from '@appium/types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Collect the response of an async script execution
|
|
8
|
-
* @this {XCUITestDriver}
|
|
9
9
|
* @deprecated
|
|
10
10
|
* @privateRemarks It's unclear what this is for. Don't use it.
|
|
11
11
|
*/
|
|
12
|
-
export async function receiveAsyncResponse(
|
|
12
|
+
export async function receiveAsyncResponse(
|
|
13
|
+
this: XCUITestDriver,
|
|
14
|
+
status: number | null | undefined,
|
|
15
|
+
value: any,
|
|
16
|
+
): Promise<void> {
|
|
13
17
|
this.log.debug(`Received async response: ${JSON.stringify(value)}`);
|
|
14
18
|
if (!util.hasValue(this.asyncPromise)) {
|
|
15
19
|
this.log.warn(
|
|
@@ -33,21 +37,22 @@ export async function receiveAsyncResponse(status, value) {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
|
-
* @template
|
|
37
|
-
* @
|
|
38
|
-
* @param
|
|
39
|
-
* @param {TArgs} [args]
|
|
40
|
-
* @this {XCUITestDriver}
|
|
41
|
-
* @returns {Promise<TReturn>}
|
|
40
|
+
* @template TReturn
|
|
41
|
+
* @param script - Either a script to run, or in the case of an Execute Method, the name of the script to execute.
|
|
42
|
+
* @param args
|
|
42
43
|
*/
|
|
43
|
-
export async function execute
|
|
44
|
+
export async function execute<TReturn = unknown>(
|
|
45
|
+
this: XCUITestDriver,
|
|
46
|
+
script: string,
|
|
47
|
+
args?: ExecuteMethodArgs,
|
|
48
|
+
): Promise<TReturn> {
|
|
44
49
|
// TODO: create a type that converts args to the parameters of the associated method using the `command` prop of `executeMethodMap`
|
|
45
50
|
script = script.trim().replace(/^mobile:\s*/, 'mobile: ');
|
|
46
51
|
if (isExecuteMethod(script)) {
|
|
47
|
-
const executeMethodArgs = preprocessExecuteMethodArgs(script, args);
|
|
52
|
+
const executeMethodArgs = preprocessExecuteMethodArgs(script, args as ExecuteMethodArgs | undefined);
|
|
48
53
|
return await this.executeMethod(script, [executeMethodArgs]);
|
|
49
54
|
} else if (this.isWebContext()) {
|
|
50
|
-
const atomsArgs = this.convertElementsForAtoms(
|
|
55
|
+
const atomsArgs = this.convertElementsForAtoms(args as readonly any[] | undefined);
|
|
51
56
|
const result = await this.executeAtom('execute_script', [script, atomsArgs]);
|
|
52
57
|
return this.cacheWebElements(result);
|
|
53
58
|
} else {
|
|
@@ -56,17 +61,20 @@ export async function execute(script, args) {
|
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
/**
|
|
59
|
-
* @this {XCUITestDriver}
|
|
60
64
|
* @group Mobile Web Only
|
|
61
65
|
*/
|
|
62
|
-
export async function executeAsync(
|
|
66
|
+
export async function executeAsync(
|
|
67
|
+
this: XCUITestDriver,
|
|
68
|
+
script: string,
|
|
69
|
+
args?: readonly any[],
|
|
70
|
+
): Promise<any> {
|
|
63
71
|
if (!this.isWebContext()) {
|
|
64
72
|
throw new errors.NotImplementedError();
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
args = this.convertElementsForAtoms(args);
|
|
68
76
|
this.asyncWaitMs = this.asyncWaitMs || 0;
|
|
69
|
-
const promise =
|
|
77
|
+
const promise = this.remote.executeAtomAsync(
|
|
70
78
|
'execute_async_script',
|
|
71
79
|
[script, args, this.asyncWaitMs],
|
|
72
80
|
this.curWebFrames,
|
|
@@ -77,16 +85,17 @@ export async function executeAsync(script, args) {
|
|
|
77
85
|
|
|
78
86
|
/**
|
|
79
87
|
* Checks if script expects a particular parameter (either optional or required).
|
|
80
|
-
* @template
|
|
81
|
-
* @param
|
|
82
|
-
* @param
|
|
88
|
+
* @template Script
|
|
89
|
+
* @param script - Script name
|
|
90
|
+
* @param param - Parameter name
|
|
83
91
|
* @returns {boolean}
|
|
84
92
|
*/
|
|
85
|
-
function executeMethodExpectsParam
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
let
|
|
93
|
+
function executeMethodExpectsParam<Script extends keyof typeof XCUITestDriver.executeMethodMap>(
|
|
94
|
+
script: Script,
|
|
95
|
+
param: string,
|
|
96
|
+
): boolean {
|
|
97
|
+
let required: ReadonlyArray<string> | undefined;
|
|
98
|
+
let optional: ReadonlyArray<string> | undefined;
|
|
90
99
|
const execMethodDef = XCUITestDriver.executeMethodMap[script];
|
|
91
100
|
if ('params' in execMethodDef) {
|
|
92
101
|
if ('required' in execMethodDef.params) {
|
|
@@ -101,24 +110,26 @@ function executeMethodExpectsParam(script, param) {
|
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
/**
|
|
104
|
-
* @param
|
|
113
|
+
* @param script
|
|
105
114
|
* @returns {script is keyof XCUITestDriver.executeMethodMap}
|
|
106
115
|
*/
|
|
107
|
-
function isExecuteMethod(script) {
|
|
116
|
+
function isExecuteMethod(script: string): script is keyof typeof XCUITestDriver.executeMethodMap {
|
|
108
117
|
return script in XCUITestDriver.executeMethodMap;
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
/**
|
|
112
121
|
* Massages the arguments going into an execute method.
|
|
113
|
-
* @param
|
|
114
|
-
* @param
|
|
115
|
-
* @returns {StringRecord<unknown>}
|
|
122
|
+
* @param script
|
|
123
|
+
* @param args
|
|
116
124
|
*/
|
|
117
|
-
function preprocessExecuteMethodArgs(
|
|
125
|
+
function preprocessExecuteMethodArgs(
|
|
126
|
+
script: keyof typeof XCUITestDriver.executeMethodMap,
|
|
127
|
+
args?: ExecuteMethodArgs,
|
|
128
|
+
): StringRecord<unknown> {
|
|
118
129
|
if (_.isArray(args)) {
|
|
119
130
|
args = _.first(args);
|
|
120
131
|
}
|
|
121
|
-
const executeMethodArgs =
|
|
132
|
+
const executeMethodArgs = (args ?? {}) as StringRecord<unknown>;
|
|
122
133
|
/**
|
|
123
134
|
* Renames the deprecated `element` key to `elementId`. Historically,
|
|
124
135
|
* all of the pre-Execute-Method-Map execute methods accepted an `element` _or_ and `elementId` param.
|
|
@@ -136,18 +147,11 @@ function preprocessExecuteMethodArgs(script, args) {
|
|
|
136
147
|
*/
|
|
137
148
|
if ('elementId' in executeMethodArgs && executeMethodExpectsParam(script, 'elementId')) {
|
|
138
149
|
executeMethodArgs.elementId = util.unwrapElement(
|
|
139
|
-
|
|
150
|
+
executeMethodArgs.elementId as Element<string> | string,
|
|
140
151
|
);
|
|
141
152
|
}
|
|
142
153
|
|
|
143
154
|
return executeMethodArgs;
|
|
144
155
|
}
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
* @template [T=any]
|
|
148
|
-
* @typedef {import('@appium/types').StringRecord<T>} StringRecord
|
|
149
|
-
*/
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @typedef {readonly any[] | readonly [StringRecord] | Readonly<StringRecord>} ExecuteMethodArgs
|
|
153
|
-
*/
|
|
157
|
+
type ExecuteMethodArgs = readonly any[] | readonly [StringRecord<unknown>] | Readonly<StringRecord<unknown>>;
|