appium-xcuitest-driver 10.3.0 → 10.4.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 +12 -0
- package/build/lib/commands/active-app-info.d.ts +9 -0
- package/build/lib/commands/active-app-info.d.ts.map +1 -0
- package/build/lib/commands/active-app-info.js +14 -0
- package/build/lib/commands/active-app-info.js.map +1 -0
- package/build/lib/commands/alert.d.ts +42 -45
- package/build/lib/commands/alert.d.ts.map +1 -1
- package/build/lib/commands/alert.js +66 -62
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-management.d.ts +150 -153
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +300 -286
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/app-strings.d.ts +14 -17
- package/build/lib/commands/app-strings.d.ts.map +1 -1
- package/build/lib/commands/app-strings.js +23 -24
- package/build/lib/commands/app-strings.js.map +1 -1
- package/build/lib/commands/appearance.d.ts +19 -22
- package/build/lib/commands/appearance.d.ts.map +1 -1
- package/build/lib/commands/appearance.js +56 -56
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/audit.d.ts +22 -17
- package/build/lib/commands/audit.d.ts.map +1 -1
- package/build/lib/commands/audit.js +17 -18
- package/build/lib/commands/audit.js.map +1 -1
- package/build/lib/commands/battery.d.ts +11 -14
- package/build/lib/commands/battery.d.ts.map +1 -1
- package/build/lib/commands/battery.js +36 -37
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/biometric.d.ts +30 -33
- package/build/lib/commands/biometric.d.ts.map +1 -1
- package/build/lib/commands/biometric.js +42 -41
- package/build/lib/commands/biometric.js.map +1 -1
- package/build/lib/commands/certificate.d.ts +48 -45
- package/build/lib/commands/certificate.d.ts.map +1 -1
- package/build/lib/commands/certificate.js +218 -205
- package/build/lib/commands/certificate.js.map +1 -1
- package/build/lib/commands/clipboard.d.ts +19 -22
- package/build/lib/commands/clipboard.d.ts.map +1 -1
- package/build/lib/commands/clipboard.js +30 -30
- package/build/lib/commands/clipboard.js.map +1 -1
- package/build/lib/commands/condition.d.ts +49 -26
- package/build/lib/commands/condition.d.ts.map +1 -1
- package/build/lib/commands/condition.js +87 -86
- package/build/lib/commands/condition.js.map +1 -1
- package/build/lib/commands/content-size.d.ts +26 -29
- package/build/lib/commands/content-size.d.ts.map +1 -1
- package/build/lib/commands/content-size.js +36 -36
- package/build/lib/commands/content-size.js.map +1 -1
- package/build/lib/commands/context.d.ts +161 -108
- package/build/lib/commands/context.d.ts.map +1 -1
- package/build/lib/commands/context.js +530 -517
- package/build/lib/commands/context.js.map +1 -1
- package/build/lib/commands/deviceInfo.d.ts +9 -12
- package/build/lib/commands/deviceInfo.d.ts.map +1 -1
- package/build/lib/commands/deviceInfo.js +17 -18
- package/build/lib/commands/deviceInfo.js.map +1 -1
- package/build/lib/commands/element.d.ts +102 -105
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +337 -323
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/execute.d.ts +24 -19
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +63 -62
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-movement.d.ts +77 -80
- package/build/lib/commands/file-movement.d.ts.map +1 -1
- package/build/lib/commands/file-movement.js +130 -124
- package/build/lib/commands/file-movement.js.map +1 -1
- package/build/lib/commands/find.d.ts +18 -21
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +158 -156
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +124 -116
- package/build/lib/commands/general.d.ts.map +1 -1
- package/build/lib/commands/general.js +248 -232
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/geolocation.d.ts +43 -46
- package/build/lib/commands/geolocation.d.ts.map +1 -1
- package/build/lib/commands/geolocation.js +10 -11
- package/build/lib/commands/geolocation.js.map +1 -1
- package/build/lib/commands/gesture.d.ts +273 -276
- package/build/lib/commands/gesture.d.ts.map +1 -1
- package/build/lib/commands/gesture.js +506 -492
- package/build/lib/commands/gesture.js.map +1 -1
- package/build/lib/commands/increase-contrast.d.ts +20 -23
- package/build/lib/commands/increase-contrast.d.ts.map +1 -1
- package/build/lib/commands/increase-contrast.js +30 -30
- package/build/lib/commands/increase-contrast.js.map +1 -1
- package/build/lib/commands/iohid.d.ts +1370 -1373
- package/build/lib/commands/iohid.d.ts.map +1 -1
- package/build/lib/commands/iohid.js +30 -31
- package/build/lib/commands/iohid.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +29 -32
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +53 -51
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/keychains.d.ts +9 -12
- package/build/lib/commands/keychains.d.ts.map +1 -1
- package/build/lib/commands/keychains.js +13 -14
- package/build/lib/commands/keychains.js.map +1 -1
- package/build/lib/commands/localization.d.ts +16 -19
- package/build/lib/commands/localization.d.ts.map +1 -1
- package/build/lib/commands/localization.js +25 -26
- package/build/lib/commands/localization.js.map +1 -1
- package/build/lib/commands/location.d.ts +36 -39
- package/build/lib/commands/location.d.ts.map +1 -1
- package/build/lib/commands/location.js +99 -98
- package/build/lib/commands/location.js.map +1 -1
- package/build/lib/commands/lock.d.ts +21 -24
- package/build/lib/commands/lock.d.ts.map +1 -1
- package/build/lib/commands/lock.js +39 -38
- package/build/lib/commands/lock.js.map +1 -1
- package/build/lib/commands/log.d.ts +43 -37
- package/build/lib/commands/log.d.ts.map +1 -1
- package/build/lib/commands/log.js +174 -171
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/memory.d.ts +9 -12
- package/build/lib/commands/memory.d.ts.map +1 -1
- package/build/lib/commands/memory.js +37 -38
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/navigation.d.ts +30 -33
- package/build/lib/commands/navigation.d.ts.map +1 -1
- package/build/lib/commands/navigation.js +92 -92
- package/build/lib/commands/navigation.js.map +1 -1
- package/build/lib/commands/notifications.d.ts +26 -29
- package/build/lib/commands/notifications.d.ts.map +1 -1
- package/build/lib/commands/notifications.js +53 -53
- package/build/lib/commands/notifications.js.map +1 -1
- package/build/lib/commands/pasteboard.d.ts +21 -24
- package/build/lib/commands/pasteboard.d.ts.map +1 -1
- package/build/lib/commands/pasteboard.js +37 -37
- package/build/lib/commands/pasteboard.js.map +1 -1
- package/build/lib/commands/pcap.d.ts +39 -26
- package/build/lib/commands/pcap.d.ts.map +1 -1
- package/build/lib/commands/pcap.js +81 -81
- package/build/lib/commands/pcap.js.map +1 -1
- package/build/lib/commands/performance.d.ts +63 -44
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +105 -105
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +33 -36
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +66 -65
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/proxy-helper.d.ts +12 -15
- package/build/lib/commands/proxy-helper.d.ts.map +1 -1
- package/build/lib/commands/proxy-helper.js +53 -54
- package/build/lib/commands/proxy-helper.js.map +1 -1
- package/build/lib/commands/record-audio.d.ts +49 -29
- package/build/lib/commands/record-audio.d.ts.map +1 -1
- package/build/lib/commands/record-audio.js +100 -104
- package/build/lib/commands/record-audio.js.map +1 -1
- package/build/lib/commands/recordscreen.d.ts +54 -18
- package/build/lib/commands/recordscreen.d.ts.map +1 -1
- package/build/lib/commands/recordscreen.js +127 -129
- package/build/lib/commands/recordscreen.js.map +1 -1
- package/build/lib/commands/screenshots.d.ts +14 -17
- package/build/lib/commands/screenshots.d.ts.map +1 -1
- package/build/lib/commands/screenshots.js +108 -107
- package/build/lib/commands/screenshots.js.map +1 -1
- package/build/lib/commands/simctl.d.ts +11 -14
- package/build/lib/commands/simctl.d.ts.map +1 -1
- package/build/lib/commands/simctl.js +23 -26
- package/build/lib/commands/simctl.js.map +1 -1
- package/build/lib/commands/source.d.ts +14 -17
- package/build/lib/commands/source.d.ts.map +1 -1
- package/build/lib/commands/source.js +40 -43
- package/build/lib/commands/source.js.map +1 -1
- package/build/lib/commands/timeouts.d.ts +44 -33
- package/build/lib/commands/timeouts.d.ts.map +1 -1
- package/build/lib/commands/timeouts.js +65 -63
- package/build/lib/commands/timeouts.js.map +1 -1
- package/build/lib/commands/web.d.ts +275 -197
- package/build/lib/commands/web.d.ts.map +1 -1
- package/build/lib/commands/web.js +866 -785
- package/build/lib/commands/web.js.map +1 -1
- package/build/lib/commands/xctest-record-screen.d.ts +63 -66
- package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
- package/build/lib/commands/xctest-record-screen.js +103 -102
- package/build/lib/commands/xctest-record-screen.js.map +1 -1
- package/build/lib/commands/xctest.d.ts +55 -51
- package/build/lib/commands/xctest.d.ts.map +1 -1
- package/build/lib/commands/xctest.js +116 -117
- package/build/lib/commands/xctest.js.map +1 -1
- package/build/lib/driver.d.ts +277 -1597
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +318 -235
- 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 +9 -0
- package/build/lib/execute-method-map.js.map +1 -1
- package/lib/commands/active-app-info.js +12 -0
- package/lib/commands/alert.js +68 -65
- package/lib/commands/app-management.js +308 -301
- package/lib/commands/app-strings.js +24 -26
- package/lib/commands/appearance.js +54 -56
- package/lib/commands/audit.js +18 -20
- package/lib/commands/battery.js +35 -37
- package/lib/commands/biometric.js +44 -46
- package/lib/commands/certificate.js +226 -215
- package/lib/commands/clipboard.js +30 -32
- package/lib/commands/condition.js +98 -100
- package/lib/commands/content-size.js +36 -38
- package/lib/commands/context.js +495 -490
- package/lib/commands/deviceInfo.js +19 -20
- package/lib/commands/element.js +367 -357
- package/lib/commands/execute.js +72 -72
- package/lib/commands/file-movement.js +132 -134
- package/lib/commands/find.js +160 -159
- package/lib/commands/general.js +238 -231
- package/lib/commands/geolocation.js +6 -14
- package/lib/commands/gesture.js +525 -515
- package/lib/commands/increase-contrast.js +30 -32
- package/lib/commands/iohid.js +32 -34
- package/lib/commands/keyboard.js +49 -51
- package/lib/commands/keychains.js +12 -14
- package/lib/commands/localization.js +24 -26
- package/lib/commands/location.js +102 -104
- package/lib/commands/lock.js +38 -38
- package/lib/commands/log.js +197 -198
- package/lib/commands/memory.js +40 -42
- package/lib/commands/navigation.js +96 -100
- package/lib/commands/notifications.js +57 -59
- package/lib/commands/pasteboard.js +37 -39
- package/lib/commands/pcap.js +84 -86
- package/lib/commands/performance.js +132 -133
- package/lib/commands/permissions.js +67 -69
- package/lib/commands/proxy-helper.js +60 -61
- package/lib/commands/record-audio.js +115 -120
- package/lib/commands/recordscreen.js +145 -149
- package/lib/commands/screenshots.js +116 -116
- package/lib/commands/simctl.js +25 -29
- package/lib/commands/source.js +42 -46
- package/lib/commands/timeouts.js +59 -63
- package/lib/commands/web.js +932 -859
- package/lib/commands/xctest-record-screen.js +103 -105
- package/lib/commands/xctest.js +134 -139
- package/lib/driver.js +286 -235
- package/lib/execute-method-map.ts +9 -0
- package/npm-shrinkwrap.json +8 -8
- package/package.json +1 -1
- package/build/lib/commands/activeAppInfo.d.ts +0 -12
- package/build/lib/commands/activeAppInfo.d.ts.map +0 -1
- package/build/lib/commands/activeAppInfo.js +0 -15
- package/build/lib/commands/activeAppInfo.js.map +0 -1
- package/build/lib/commands/index.d.ts +0 -96
- package/build/lib/commands/index.d.ts.map +0 -1
- package/build/lib/commands/index.js +0 -100
- package/build/lib/commands/index.js.map +0 -1
- package/build/lib/cookies.d.ts +0 -15
- package/build/lib/cookies.d.ts.map +0 -1
- package/build/lib/cookies.js +0 -84
- package/build/lib/cookies.js.map +0 -1
- package/lib/commands/activeAppInfo.js +0 -14
- package/lib/commands/index.js +0 -95
- package/lib/cookies.js +0 -92
|
@@ -7,114 +7,110 @@ import { isTvOs } from '../utils';
|
|
|
7
7
|
const CLOSE_WINDOW_TIMEOUT = 5000;
|
|
8
8
|
const CLOSE_WINDOW_INTERVAL = 100;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
/**
|
|
22
|
-
* @this {XCUITestDriver}
|
|
23
|
-
*/
|
|
24
|
-
async forward() {
|
|
25
|
-
if (!this.isWebContext()) {
|
|
26
|
-
}
|
|
27
|
-
await this.mobileWebNav('forward');
|
|
28
|
-
},
|
|
29
|
-
/**
|
|
30
|
-
* @this {XCUITestDriver}
|
|
31
|
-
*/
|
|
32
|
-
async closeWindow() {
|
|
33
|
-
if (!this.isWebContext()) {
|
|
34
|
-
throw new errors.NotImplementedError();
|
|
35
|
-
}
|
|
10
|
+
/**
|
|
11
|
+
* @this {XCUITestDriver}
|
|
12
|
+
*/
|
|
13
|
+
export async function back() {
|
|
14
|
+
if (!this.isWebContext()) {
|
|
15
|
+
await this.nativeBack();
|
|
16
|
+
} else {
|
|
17
|
+
await this.mobileWebNav('back');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
36
20
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
await waitForCondition(() => this.curContext !== context, {
|
|
47
|
-
waitMs: CLOSE_WINDOW_TIMEOUT,
|
|
48
|
-
intervalMs: CLOSE_WINDOW_INTERVAL,
|
|
49
|
-
});
|
|
50
|
-
} catch {
|
|
51
|
-
this.log.debug('Context has not yet been changed after closing window. Continuing...');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
},
|
|
21
|
+
/**
|
|
22
|
+
* @this {XCUITestDriver}
|
|
23
|
+
*/
|
|
24
|
+
export async function forward() {
|
|
25
|
+
if (!this.isWebContext()) {
|
|
26
|
+
}
|
|
27
|
+
await this.mobileWebNav('forward');
|
|
28
|
+
}
|
|
55
29
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* @param {string} [bundleId] - the application to open the given URL with. If not provided, then
|
|
64
|
-
* the application assigned by the operating system to handle URLs of the appropriate type
|
|
65
|
-
* @returns {Promise<void>}
|
|
66
|
-
* @since 4.17
|
|
67
|
-
* @this {XCUITestDriver}
|
|
68
|
-
*/
|
|
69
|
-
async mobileDeepLink(url, bundleId) {
|
|
70
|
-
return await this.proxyCommand('/url', 'POST', {
|
|
71
|
-
url,
|
|
72
|
-
bundleId,
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
};
|
|
30
|
+
/**
|
|
31
|
+
* @this {XCUITestDriver}
|
|
32
|
+
*/
|
|
33
|
+
export async function closeWindow() {
|
|
34
|
+
if (!this.isWebContext()) {
|
|
35
|
+
throw new errors.NotImplementedError();
|
|
36
|
+
}
|
|
76
37
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
38
|
+
// since the window will be closed and the execution context gone, return
|
|
39
|
+
// first before closing. Waiting for close will happen in the finally block
|
|
40
|
+
const script = `setTimeout(function () {window.open('','_self').close();}, 0); return true;`;
|
|
41
|
+
const context = this.curContext;
|
|
42
|
+
try {
|
|
43
|
+
return await this.executeAtom('execute_script', [script, []], true);
|
|
44
|
+
} finally {
|
|
45
|
+
// wait for the window to successfully change...
|
|
46
|
+
try {
|
|
47
|
+
await waitForCondition(() => this.curContext !== context, {
|
|
48
|
+
waitMs: CLOSE_WINDOW_TIMEOUT,
|
|
49
|
+
intervalMs: CLOSE_WINDOW_INTERVAL,
|
|
50
|
+
});
|
|
51
|
+
} catch {
|
|
52
|
+
this.log.debug('Context has not yet been changed after closing window. Continuing...');
|
|
85
53
|
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Opens the given URL with the default application assigned to handle it based on the URL
|
|
59
|
+
* scheme, or the application provided as an optional parameter
|
|
60
|
+
*
|
|
61
|
+
* (Note: the version of Xcode must be 14.3+ and iOS must be 16.4+)
|
|
62
|
+
*
|
|
63
|
+
* @param {string} url - the URL to be opened, e.g. `myscheme://yolo`
|
|
64
|
+
* @param {string} [bundleId] - the application to open the given URL with. If not provided, then
|
|
65
|
+
* the application assigned by the operating system to handle URLs of the appropriate type
|
|
66
|
+
* @returns {Promise<void>}
|
|
67
|
+
* @since 4.17
|
|
68
|
+
* @this {XCUITestDriver}
|
|
69
|
+
*/
|
|
70
|
+
export async function mobileDeepLink(url, bundleId) {
|
|
71
|
+
return await this.proxyCommand('/url', 'POST', {
|
|
72
|
+
url,
|
|
73
|
+
bundleId,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
102
76
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
77
|
+
/**
|
|
78
|
+
* @this {XCUITestDriver}
|
|
79
|
+
*/
|
|
80
|
+
export async function nativeBack() {
|
|
81
|
+
if (isTvOs(this.opts.platformName)) {
|
|
82
|
+
this.log.debug(`Sending Menu button as back behavior in tvOS`);
|
|
83
|
+
return await this.mobilePressButton('Menu');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
let navBar = await this.findNativeElementOrElements(
|
|
88
|
+
'class name',
|
|
89
|
+
'XCUIElementTypeNavigationBar',
|
|
90
|
+
false,
|
|
91
|
+
);
|
|
92
|
+
let buttons = await this.findNativeElementOrElements(
|
|
93
|
+
'class name',
|
|
94
|
+
'XCUIElementTypeButton',
|
|
95
|
+
true,
|
|
96
|
+
navBar,
|
|
97
|
+
);
|
|
98
|
+
if (buttons?.length === 0) {
|
|
99
|
+
throw new Error('No buttons found in navigation bar');
|
|
113
100
|
}
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
101
|
|
|
117
|
-
|
|
102
|
+
let backButton = _.filter(buttons, (value) => value.label === 'Back')[0];
|
|
103
|
+
if (backButton) {
|
|
104
|
+
this.log.debug(`Found navigation bar 'back' button. Clicking.`);
|
|
105
|
+
} else {
|
|
106
|
+
this.log.debug(`Unable to find 'Back' button. Trying first button in navigation bar`);
|
|
107
|
+
backButton = buttons?.[0];
|
|
108
|
+
}
|
|
109
|
+
await this.nativeClick(/** @type {string} */ (backButton));
|
|
110
|
+
} catch (err) {
|
|
111
|
+
this.log.error(`Unable to find navigation bar and back button: ${err.message}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
118
114
|
|
|
119
115
|
/**
|
|
120
116
|
* @typedef {import('../driver').XCUITestDriver} XCUITestDriver
|
|
@@ -1,67 +1,65 @@
|
|
|
1
1
|
import {errors} from 'appium/driver';
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
4
|
+
/**
|
|
5
|
+
* Simulates push notification delivery to a simulated device.
|
|
6
|
+
*
|
|
7
|
+
* **Only "remote" push notifications are supported.** VoIP, Complication, File Provider, and other types are unsupported.
|
|
8
|
+
*
|
|
9
|
+
* Supported in Xcode SDK 11.4+.
|
|
10
|
+
* @param {string} bundleId - The bundle identifier of the target application
|
|
11
|
+
* @param {import('./types').PushPayload} payload - Valid push payload.
|
|
12
|
+
* @group Simulator Only
|
|
13
|
+
* @this {XCUITestDriver}
|
|
14
|
+
*/
|
|
15
|
+
export async function mobilePushNotification(bundleId, payload) {
|
|
16
|
+
if (!this.isSimulator()) {
|
|
17
|
+
throw new Error('This extension only works on Simulator');
|
|
18
|
+
}
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
20
|
+
if (!bundleId) {
|
|
21
|
+
throw new errors.InvalidArgumentError(
|
|
22
|
+
`'bundleId' argument must be a valid bundle identifier string`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (!_.isPlainObject(payload)) {
|
|
26
|
+
throw new errors.InvalidArgumentError(
|
|
27
|
+
`The 'payload' argument value must be a valid dictionary. ` +
|
|
28
|
+
`Got ${JSON.stringify(payload)} instead`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (!_.isPlainObject(payload.aps)) {
|
|
32
|
+
throw new errors.InvalidArgumentError(
|
|
33
|
+
`The 'payload.aps' value must be a valid dictionary. ` +
|
|
34
|
+
`Got ${JSON.stringify(payload.aps)} instead`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return await /** @type {import('../driver').Simulator} */ (this.device).pushNotification({
|
|
38
|
+
...payload,
|
|
39
|
+
'Simulator Target Bundle': bundleId,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
};
|
|
43
|
+
/**
|
|
44
|
+
* Blocks until the expected notification is delivered.
|
|
45
|
+
*
|
|
46
|
+
* This method is a thin wrapper over the
|
|
47
|
+
* [`XCTNSNotificationExpectation`](https://developer.apple.com/documentation/xctest/xctnsnotificationexpectation?language=objc) and
|
|
48
|
+
* [`XCTDarwinNotificationExpectation`](https://developer.apple.com/documentation/xctest/xctdarwinnotificationexpectation?language=objc) entities.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} name - The name of the notification to expect
|
|
51
|
+
* @param {import('./types').NotificationType} type - Which notification type to expect.
|
|
52
|
+
* @param {number} timeoutSeconds - For how long to wait until the notification is delivered (in float seconds).
|
|
53
|
+
* @throws A [`TimeoutError`](https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/lib/error_exports_TimeoutError.html) if the expected notification has not been delivered within the given timeout.
|
|
54
|
+
* @this {XCUITestDriver}
|
|
55
|
+
*/
|
|
56
|
+
export async function mobileExpectNotification(name, type = 'plain', timeoutSeconds = 60) {
|
|
57
|
+
return await this.proxyCommand('/wda/expectNotification', 'POST', {
|
|
58
|
+
name,
|
|
59
|
+
type,
|
|
60
|
+
timeout: timeoutSeconds,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
65
63
|
|
|
66
64
|
/**
|
|
67
65
|
* @typedef {import('../driver').XCUITestDriver} XCUITestDriver
|
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
1
|
+
/**
|
|
2
|
+
* Sets the Simulator's pasteboard content to the given value.
|
|
3
|
+
*
|
|
4
|
+
* Does not work for real devices.
|
|
5
|
+
* @param {string} content - The content to set
|
|
6
|
+
* @param {string} encoding - The content's encoding
|
|
7
|
+
* @group Simulator Only
|
|
8
|
+
* @returns {Promise<void>}
|
|
9
|
+
* @this {XCUITestDriver}
|
|
10
|
+
*/
|
|
11
|
+
export async function mobileSetPasteboard(content, encoding = 'utf8') {
|
|
12
|
+
if (!this.isSimulator()) {
|
|
13
|
+
throw new Error('Setting pasteboard content is not supported on real devices');
|
|
14
|
+
}
|
|
15
|
+
if (!content) {
|
|
16
|
+
// can be empty string
|
|
17
|
+
throw new Error('Pasteboard content is mandatory to set');
|
|
18
|
+
}
|
|
19
|
+
return await /** @type {import('../driver').Simulator} */ (this.device).simctl.setPasteboard(
|
|
20
|
+
content, /** @type {BufferEncoding} */ (encoding)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
24
|
+
/**
|
|
25
|
+
* Gets the Simulator's pasteboard content.
|
|
26
|
+
*
|
|
27
|
+
* Does not work for real devices.
|
|
28
|
+
* @param {string} encoding - Expected encoding of returned string
|
|
29
|
+
* @group Simulator Only
|
|
30
|
+
* @this {XCUITestDriver}
|
|
31
|
+
* @returns {Promise<string>} The pasteboard content string
|
|
32
|
+
*/
|
|
33
|
+
export async function mobileGetPasteboard(encoding = 'utf8') {
|
|
34
|
+
if (!this.isSimulator()) {
|
|
35
|
+
throw new Error('Getting pasteboard content is not supported on real devices');
|
|
36
|
+
}
|
|
37
|
+
return await /** @type {import('../driver').Simulator} */ (this.device).simctl.getPasteboard(encoding);
|
|
38
|
+
}
|
|
41
39
|
|
|
42
40
|
/**
|
|
43
41
|
* @typedef {import('../driver').XCUITestDriver} XCUITestDriver
|
package/lib/commands/pcap.js
CHANGED
|
@@ -71,99 +71,97 @@ export class TrafficCapture {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
74
|
+
/**
|
|
75
|
+
* Records the given network traffic capture into a .pcap file.
|
|
76
|
+
*
|
|
77
|
+
* @param {number} timeLimitSec - The maximum recording time, in seconds. The maximum value is `43200` (12 hours).
|
|
78
|
+
* @param {boolean} forceRestart - Whether to restart traffic capture process forcefully when startPcap is called (`true`) or ignore the call until the current traffic capture is completed (`false`, the default value).
|
|
79
|
+
* @throws {Error} If network traffic capture has failed to start.
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
* @this {XCUITestDriver}
|
|
82
|
+
*/
|
|
83
|
+
export async function mobileStartPcap(timeLimitSec = 180, forceRestart = false) {
|
|
84
|
+
if (this.isSimulator()) {
|
|
85
|
+
throw this.log.errorWithException('Network traffic capture only works on real devices');
|
|
86
|
+
}
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (this._trafficCapture) {
|
|
103
|
-
await this._trafficCapture.cleanup();
|
|
104
|
-
this._trafficCapture = null;
|
|
88
|
+
if (this._trafficCapture?.isCapturing()) {
|
|
89
|
+
this.log.info(`There is an active traffic capture process`);
|
|
90
|
+
if (forceRestart) {
|
|
91
|
+
this.log.info(`Stopping it because 'forceRestart' option is set to true`);
|
|
92
|
+
await this._trafficCapture.interrupt(true);
|
|
93
|
+
} else {
|
|
94
|
+
this.log.info(
|
|
95
|
+
`Doing nothing. ` +
|
|
96
|
+
`Set 'forceRestart' option to true if you'd like to start a new traffic capture session`,
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
105
99
|
}
|
|
100
|
+
}
|
|
101
|
+
if (this._trafficCapture) {
|
|
102
|
+
await this._trafficCapture.cleanup();
|
|
103
|
+
this._trafficCapture = null;
|
|
104
|
+
}
|
|
106
105
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
const resultPath = await tempDir.path({
|
|
107
|
+
prefix: `appium_${util.uuidV4().substring(0, 8)}`,
|
|
108
|
+
suffix: DEFAULT_EXT,
|
|
109
|
+
});
|
|
110
|
+
const trafficCollector = new TrafficCapture(this.device.udid, this.log, resultPath);
|
|
111
|
+
|
|
112
|
+
const timeoutSeconds = parseInt(String(timeLimitSec), 10);
|
|
113
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_CAPTURE_TIME_SEC || timeoutSeconds <= 0) {
|
|
114
|
+
throw new errors.InvalidArgumentError(
|
|
115
|
+
`The timeLimitSec value must be in range [1, ${MAX_CAPTURE_TIME_SEC}] seconds. ` +
|
|
116
|
+
`The value of '${timeLimitSec}' has been passed instead.`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
112
119
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
try {
|
|
121
|
+
await trafficCollector.start(timeoutSeconds);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
await trafficCollector.interrupt(true);
|
|
124
|
+
await trafficCollector.cleanup();
|
|
125
|
+
throw e;
|
|
126
|
+
}
|
|
127
|
+
this._trafficCapture = trafficCollector;
|
|
128
|
+
}
|
|
120
129
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
* @remarks Network capture files can be viewed in [Wireshark](https://www.wireshark.org/) and other similar applications.
|
|
139
|
-
* @returns {Promise<string>} Base64-encoded content of the recorded pcap file or an empty string if no traffic capture has been started before.
|
|
140
|
-
* @throws {Error} If there was an error while getting the capture file.
|
|
141
|
-
* @this {XCUITestDriver}
|
|
142
|
-
*/
|
|
143
|
-
async mobileStopPcap() {
|
|
144
|
-
if (!this._trafficCapture) {
|
|
145
|
-
this.log.info('Network traffic collector has not been started. There is nothing to stop');
|
|
146
|
-
return '';
|
|
147
|
-
}
|
|
130
|
+
/**
|
|
131
|
+
* Stops network traffic capture.
|
|
132
|
+
*
|
|
133
|
+
* If no traffic capture process is running, then the endpoint will try to get the recently recorded file.
|
|
134
|
+
*
|
|
135
|
+
* If no previously recorded file is found and no active traffic capture processes are running, then the method returns an empty string.
|
|
136
|
+
*
|
|
137
|
+
* @remarks Network capture files can be viewed in [Wireshark](https://www.wireshark.org/) and other similar applications.
|
|
138
|
+
* @returns {Promise<string>} Base64-encoded content of the recorded pcap file or an empty string if no traffic capture has been started before.
|
|
139
|
+
* @throws {Error} If there was an error while getting the capture file.
|
|
140
|
+
* @this {XCUITestDriver}
|
|
141
|
+
*/
|
|
142
|
+
export async function mobileStopPcap() {
|
|
143
|
+
if (!this._trafficCapture) {
|
|
144
|
+
this.log.info('Network traffic collector has not been started. There is nothing to stop');
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
} catch (e) {
|
|
159
|
-
await this._trafficCapture.interrupt(true);
|
|
160
|
-
await this._trafficCapture.cleanup();
|
|
161
|
-
this._trafficCapture = null;
|
|
162
|
-
throw e;
|
|
148
|
+
let resultPath;
|
|
149
|
+
try {
|
|
150
|
+
resultPath = await this._trafficCapture.finish();
|
|
151
|
+
if (!(await fs.exists(resultPath))) {
|
|
152
|
+
throw this.log.errorWithException(
|
|
153
|
+
`The network traffic capture utility has failed ` +
|
|
154
|
+
`to store the actual traffic capture at '${resultPath}'`,
|
|
155
|
+
);
|
|
163
156
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
157
|
+
} catch (e) {
|
|
158
|
+
await this._trafficCapture.interrupt(true);
|
|
159
|
+
await this._trafficCapture.cleanup();
|
|
160
|
+
this._trafficCapture = null;
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
return await encodeBase64OrUpload(resultPath);
|
|
164
|
+
}
|
|
167
165
|
|
|
168
166
|
/**
|
|
169
167
|
* @typedef {import('../driver').XCUITestDriver} XCUITestDriver
|