appium-xcuitest-driver 5.14.2 → 5.15.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 +21 -0
- package/build/lib/commands/index.d.ts +2 -0
- package/build/lib/commands/index.d.ts.map +1 -1
- package/build/lib/commands/index.js +2 -0
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/memory.d.ts +14 -0
- package/build/lib/commands/memory.d.ts.map +1 -0
- package/build/lib/commands/memory.js +52 -0
- package/build/lib/commands/memory.js.map +1 -0
- package/build/lib/devicectl.d.ts +103 -0
- package/build/lib/devicectl.d.ts.map +1 -0
- package/build/lib/devicectl.js +162 -0
- package/build/lib/devicectl.js.map +1 -0
- package/build/lib/driver.d.ts +14 -11
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +4 -0
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts +6 -0
- package/build/lib/execute-method-map.d.ts.map +1 -1
- package/build/lib/execute-method-map.js +6 -0
- package/build/lib/execute-method-map.js.map +1 -1
- package/build/lib/ios-deploy.d.ts.map +1 -1
- package/build/lib/ios-deploy.js +7 -31
- package/build/lib/ios-deploy.js.map +1 -1
- package/lib/commands/index.js +2 -0
- package/lib/commands/memory.js +54 -0
- package/lib/devicectl.js +174 -0
- package/lib/driver.js +6 -0
- package/lib/execute-method-map.ts +6 -0
- package/lib/ios-deploy.js +7 -32
- package/npm-shrinkwrap.json +9 -9
- package/package.json +2 -2
package/lib/devicectl.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import {exec, SubProcess} from 'teen_process';
|
|
2
|
+
import {util} from 'appium/support';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
|
|
5
|
+
const XCRUN = 'xcrun';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} ProcessInfo
|
|
9
|
+
* @property {number} processIdentifier
|
|
10
|
+
* @property {string} executable
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
Example:
|
|
15
|
+
{
|
|
16
|
+
"executable" : "file:///sbin/launchd",
|
|
17
|
+
"processIdentifier" : 1
|
|
18
|
+
},
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} AppInfo
|
|
23
|
+
* @property {boolean} appClip
|
|
24
|
+
* @property {boolean} builtByDeveloper
|
|
25
|
+
* @property {string} bundleIdentifier
|
|
26
|
+
* @property {string} bundleVersion
|
|
27
|
+
* @property {boolean} defaultApp
|
|
28
|
+
* @property {boolean} hidden
|
|
29
|
+
* @property {boolean} internalApp
|
|
30
|
+
* @property {string} name
|
|
31
|
+
* @property {boolean} removable
|
|
32
|
+
* @property {string} url
|
|
33
|
+
* @property {string} version
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
Example:
|
|
38
|
+
{
|
|
39
|
+
"appClip" : false,
|
|
40
|
+
"builtByDeveloper" : false,
|
|
41
|
+
"bundleIdentifier" : "com.apple.mobilesafari",
|
|
42
|
+
"bundleVersion" : "8617.1.17.10.9",
|
|
43
|
+
"defaultApp" : true,
|
|
44
|
+
"hidden" : false,
|
|
45
|
+
"internalApp" : false,
|
|
46
|
+
"name" : "Safari",
|
|
47
|
+
"removable" : false,
|
|
48
|
+
"url" : "file:///Applications/MobileSafari.app/",
|
|
49
|
+
"version" : "17.2"
|
|
50
|
+
}
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {Object} ExecuteOptions
|
|
55
|
+
* @property {boolean} [logStdout=false]
|
|
56
|
+
* @property {boolean} [asJson=true]
|
|
57
|
+
* @property {boolean} [asynchronous=false]
|
|
58
|
+
* @property {string[]|string} [subcommandOptions]
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {{asynchronous: true}} TAsyncOpts
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
export class Devicectl {
|
|
66
|
+
/**
|
|
67
|
+
* @since Xcode 15, iOS 17
|
|
68
|
+
* @param {string} udid
|
|
69
|
+
* @param {import('@appium/types').AppiumLogger} log
|
|
70
|
+
*/
|
|
71
|
+
constructor(udid, log) {
|
|
72
|
+
this.udid = udid;
|
|
73
|
+
this.log = log;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @template {ExecuteOptions} TExecOpts
|
|
78
|
+
* @param {string[]} subcommand
|
|
79
|
+
* @param {TExecOpts} [opts]
|
|
80
|
+
* @return {Promise<TExecOpts extends TAsyncOpts ? import('teen_process').SubProcess : import('teen_process').TeenProcessExecResult>}
|
|
81
|
+
*/
|
|
82
|
+
async execute(subcommand, opts) {
|
|
83
|
+
const {
|
|
84
|
+
logStdout = false,
|
|
85
|
+
asynchronous = false,
|
|
86
|
+
asJson = true,
|
|
87
|
+
subcommandOptions,
|
|
88
|
+
} = opts ?? {};
|
|
89
|
+
|
|
90
|
+
const finalArgs = [
|
|
91
|
+
'devicectl', ...subcommand,
|
|
92
|
+
'--device', this.udid,
|
|
93
|
+
];
|
|
94
|
+
if (subcommandOptions && !_.isEmpty(subcommandOptions)) {
|
|
95
|
+
finalArgs.push(
|
|
96
|
+
...(Array.isArray(subcommandOptions) ? subcommandOptions : [subcommandOptions])
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (asJson) {
|
|
100
|
+
finalArgs.push('--quiet', '--json-output', '-');
|
|
101
|
+
}
|
|
102
|
+
const cmdStr = util.quote([XCRUN, ...finalArgs]);
|
|
103
|
+
this.log.debug(`Executing ${cmdStr}`);
|
|
104
|
+
try {
|
|
105
|
+
if (asynchronous) {
|
|
106
|
+
const result = new SubProcess(XCRUN, finalArgs);
|
|
107
|
+
await result.start(0);
|
|
108
|
+
// @ts-ignore TS does not understand it
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
const result = await exec(XCRUN, finalArgs);
|
|
112
|
+
if (logStdout) {
|
|
113
|
+
this.log.debug(`Command output: ${result.stdout}`);
|
|
114
|
+
}
|
|
115
|
+
// @ts-ignore TS does not understand it
|
|
116
|
+
return result;
|
|
117
|
+
} catch (e) {
|
|
118
|
+
throw new Error(`'${cmdStr}' failed. Original error: ${e.stderr || e.stdout || e.message}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Simulates memory warning for the process with the given PID
|
|
124
|
+
*
|
|
125
|
+
* @param {number|string} pid The process identifier to simulate the Low Memory warning for
|
|
126
|
+
* @return {Promise<void>}
|
|
127
|
+
*/
|
|
128
|
+
async sendMemoryWarning(pid) {
|
|
129
|
+
await this.execute(['device', 'process', 'sendMemoryWarning'], {
|
|
130
|
+
subcommandOptions: ['--pid', `${pid}`]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Lists running processes on the device
|
|
136
|
+
*
|
|
137
|
+
* @returns {Promise<ProcessInfo[]>}
|
|
138
|
+
*/
|
|
139
|
+
async listProcesses() {
|
|
140
|
+
const {stdout} = await this.execute(['device', 'info', 'processes']);
|
|
141
|
+
return JSON.parse(stdout).result.runningProcesses;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Send POSIX signal to the running process
|
|
146
|
+
*
|
|
147
|
+
* @param {number|string} pid The process identifier to send a signal to
|
|
148
|
+
* @param {number|string} signal The signal to send to a process. See 'man signal' for a list of signals
|
|
149
|
+
* @returns {Promise<void>}
|
|
150
|
+
*/
|
|
151
|
+
async sendSignalToProcess(pid, signal) {
|
|
152
|
+
await this.execute(['device', 'process', 'signal'], {
|
|
153
|
+
subcommandOptions: ['--signal', `${signal}`, '--pid', `${pid}`]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Retrieves the list of installed apps from the device
|
|
159
|
+
*
|
|
160
|
+
* @param {string?} [bundleId=null] Provide the target bundle identifier
|
|
161
|
+
* to speed up the lookup.
|
|
162
|
+
* @returns {Promise<AppInfo[]>} Empty array is returned if no matching apps are found
|
|
163
|
+
*/
|
|
164
|
+
async listApps(bundleId = null) {
|
|
165
|
+
const subcommandOptions = ['--include-all-apps'];
|
|
166
|
+
if (bundleId) {
|
|
167
|
+
subcommandOptions.push('--bundle-id', bundleId);
|
|
168
|
+
}
|
|
169
|
+
const {stdout} = await this.execute(['device', 'info', 'apps'], {
|
|
170
|
+
subcommandOptions,
|
|
171
|
+
});
|
|
172
|
+
return JSON.parse(stdout).result.apps;
|
|
173
|
+
}
|
|
174
|
+
}
|
package/lib/driver.js
CHANGED
|
@@ -1946,6 +1946,12 @@ class XCUITestDriver extends BaseDriver {
|
|
|
1946
1946
|
pullFolder = commands.fileMovementExtensions.pullFolder;
|
|
1947
1947
|
mobilePullFolder = commands.fileMovementExtensions.mobilePullFolder;
|
|
1948
1948
|
|
|
1949
|
+
/*--------+
|
|
1950
|
+
| MEMORY |
|
|
1951
|
+
+--------+*/
|
|
1952
|
+
|
|
1953
|
+
mobileSendMemoryWarning = commands.memoryExtensions.mobileSendMemoryWarning;
|
|
1954
|
+
|
|
1949
1955
|
/*------+
|
|
1950
1956
|
| FIND |
|
|
1951
1957
|
+------+*/
|
|
@@ -19,6 +19,12 @@ export const executeMethodMap = {
|
|
|
19
19
|
optional: ['offset'],
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
|
+
'mobile: sendMemoryWarning': {
|
|
23
|
+
command: 'mobileSendMemoryWarning',
|
|
24
|
+
params: {
|
|
25
|
+
required: ['bundleId'],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
22
28
|
// https://developer.apple.com/documentation/xctest/xcuielement/1618668-swipeleft?language=objc
|
|
23
29
|
// https://developer.apple.com/documentation/xctest/xcuielement/1618674-swiperight?language=objc
|
|
24
30
|
// https://developer.apple.com/documentation/xctest/xcuielement/1618667-swipeup?language=objc
|
package/lib/ios-deploy.js
CHANGED
|
@@ -7,7 +7,7 @@ import _ from 'lodash';
|
|
|
7
7
|
import {exec} from 'teen_process';
|
|
8
8
|
import {extractBundleId} from './app-utils';
|
|
9
9
|
import {pushFolder} from './ios-fs-helpers';
|
|
10
|
-
import {
|
|
10
|
+
import { Devicectl } from './devicectl';
|
|
11
11
|
|
|
12
12
|
const APPLICATION_INSTALLED_NOTIFICATION = 'com.apple.mobile.application_installed';
|
|
13
13
|
const INSTALLATION_STAGING_DIR = 'PublicStaging';
|
|
@@ -211,40 +211,15 @@ class IOSDeploy {
|
|
|
211
211
|
if (util.compareVersions(platformVersion, '>=', '17.0')) {
|
|
212
212
|
log.debug(`Calling devicectl to kill the process`);
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
'devicectl',
|
|
220
|
-
'device',
|
|
221
|
-
'info',
|
|
222
|
-
'processes',
|
|
223
|
-
`--device`, this.udid
|
|
224
|
-
]);
|
|
225
|
-
// Each line has spaces. devicectl has JSON output option, but it writes it to a file only.
|
|
226
|
-
// Here parse the standard output directly.
|
|
227
|
-
// e.g.:
|
|
228
|
-
// 823 /private/var/containers/Bundle/Application/8E748312-8CBE-4C13-8295-C2EF3ED2C0C1/WebDriverAgentRunner-Runner.app/WebDriverAgentRunner-Runner
|
|
229
|
-
// 824 /Applications/MobileSafari.app/MobileSafari
|
|
230
|
-
// 825 /usr/libexec/debugserver
|
|
231
|
-
const executableLine = stdout.split('\n').find((line) => line.trim().endsWith(executableName));
|
|
232
|
-
if (!executableLine) {
|
|
214
|
+
const devicectl = new Devicectl(this.udid, log);
|
|
215
|
+
const pids = (await devicectl.listProcesses())
|
|
216
|
+
.filter(({executable}) => executable.endsWith(`/${executableName}`))
|
|
217
|
+
.map(({processIdentifier}) => processIdentifier);
|
|
218
|
+
if (_.isEmpty(pids)) {
|
|
233
219
|
log.info(`The process of the bundle id '${bundleId}' was not running`);
|
|
234
220
|
return false;
|
|
235
221
|
}
|
|
236
|
-
await
|
|
237
|
-
'devicectl',
|
|
238
|
-
'device',
|
|
239
|
-
'process',
|
|
240
|
-
'signal',
|
|
241
|
-
'-s', `2`,
|
|
242
|
-
// e.g.
|
|
243
|
-
// '824 /Applications/MobileSafari.app/MobileSafari '
|
|
244
|
-
// ' 999 /Applications/MobileSafari.app/MobileSafari ' (can include spaces in the top)
|
|
245
|
-
'-p', `${executableLine.trim().split(/\s+/)[0]}`,
|
|
246
|
-
`--device`, this.udid
|
|
247
|
-
]);
|
|
222
|
+
await devicectl.sendSignalToProcess(pids[0], 2);
|
|
248
223
|
} else {
|
|
249
224
|
instrumentService = await services.startInstrumentService(this.udid);
|
|
250
225
|
const processes = await instrumentService.callChannel(
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-xcuitest-driver",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.15.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "appium-xcuitest-driver",
|
|
9
|
-
"version": "5.
|
|
9
|
+
"version": "5.15.1",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@colors/colors": "^1.6.0",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"appium-ios-device": "^2.5.4",
|
|
15
15
|
"appium-ios-simulator": "^5.5.1",
|
|
16
16
|
"appium-remote-debugger": "^10.0.0",
|
|
17
|
-
"appium-webdriveragent": "
|
|
17
|
+
"appium-webdriveragent": "~5.15.9",
|
|
18
18
|
"appium-xcode": "^5.1.4",
|
|
19
19
|
"async-lock": "^1.4.0",
|
|
20
20
|
"asyncbox": "^3.0.0",
|
|
@@ -829,9 +829,9 @@
|
|
|
829
829
|
}
|
|
830
830
|
},
|
|
831
831
|
"node_modules/@types/node": {
|
|
832
|
-
"version": "20.11.
|
|
833
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.
|
|
834
|
-
"integrity": "sha512-
|
|
832
|
+
"version": "20.11.14",
|
|
833
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.14.tgz",
|
|
834
|
+
"integrity": "sha512-w3yWCcwULefjP9DmDDsgUskrMoOy5Z8MiwKHr1FvqGPtx7CvJzQvxD7eKpxNtklQxLruxSXWddyeRtyud0RcXQ==",
|
|
835
835
|
"dependencies": {
|
|
836
836
|
"undici-types": "~5.26.4"
|
|
837
837
|
}
|
|
@@ -1064,9 +1064,9 @@
|
|
|
1064
1064
|
}
|
|
1065
1065
|
},
|
|
1066
1066
|
"node_modules/appium-webdriveragent": {
|
|
1067
|
-
"version": "5.15.
|
|
1068
|
-
"resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-5.15.
|
|
1069
|
-
"integrity": "sha512-
|
|
1067
|
+
"version": "5.15.9",
|
|
1068
|
+
"resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-5.15.9.tgz",
|
|
1069
|
+
"integrity": "sha512-03brYer2B68V+Jqjy8VVYNEeDftSzizZaXGazZsAq1ENDhvXgzIErKWjFAswTQWu/ciDmXASt8I96K6ks+Gy0A==",
|
|
1070
1070
|
"dependencies": {
|
|
1071
1071
|
"@appium/base-driver": "^9.0.0",
|
|
1072
1072
|
"@appium/strongbox": "^0.x",
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"xcuitest",
|
|
9
9
|
"xctest"
|
|
10
10
|
],
|
|
11
|
-
"version": "5.
|
|
11
|
+
"version": "5.15.1",
|
|
12
12
|
"author": "Appium Contributors",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"repository": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"appium-ios-device": "^2.5.4",
|
|
82
82
|
"appium-ios-simulator": "^5.5.1",
|
|
83
83
|
"appium-remote-debugger": "^10.0.0",
|
|
84
|
-
"appium-webdriveragent": "
|
|
84
|
+
"appium-webdriveragent": "~5.15.9",
|
|
85
85
|
"appium-xcode": "^5.1.4",
|
|
86
86
|
"async-lock": "^1.4.0",
|
|
87
87
|
"asyncbox": "^3.0.0",
|