appium-remote-debugger 11.5.9 → 12.0.0
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 +45 -0
- package/build/lib/mixins/connect.d.ts +31 -30
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +55 -45
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/cookies.d.ts +8 -4
- package/build/lib/mixins/cookies.d.ts.map +1 -1
- package/build/lib/mixins/cookies.js +12 -7
- package/build/lib/mixins/cookies.js.map +1 -1
- package/build/lib/mixins/events.d.ts +32 -4
- package/build/lib/mixins/events.d.ts.map +1 -1
- package/build/lib/mixins/events.js +46 -2
- package/build/lib/mixins/events.js.map +1 -1
- package/build/lib/mixins/execute.d.ts +16 -5
- package/build/lib/mixins/execute.d.ts.map +1 -1
- package/build/lib/mixins/execute.js +21 -13
- package/build/lib/mixins/execute.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts +25 -16
- package/build/lib/mixins/message-handlers.d.ts.map +1 -1
- package/build/lib/mixins/message-handlers.js +34 -24
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/mixins/misc.d.ts +11 -29
- package/build/lib/mixins/misc.d.ts.map +1 -1
- package/build/lib/mixins/misc.js +16 -51
- package/build/lib/mixins/misc.js.map +1 -1
- package/build/lib/mixins/navigate.d.ts +29 -15
- package/build/lib/mixins/navigate.d.ts.map +1 -1
- package/build/lib/mixins/navigate.js +40 -28
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/mixins/screenshot.d.ts +10 -2
- package/build/lib/mixins/screenshot.d.ts.map +1 -1
- package/build/lib/mixins/screenshot.js +9 -3
- package/build/lib/mixins/screenshot.js.map +1 -1
- package/build/lib/remote-debugger-real-device.d.ts +7 -19
- package/build/lib/remote-debugger-real-device.d.ts.map +1 -1
- package/build/lib/remote-debugger-real-device.js +12 -20
- package/build/lib/remote-debugger-real-device.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +60 -167
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +62 -119
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/types.d.ts +41 -1
- package/build/lib/types.d.ts.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/mixins/connect.js +65 -51
- package/lib/mixins/cookies.js +13 -7
- package/lib/mixins/events.js +47 -2
- package/lib/mixins/execute.js +22 -13
- package/lib/mixins/message-handlers.js +35 -24
- package/lib/mixins/misc.js +17 -51
- package/lib/mixins/navigate.js +41 -28
- package/lib/mixins/screenshot.js +10 -3
- package/lib/remote-debugger-real-device.ts +28 -0
- package/lib/remote-debugger.ts +251 -0
- package/lib/types.ts +44 -1
- package/package.json +1 -1
- package/lib/remote-debugger-real-device.js +0 -39
- package/lib/remote-debugger.js +0 -299
package/lib/mixins/connect.js
CHANGED
|
@@ -66,19 +66,19 @@ export async function connect (timeout = APP_CONNECT_TIMEOUT_MS) {
|
|
|
66
66
|
const timer = new timing.Timer().start();
|
|
67
67
|
this.log.debug(`Waiting up to ${timeout}ms for applications to be reported`);
|
|
68
68
|
try {
|
|
69
|
-
await waitForCondition(() => !_.isEmpty(this.
|
|
69
|
+
await waitForCondition(() => !_.isEmpty(this._appDict), {
|
|
70
70
|
waitMs: timeout,
|
|
71
71
|
intervalMs: APP_CONNECT_INTERVAL_MS,
|
|
72
72
|
});
|
|
73
73
|
this.log.debug(
|
|
74
|
-
`Retrieved ${util.pluralize('application', _.size(this.
|
|
74
|
+
`Retrieved ${util.pluralize('application', _.size(this._appDict), true)} ` +
|
|
75
75
|
`within ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
|
|
76
76
|
);
|
|
77
77
|
} catch (err) {
|
|
78
78
|
this.log.debug(`Timed out waiting for applications to be reported`);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
return this.
|
|
81
|
+
return this._appDict || {};
|
|
82
82
|
} catch (err) {
|
|
83
83
|
this.log.error(`Error setting connection key: ${err.message}`);
|
|
84
84
|
await this.disconnect();
|
|
@@ -92,8 +92,8 @@ export async function connect (timeout = APP_CONNECT_TIMEOUT_MS) {
|
|
|
92
92
|
* @returns {Promise<void>}
|
|
93
93
|
*/
|
|
94
94
|
export async function disconnect () {
|
|
95
|
-
if (this.
|
|
96
|
-
await this.
|
|
95
|
+
if (this._rpcClient) {
|
|
96
|
+
await this._rpcClient.disconnect();
|
|
97
97
|
}
|
|
98
98
|
this.emit(events.EVENT_DISCONNECT, true);
|
|
99
99
|
this.teardown();
|
|
@@ -115,23 +115,23 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
115
115
|
rpcClient.shouldCheckForTarget = false;
|
|
116
116
|
try {
|
|
117
117
|
const timer = new timing.Timer().start();
|
|
118
|
-
if (!this.
|
|
118
|
+
if (!this._appDict || _.isEmpty(this._appDict)) {
|
|
119
119
|
this.log.debug('No applications currently connected.');
|
|
120
120
|
return [];
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
const { appIdKey } = await
|
|
124
|
-
if (this.
|
|
125
|
-
this.log.debug(`Received altered app id, updating from '${this.
|
|
126
|
-
this.
|
|
123
|
+
const { appIdKey } = await searchForApp.bind(this)(currentUrl, maxTries, ignoreAboutBlankUrl);
|
|
124
|
+
if (this._appIdKey !== appIdKey) {
|
|
125
|
+
this.log.debug(`Received altered app id, updating from '${this._appIdKey}' to '${appIdKey}'`);
|
|
126
|
+
this._appIdKey = appIdKey;
|
|
127
127
|
}
|
|
128
128
|
logApplicationDictionary.bind(this)();
|
|
129
129
|
// translate the dictionary into a useful form, and return to sender
|
|
130
|
-
this.log.debug(`Finally selecting app ${this.
|
|
130
|
+
this.log.debug(`Finally selecting app ${this._appIdKey}`);
|
|
131
131
|
|
|
132
132
|
/** @type {import('../types').Page[]} */
|
|
133
133
|
const fullPageArray = [];
|
|
134
|
-
for (const [app, info] of _.toPairs(this.
|
|
134
|
+
for (const [app, info] of _.toPairs(this._appDict)) {
|
|
135
135
|
if (!_.isArray(info.pageArray) || !info.isActive) {
|
|
136
136
|
continue;
|
|
137
137
|
}
|
|
@@ -153,6 +153,32 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
*
|
|
158
|
+
* @this {RemoteDebugger}
|
|
159
|
+
* @param {string|number} appIdKey
|
|
160
|
+
* @param {string|number} pageIdKey
|
|
161
|
+
* @param {boolean} [skipReadyCheck]
|
|
162
|
+
* @returns {Promise<void>}
|
|
163
|
+
*/
|
|
164
|
+
export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
165
|
+
this._appIdKey = _.startsWith(`${appIdKey}`, 'PID:') ? `${appIdKey}` : `PID:${appIdKey}`;
|
|
166
|
+
this._pageIdKey = pageIdKey;
|
|
167
|
+
|
|
168
|
+
this.log.debug(`Selecting page '${pageIdKey}' on app '${this._appIdKey}' and forwarding socket setup`);
|
|
169
|
+
|
|
170
|
+
const timer = new timing.Timer().start();
|
|
171
|
+
|
|
172
|
+
await this.requireRpcClient().selectPage(this._appIdKey, pageIdKey);
|
|
173
|
+
|
|
174
|
+
if (!skipReadyCheck && !await this.checkPageIsReady()) {
|
|
175
|
+
await this.waitForDom();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.log.debug(`Selected page after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
156
182
|
/**
|
|
157
183
|
*
|
|
158
184
|
* @this {RemoteDebugger}
|
|
@@ -161,10 +187,10 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
161
187
|
* @param {boolean} ignoreAboutBlankUrl
|
|
162
188
|
* @returns {Promise<import('../types').AppPage>}
|
|
163
189
|
*/
|
|
164
|
-
|
|
165
|
-
const bundleIds = this.
|
|
166
|
-
? [this.
|
|
167
|
-
: [this.
|
|
190
|
+
async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
191
|
+
const bundleIds = this._includeSafari && !this._isSafari
|
|
192
|
+
? [this._bundleId, ...this._additionalBundleIds, SAFARI_BUNDLE_ID]
|
|
193
|
+
: [this._bundleId, ...this._additionalBundleIds];
|
|
168
194
|
let retryCount = 0;
|
|
169
195
|
return /** @type {import('../types').AppPage} */ (await retryInterval(maxTries, SELECT_APP_RETRY_SLEEP_MS, async () => {
|
|
170
196
|
logApplicationDictionary.bind(this)();
|
|
@@ -172,7 +198,7 @@ export async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
|
172
198
|
this.log.debug(`Trying out the possible app ids: ${possibleAppIds.join(', ')} (try #${retryCount + 1} of ${maxTries})`);
|
|
173
199
|
for (const attemptedAppIdKey of possibleAppIds) {
|
|
174
200
|
try {
|
|
175
|
-
if (!this.
|
|
201
|
+
if (!this._appDict[attemptedAppIdKey].isActive) {
|
|
176
202
|
this.log.debug(`Skipping app '${attemptedAppIdKey}' because it is not active`);
|
|
177
203
|
continue;
|
|
178
204
|
}
|
|
@@ -190,12 +216,12 @@ export async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
|
190
216
|
}
|
|
191
217
|
|
|
192
218
|
// save the page array for this app
|
|
193
|
-
this.
|
|
219
|
+
this._appDict[appIdKey].pageArray = pageArrayFromDict(pageDict);
|
|
194
220
|
|
|
195
221
|
// if we are looking for a particular url, make sure we
|
|
196
222
|
// have the right page. Ignore empty or undefined urls.
|
|
197
223
|
// Ignore about:blank if requested.
|
|
198
|
-
const result =
|
|
224
|
+
const result = searchForPage.bind(this)(this._appDict, currentUrl, ignoreAboutBlankUrl);
|
|
199
225
|
if (result) {
|
|
200
226
|
return result;
|
|
201
227
|
}
|
|
@@ -225,7 +251,7 @@ export async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
|
225
251
|
* @param {boolean} [ignoreAboutBlankUrl]
|
|
226
252
|
* @returns {import('../types').AppPage?}
|
|
227
253
|
*/
|
|
228
|
-
|
|
254
|
+
function searchForPage (appsDict, currentUrl = null, ignoreAboutBlankUrl = false) {
|
|
229
255
|
for (const appDict of _.values(appsDict)) {
|
|
230
256
|
if (!appDict || !appDict.isActive || !appDict.pageArray || _.isEmpty(appDict.pageArray)) {
|
|
231
257
|
continue;
|
|
@@ -244,39 +270,13 @@ export function searchForPage (appsDict, currentUrl = null, ignoreAboutBlankUrl
|
|
|
244
270
|
return null;
|
|
245
271
|
}
|
|
246
272
|
|
|
247
|
-
/**
|
|
248
|
-
*
|
|
249
|
-
* @this {RemoteDebugger}
|
|
250
|
-
* @param {string|number} appIdKey
|
|
251
|
-
* @param {string|number} pageIdKey
|
|
252
|
-
* @param {boolean} [skipReadyCheck]
|
|
253
|
-
* @returns {Promise<void>}
|
|
254
|
-
*/
|
|
255
|
-
export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
256
|
-
this.appIdKey = _.startsWith(`${appIdKey}`, 'PID:') ? `${appIdKey}` : `PID:${appIdKey}`;
|
|
257
|
-
this.pageIdKey = pageIdKey;
|
|
258
|
-
|
|
259
|
-
this.log.debug(`Selecting page '${pageIdKey}' on app '${this.appIdKey}' and forwarding socket setup`);
|
|
260
|
-
|
|
261
|
-
const timer = new timing.Timer().start();
|
|
262
|
-
|
|
263
|
-
await this.requireRpcClient().selectPage(this.appIdKey, pageIdKey);
|
|
264
|
-
|
|
265
|
-
// make sure everything is ready to go
|
|
266
|
-
if (!skipReadyCheck && !await this.checkPageIsReady()) {
|
|
267
|
-
await this.waitForDom();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
this.log.debug(`Selected page after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
273
|
/**
|
|
274
274
|
* @this {RemoteDebugger}
|
|
275
275
|
* @returns {void}
|
|
276
276
|
*/
|
|
277
277
|
function logApplicationDictionary () {
|
|
278
278
|
this.log.debug('Current applications available:');
|
|
279
|
-
for (const [app, info] of _.toPairs(this.
|
|
279
|
+
for (const [app, info] of _.toPairs(this._appDict)) {
|
|
280
280
|
this.log.debug(` Application: "${app}"`);
|
|
281
281
|
for (const [key, value] of _.toPairs(info)) {
|
|
282
282
|
if (key === 'pageArray' && Array.isArray(value) && value.length) {
|
|
@@ -307,7 +307,7 @@ function logApplicationDictionary () {
|
|
|
307
307
|
export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
308
308
|
if (bundleIds.includes(WILDCARD_BUNDLE_ID)) {
|
|
309
309
|
this.log.debug('Skip checking bundle identifiers because the bundleIds includes a wildcard');
|
|
310
|
-
return _.uniq(Object.keys(this.
|
|
310
|
+
return _.uniq(Object.keys(this._appDict));
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
// go through the possible bundle identifiers
|
|
@@ -324,10 +324,10 @@ export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
|
324
324
|
const proxiedAppIds = new Set();
|
|
325
325
|
for (const bundleId of possibleBundleIds) {
|
|
326
326
|
// now we need to determine if we should pick a proxy for this instead
|
|
327
|
-
for (const appId of appIdsForBundle(bundleId, this.
|
|
327
|
+
for (const appId of appIdsForBundle(bundleId, this._appDict)) {
|
|
328
328
|
proxiedAppIds.add(appId);
|
|
329
329
|
this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
|
|
330
|
-
for (const [key, data] of _.toPairs(this.
|
|
330
|
+
for (const [key, data] of _.toPairs(this._appDict)) {
|
|
331
331
|
if (data.isProxy && data.hostId === appId) {
|
|
332
332
|
this.log.debug(
|
|
333
333
|
`Found separate bundleId '${data.bundleId}' ` +
|
|
@@ -343,5 +343,19 @@ export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
/**
|
|
346
|
-
* @typedef {
|
|
346
|
+
* @typedef {Object} HasConnectionRelatedProperties
|
|
347
|
+
* @property {string | null | undefined} _appIdKey
|
|
348
|
+
* @property {string | number | null | undefined} _pageIdKey
|
|
349
|
+
* @property {import('../types').AppDict} _appDict
|
|
350
|
+
* @property {string | undefined} _bundleId
|
|
351
|
+
* @property {import('../rpc/rpc-client').RpcClient | undefined} _rpcClient
|
|
352
|
+
* @property {boolean} _includeSafari
|
|
353
|
+
* @property {boolean} _isSafari
|
|
354
|
+
* @property {string[]} _additionalBundleIds
|
|
355
|
+
* @property {(this: RemoteDebugger, timeoutMs?: number | undefined) => Promise<boolean>} checkPageIsReady:
|
|
356
|
+
* @property {(this: RemoteDebugger, startPageLoadTimer?: timing.Timer | null | undefined) => Promise<void>} waitForDom:
|
|
357
|
+
*/
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasConnectionRelatedProperties} RemoteDebugger
|
|
347
361
|
*/
|
package/lib/mixins/cookies.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
export async function getCookies () {
|
|
8
8
|
this.log.debug('Getting cookies');
|
|
9
9
|
return await this.requireRpcClient().send('Page.getCookies', {
|
|
10
|
-
appIdKey: this.
|
|
11
|
-
pageIdKey: this.
|
|
10
|
+
appIdKey: this._appIdKey,
|
|
11
|
+
pageIdKey: this._pageIdKey
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -21,8 +21,8 @@ export async function getCookies () {
|
|
|
21
21
|
export async function setCookie (cookie) {
|
|
22
22
|
this.log.debug('Setting cookie');
|
|
23
23
|
return await this.requireRpcClient().send('Page.setCookie', {
|
|
24
|
-
appIdKey: this.
|
|
25
|
-
pageIdKey: this.
|
|
24
|
+
appIdKey: this._appIdKey,
|
|
25
|
+
pageIdKey: this._pageIdKey,
|
|
26
26
|
cookie
|
|
27
27
|
});
|
|
28
28
|
}
|
|
@@ -37,13 +37,19 @@ export async function setCookie (cookie) {
|
|
|
37
37
|
export async function deleteCookie (cookieName, url) {
|
|
38
38
|
this.log.debug(`Deleting cookie '${cookieName}' on '${url}'`);
|
|
39
39
|
return await this.requireRpcClient().send('Page.deleteCookie', {
|
|
40
|
-
appIdKey: this.
|
|
41
|
-
pageIdKey: this.
|
|
40
|
+
appIdKey: this._appIdKey,
|
|
41
|
+
pageIdKey: this._pageIdKey,
|
|
42
42
|
cookieName,
|
|
43
43
|
url,
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* @typedef {
|
|
48
|
+
* @typedef {Object} HasCookiesRelatedProperties
|
|
49
|
+
* @property {string | null | undefined} _appIdKey
|
|
50
|
+
* @property {string | number | null | undefined} _pageIdKey
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasCookiesRelatedProperties} RemoteDebugger
|
|
49
55
|
*/
|
package/lib/mixins/events.js
CHANGED
|
@@ -10,7 +10,7 @@ export const events = {
|
|
|
10
10
|
*
|
|
11
11
|
* @this {RemoteDebugger}
|
|
12
12
|
* @param {string} eventName
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {import('../types').EventListener} listener
|
|
14
14
|
* @returns {void}
|
|
15
15
|
*/
|
|
16
16
|
export function addClientEventListener (eventName, listener) {
|
|
@@ -30,8 +30,53 @@ export function removeClientEventListener (eventName) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @this {RemoteDebugger}
|
|
35
|
+
* @param {import('../types').EventListener} listener
|
|
36
|
+
* @returns {void}
|
|
37
|
+
*/
|
|
38
|
+
export function startConsole (listener) {
|
|
39
|
+
this.log.debug('Starting to listen for JavaScript console');
|
|
40
|
+
this.addClientEventListener('Console.messageAdded', listener);
|
|
41
|
+
this.addClientEventListener('Console.messageRepeatCountUpdated', listener);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @this {RemoteDebugger}
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
export function stopConsole () {
|
|
49
|
+
this.log.debug('Stopping to listen for JavaScript console');
|
|
50
|
+
this.removeClientEventListener('Console.messageAdded');
|
|
51
|
+
this.removeClientEventListener('Console.messageRepeatCountUpdated');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @this {RemoteDebugger}
|
|
56
|
+
* @param {import('../types').EventListener} listener
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
export function startNetwork (listener) {
|
|
60
|
+
this.log.debug('Starting to listen for network events');
|
|
61
|
+
this.addClientEventListener('NetworkEvent', listener);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @this {RemoteDebugger}
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*/
|
|
68
|
+
export function stopNetwork () {
|
|
69
|
+
this.log.debug('Stopping to listen for network events');
|
|
70
|
+
this.removeClientEventListener('NetworkEvent');
|
|
71
|
+
}
|
|
72
|
+
|
|
33
73
|
export default events;
|
|
34
74
|
|
|
35
75
|
/**
|
|
36
|
-
* @typedef {
|
|
76
|
+
* @typedef {Object} HasEventsRelatedProperties
|
|
77
|
+
* @property {import('@appium/types').StringRecord<import('../types').EventListener[]>} _clientEventListeners:
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasEventsRelatedProperties} RemoteDebugger
|
|
37
82
|
*/
|
package/lib/mixins/execute.js
CHANGED
|
@@ -36,8 +36,8 @@ export async function executeAtom (atom, args = [], frames = []) {
|
|
|
36
36
|
export async function executeAtomAsync (atom, args = [], frames = []) {
|
|
37
37
|
// helper to send directly to the web inspector
|
|
38
38
|
const evaluate = async (method, opts) => await this.requireRpcClient(true).send(method, Object.assign({
|
|
39
|
-
appIdKey: this.
|
|
40
|
-
pageIdKey: this.
|
|
39
|
+
appIdKey: this._appIdKey,
|
|
40
|
+
pageIdKey: this._pageIdKey,
|
|
41
41
|
returnByValue: false,
|
|
42
42
|
}, opts));
|
|
43
43
|
|
|
@@ -125,19 +125,19 @@ export async function executeAtomAsync (atom, args = [], frames = []) {
|
|
|
125
125
|
*/
|
|
126
126
|
export async function execute (command, override) {
|
|
127
127
|
// if the page is not loaded yet, wait for it
|
|
128
|
-
if (this.
|
|
128
|
+
if (this._pageLoading && !override) {
|
|
129
129
|
this.log.debug('Trying to execute but page is not loaded.');
|
|
130
130
|
await this.waitForDom();
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
if (_.isNil(this.
|
|
133
|
+
if (_.isNil(this._appIdKey)) {
|
|
134
134
|
throw new Error('Missing parameter: appIdKey. Is the target web application still alive?');
|
|
135
135
|
}
|
|
136
|
-
if (_.isNil(this.
|
|
136
|
+
if (_.isNil(this._pageIdKey)) {
|
|
137
137
|
throw new Error('Missing parameter: pageIdKey. Is the target web page still alive?');
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
if (this.
|
|
140
|
+
if (this._garbageCollectOnExecute) {
|
|
141
141
|
await this.garbageCollect();
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -145,8 +145,8 @@ export async function execute (command, override) {
|
|
|
145
145
|
const res = await this.requireRpcClient(true).send('Runtime.evaluate', {
|
|
146
146
|
expression: command,
|
|
147
147
|
returnByValue: true,
|
|
148
|
-
appIdKey: this.
|
|
149
|
-
pageIdKey: this.
|
|
148
|
+
appIdKey: this._appIdKey,
|
|
149
|
+
pageIdKey: this._pageIdKey,
|
|
150
150
|
});
|
|
151
151
|
return convertResult(res);
|
|
152
152
|
}
|
|
@@ -158,9 +158,9 @@ export async function execute (command, override) {
|
|
|
158
158
|
* @param {any[]} [args]
|
|
159
159
|
*/
|
|
160
160
|
export async function callFunction (objectId, fn, args) {
|
|
161
|
-
checkParams({appIdKey: this.
|
|
161
|
+
checkParams({appIdKey: this._appIdKey, pageIdKey: this._pageIdKey});
|
|
162
162
|
|
|
163
|
-
if (this.
|
|
163
|
+
if (this._garbageCollectOnExecute) {
|
|
164
164
|
await this.garbageCollect();
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -170,13 +170,22 @@ export async function callFunction (objectId, fn, args) {
|
|
|
170
170
|
functionDeclaration: fn,
|
|
171
171
|
arguments: args,
|
|
172
172
|
returnByValue: true,
|
|
173
|
-
appIdKey: this.
|
|
174
|
-
pageIdKey: this.
|
|
173
|
+
appIdKey: this._appIdKey,
|
|
174
|
+
pageIdKey: this._pageIdKey,
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
return convertResult(res);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
|
-
* @typedef {
|
|
181
|
+
* @typedef {Object} HasExecutionRelatedProperties
|
|
182
|
+
* @property {string | null | undefined} _appIdKey
|
|
183
|
+
* @property {string | number | null | undefined} _pageIdKey
|
|
184
|
+
* @property {boolean} _pageLoading
|
|
185
|
+
* @property {boolean} _garbageCollectOnExecute
|
|
186
|
+
* @property {(this: RemoteDebugger, startPageLoadTimer?: timing.Timer | null | undefined) => Promise<void>} waitForDom:
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasExecutionRelatedProperties} RemoteDebugger
|
|
182
191
|
*/
|
|
@@ -26,8 +26,8 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
26
26
|
|
|
27
27
|
const currentPages = pageArrayFromDict(pageDict);
|
|
28
28
|
// save the page dict for this app
|
|
29
|
-
if (this.
|
|
30
|
-
const previousPages = this.
|
|
29
|
+
if (this._appDict[appIdKey]) {
|
|
30
|
+
const previousPages = this._appDict[appIdKey].pageArray;
|
|
31
31
|
// we have a pre-existing pageDict
|
|
32
32
|
if (previousPages && _.isEqual(previousPages, currentPages)) {
|
|
33
33
|
this.log.debug(
|
|
@@ -37,7 +37,7 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
// keep track of the page dictionary
|
|
40
|
-
this.
|
|
40
|
+
this._appDict[appIdKey].pageArray = currentPages;
|
|
41
41
|
this.log.debug(
|
|
42
42
|
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}`
|
|
43
43
|
);
|
|
@@ -76,22 +76,21 @@ export async function onAppConnect (err, dict) {
|
|
|
76
76
|
export function onAppDisconnect (err, dict) {
|
|
77
77
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
78
78
|
this.log.debug(`Application '${appIdKey}' disconnected. Removing from app dictionary.`);
|
|
79
|
-
this.log.debug(`Current app is '${this.
|
|
79
|
+
this.log.debug(`Current app is '${this._appIdKey}'`);
|
|
80
80
|
|
|
81
81
|
// get rid of the entry in our app dictionary,
|
|
82
82
|
// since it is no longer available
|
|
83
|
-
delete this.
|
|
83
|
+
delete this._appDict[appIdKey];
|
|
84
84
|
|
|
85
85
|
// if the disconnected app is the one we are connected to, try to find another
|
|
86
|
-
if (this.
|
|
86
|
+
if (this._appIdKey === appIdKey) {
|
|
87
87
|
this.log.debug(`No longer have app id. Attempting to find new one.`);
|
|
88
|
-
this.
|
|
88
|
+
this._appIdKey = getDebuggerAppKey.bind(this)(/** @type {string} */ (this._bundleId));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
if (!this.
|
|
91
|
+
if (!this._appDict) {
|
|
92
92
|
// this means we no longer have any apps. what the what?
|
|
93
93
|
this.log.debug('Main app disconnected. Disconnecting altogether.');
|
|
94
|
-
this.connected = false;
|
|
95
94
|
this.emit(events.EVENT_DISCONNECT, true);
|
|
96
95
|
}
|
|
97
96
|
}
|
|
@@ -115,8 +114,8 @@ export async function onAppUpdate (err, dict) {
|
|
|
115
114
|
* @returns {void}
|
|
116
115
|
*/
|
|
117
116
|
export function onConnectedDriverList (err, drivers) {
|
|
118
|
-
this.
|
|
119
|
-
this.log.debug(`Received connected driver list: ${JSON.stringify(this.
|
|
117
|
+
this._connectedDrivers = drivers.WIRDriverDictionaryKey;
|
|
118
|
+
this.log.debug(`Received connected driver list: ${JSON.stringify(this._connectedDrivers)}`);
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
/**
|
|
@@ -126,10 +125,10 @@ export function onConnectedDriverList (err, drivers) {
|
|
|
126
125
|
* @returns {void}
|
|
127
126
|
*/
|
|
128
127
|
export function onCurrentState (err, state) {
|
|
129
|
-
this.
|
|
128
|
+
this._currentState = state.WIRAutomationAvailabilityKey;
|
|
130
129
|
// This state changes when 'Remote Automation' in 'Settings app' > 'Safari' > 'Advanced' > 'Remote Automation' changes
|
|
131
130
|
// WIRAutomationAvailabilityAvailable or WIRAutomationAvailabilityNotAvailable
|
|
132
|
-
this.log.debug(`Received connected automation availability state: ${JSON.stringify(this.
|
|
131
|
+
this.log.debug(`Received connected automation availability state: ${JSON.stringify(this._currentState)}`);
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
/**
|
|
@@ -147,13 +146,13 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
147
146
|
let newDict = {};
|
|
148
147
|
for (const dict of _.values(apps)) {
|
|
149
148
|
const [id, entry] = appInfoFromDict(dict);
|
|
150
|
-
if (this.
|
|
149
|
+
if (this._skippedApps.includes(entry.name)) {
|
|
151
150
|
continue;
|
|
152
151
|
}
|
|
153
152
|
newDict[id] = entry;
|
|
154
153
|
}
|
|
155
154
|
// update the object's list of apps
|
|
156
|
-
_.defaults(this.
|
|
155
|
+
_.defaults(this._appDict, newDict);
|
|
157
156
|
}
|
|
158
157
|
|
|
159
158
|
/**
|
|
@@ -165,17 +164,17 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
165
164
|
function updateAppsWithDict (dict) {
|
|
166
165
|
// get the dictionary entry into a nice form, and add it to the
|
|
167
166
|
// application dictionary
|
|
168
|
-
this.
|
|
167
|
+
this._appDict ??= {};
|
|
169
168
|
const [id, entry] = appInfoFromDict(dict);
|
|
170
|
-
if (this.
|
|
169
|
+
if (this._appDict[id]) {
|
|
171
170
|
// preserve the page dictionary for this entry
|
|
172
|
-
entry.pageArray = this.
|
|
171
|
+
entry.pageArray = this._appDict[id].pageArray;
|
|
173
172
|
}
|
|
174
|
-
this.
|
|
173
|
+
this._appDict[id] = entry;
|
|
175
174
|
|
|
176
175
|
// try to get the app id from our connected apps
|
|
177
|
-
if (!this.
|
|
178
|
-
this.
|
|
176
|
+
if (!this._appIdKey) {
|
|
177
|
+
this._appIdKey = getDebuggerAppKey.bind(this)(/** @type {string} */ (this._bundleId));
|
|
179
178
|
}
|
|
180
179
|
}
|
|
181
180
|
|
|
@@ -189,7 +188,7 @@ function updateAppsWithDict (dict) {
|
|
|
189
188
|
*/
|
|
190
189
|
export function getDebuggerAppKey (bundleId) {
|
|
191
190
|
let appId;
|
|
192
|
-
for (const [key, data] of _.toPairs(this.
|
|
191
|
+
for (const [key, data] of _.toPairs(this._appDict)) {
|
|
193
192
|
if (data.bundleId === bundleId) {
|
|
194
193
|
appId = key;
|
|
195
194
|
break;
|
|
@@ -199,7 +198,7 @@ export function getDebuggerAppKey (bundleId) {
|
|
|
199
198
|
if (appId) {
|
|
200
199
|
this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
|
|
201
200
|
let proxyAppId;
|
|
202
|
-
for (const [key, data] of _.toPairs(this.
|
|
201
|
+
for (const [key, data] of _.toPairs(this._appDict)) {
|
|
203
202
|
if (data.isProxy && data.hostId === appId) {
|
|
204
203
|
this.log.debug(`Found separate bundleId '${data.bundleId}' ` +
|
|
205
204
|
`acting as proxy for '${bundleId}', with app id '${key}'`);
|
|
@@ -217,5 +216,17 @@ export function getDebuggerAppKey (bundleId) {
|
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
/**
|
|
220
|
-
* @typedef {
|
|
219
|
+
* @typedef {Object} HasMessageHandlersRelatedProperties
|
|
220
|
+
* @property {string | null | undefined} _appIdKey
|
|
221
|
+
* @property {string | number | null | undefined} _pageIdKey
|
|
222
|
+
* @property {import('../types').AppDict} _appDict
|
|
223
|
+
* @property {boolean} _navigatingToPage
|
|
224
|
+
* @property {string | undefined} _currentState
|
|
225
|
+
* @property {string | undefined} _bundleId
|
|
226
|
+
* @property {string[] | undefined} _connectedDrivers
|
|
227
|
+
* @property {string[]} _skippedApps
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasMessageHandlersRelatedProperties} RemoteDebugger
|
|
221
232
|
*/
|
package/lib/mixins/misc.js
CHANGED
|
@@ -16,15 +16,15 @@ export async function launchSafari () {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @this {RemoteDebugger}
|
|
19
|
-
* @param {
|
|
19
|
+
* @param {import('../types').EventListener} fn
|
|
20
20
|
* @returns {Promise<any>}
|
|
21
21
|
*/
|
|
22
22
|
export async function startTimeline (fn) {
|
|
23
23
|
this.log.debug('Starting to record the timeline');
|
|
24
24
|
this.requireRpcClient().on('Timeline.eventRecorded', fn);
|
|
25
25
|
return await this.requireRpcClient().send('Timeline.start', {
|
|
26
|
-
appIdKey: this.
|
|
27
|
-
pageIdKey: this.
|
|
26
|
+
appIdKey: this._appIdKey,
|
|
27
|
+
pageIdKey: this._pageIdKey,
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -35,51 +35,11 @@ export async function startTimeline (fn) {
|
|
|
35
35
|
export async function stopTimeline () {
|
|
36
36
|
this.log.debug('Stopping to record the timeline');
|
|
37
37
|
await this.requireRpcClient().send('Timeline.stop', {
|
|
38
|
-
appIdKey: this.
|
|
39
|
-
pageIdKey: this.
|
|
38
|
+
appIdKey: this._appIdKey,
|
|
39
|
+
pageIdKey: this._pageIdKey,
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* @this {RemoteDebugger}
|
|
45
|
-
* @param {(event: import('@appium/types').StringRecord) => any} listener
|
|
46
|
-
* @returns {void}
|
|
47
|
-
*/
|
|
48
|
-
export function startConsole (listener) {
|
|
49
|
-
this.log.debug('Starting to listen for JavaScript console');
|
|
50
|
-
this.addClientEventListener('Console.messageAdded', listener);
|
|
51
|
-
this.addClientEventListener('Console.messageRepeatCountUpdated', listener);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @this {RemoteDebugger}
|
|
56
|
-
* @returns {void}
|
|
57
|
-
*/
|
|
58
|
-
export function stopConsole () {
|
|
59
|
-
this.log.debug('Stopping to listen for JavaScript console');
|
|
60
|
-
this.removeClientEventListener('Console.messageAdded');
|
|
61
|
-
this.removeClientEventListener('Console.messageRepeatCountUpdated');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @this {RemoteDebugger}
|
|
66
|
-
* @param {(event: import('@appium/types').StringRecord) => any} listener
|
|
67
|
-
* @returns {void}
|
|
68
|
-
*/
|
|
69
|
-
export function startNetwork (listener) {
|
|
70
|
-
this.log.debug('Starting to listen for network events');
|
|
71
|
-
this.addClientEventListener('NetworkEvent', listener);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @this {RemoteDebugger}
|
|
76
|
-
* @returns {void}
|
|
77
|
-
*/
|
|
78
|
-
export function stopNetwork () {
|
|
79
|
-
this.log.debug('Stopping to listen for network events');
|
|
80
|
-
this.removeClientEventListener('NetworkEvent');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
43
|
// Potentially this does not work for mobile safari
|
|
84
44
|
/**
|
|
85
45
|
* @this {RemoteDebugger}
|
|
@@ -89,8 +49,8 @@ export function stopNetwork () {
|
|
|
89
49
|
export async function overrideUserAgent (value) {
|
|
90
50
|
this.log.debug('Setting overrideUserAgent');
|
|
91
51
|
return await this.requireRpcClient().send('Page.overrideUserAgent', {
|
|
92
|
-
appIdKey: this.
|
|
93
|
-
pageIdKey: this.
|
|
52
|
+
appIdKey: this._appIdKey,
|
|
53
|
+
pageIdKey: this._pageIdKey,
|
|
94
54
|
value
|
|
95
55
|
});
|
|
96
56
|
}
|
|
@@ -104,7 +64,7 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
104
64
|
this.log.debug(`Garbage collecting with ${timeoutMs}ms timeout`);
|
|
105
65
|
|
|
106
66
|
try {
|
|
107
|
-
checkParams({appIdKey: this.
|
|
67
|
+
checkParams({appIdKey: this._appIdKey, pageIdKey: this._pageIdKey});
|
|
108
68
|
} catch (err) {
|
|
109
69
|
this.log.debug(`Unable to collect garbage at this time`);
|
|
110
70
|
return;
|
|
@@ -113,8 +73,8 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
113
73
|
try {
|
|
114
74
|
await B.resolve(this.requireRpcClient().send(
|
|
115
75
|
'Heap.gc', {
|
|
116
|
-
appIdKey: this.
|
|
117
|
-
pageIdKey: this.
|
|
76
|
+
appIdKey: this._appIdKey,
|
|
77
|
+
pageIdKey: this._pageIdKey,
|
|
118
78
|
})
|
|
119
79
|
).timeout(timeoutMs);
|
|
120
80
|
this.log.debug(`Garbage collection successful`);
|
|
@@ -128,5 +88,11 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
128
88
|
}
|
|
129
89
|
|
|
130
90
|
/**
|
|
131
|
-
* @typedef {
|
|
91
|
+
* @typedef {Object} HasMiscRelatedProperties
|
|
92
|
+
* @property {string | null | undefined} _appIdKey
|
|
93
|
+
* @property {string | number | null | undefined} _pageIdKey
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {import('../remote-debugger').RemoteDebugger & HasMiscRelatedProperties} RemoteDebugger
|
|
132
98
|
*/
|