appium-remote-debugger 11.5.4 → 11.5.5
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 +6 -0
- package/build/lib/mixins/connect.d.ts +15 -41
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +80 -95
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts +4 -4
- package/build/lib/mixins/message-handlers.d.ts.map +1 -1
- package/build/lib/mixins/message-handlers.js +25 -67
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +0 -2
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +0 -2
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client.js +14 -17
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/utils.d.ts +14 -7
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +15 -20
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/mixins/connect.js +84 -105
- package/lib/mixins/message-handlers.js +30 -70
- package/lib/remote-debugger.js +1 -3
- package/lib/rpc/rpc-client.js +13 -18
- package/lib/utils.js +15 -20
- package/package.json +1 -2
package/lib/mixins/connect.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pageArrayFromDict,
|
|
3
3
|
getPossibleDebuggerAppKeys,
|
|
4
|
-
simpleStringify,
|
|
5
4
|
} from '../utils';
|
|
6
5
|
import events from './events';
|
|
7
6
|
import { timing } from '@appium/support';
|
|
8
7
|
import { retryInterval, waitForCondition } from 'asyncbox';
|
|
9
8
|
import _ from 'lodash';
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
const APP_CONNECT_TIMEOUT_MS = 0;
|
|
13
11
|
const APP_CONNECT_INTERVAL_MS = 100;
|
|
14
12
|
const SELECT_APP_RETRIES = 20;
|
|
@@ -16,19 +14,6 @@ const SELECT_APP_RETRY_SLEEP_MS = 500;
|
|
|
16
14
|
const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
|
|
17
15
|
const BLANK_PAGE_URL = 'about:blank';
|
|
18
16
|
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {Object} AppPages
|
|
21
|
-
* @property {string} appIdKey
|
|
22
|
-
* @property {Record<string, any>} pageDict
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {Object} App
|
|
27
|
-
* @property {string} id
|
|
28
|
-
* @property {string} bundleId
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
17
|
/**
|
|
33
18
|
*
|
|
34
19
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
@@ -104,21 +89,12 @@ export async function disconnect () {
|
|
|
104
89
|
this.teardown();
|
|
105
90
|
}
|
|
106
91
|
|
|
107
|
-
/**
|
|
108
|
-
* @typedef {Object} Page
|
|
109
|
-
* @property {string} url
|
|
110
|
-
* @property {string} title
|
|
111
|
-
* @property {number} id
|
|
112
|
-
* @property {boolean} isKey
|
|
113
|
-
* @property {string} [bundleId]
|
|
114
|
-
*/
|
|
115
|
-
|
|
116
92
|
/**
|
|
117
93
|
*
|
|
118
94
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
119
|
-
* @param {string?} currentUrl
|
|
120
|
-
* @param {number} [maxTries]
|
|
121
|
-
* @param {boolean} [ignoreAboutBlankUrl]
|
|
95
|
+
* @param {string?} [currentUrl=null]
|
|
96
|
+
* @param {number} [maxTries=SELECT_APP_RETRIES]
|
|
97
|
+
* @param {boolean} [ignoreAboutBlankUrl=false]
|
|
122
98
|
* @returns {Promise<Page[]>}
|
|
123
99
|
*/
|
|
124
100
|
export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIES, ignoreAboutBlankUrl = false) {
|
|
@@ -134,25 +110,14 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
134
110
|
return [];
|
|
135
111
|
}
|
|
136
112
|
|
|
137
|
-
const {appIdKey
|
|
138
|
-
|
|
139
|
-
// if, after all this, we have no dictionary, we have failed
|
|
140
|
-
if (!appIdKey || !pageDict) {
|
|
141
|
-
throw this.log.errorWithException(`Could not connect to a valid app after ${maxTries} tries.`);
|
|
142
|
-
}
|
|
143
|
-
|
|
113
|
+
const { appIdKey } = await this.searchForApp(currentUrl, maxTries, ignoreAboutBlankUrl);
|
|
144
114
|
if (this.appIdKey !== appIdKey) {
|
|
145
115
|
this.log.debug(`Received altered app id, updating from '${this.appIdKey}' to '${appIdKey}'`);
|
|
146
116
|
this.appIdKey = appIdKey;
|
|
147
117
|
}
|
|
148
|
-
|
|
149
|
-
logApplicationDictionary.bind(this)(this.appDict);
|
|
150
|
-
|
|
118
|
+
logApplicationDictionary.bind(this)();
|
|
151
119
|
// translate the dictionary into a useful form, and return to sender
|
|
152
|
-
|
|
153
|
-
? pageArrayFromDict(pageDict)
|
|
154
|
-
: this.appDict[appIdKey].pageArray;
|
|
155
|
-
this.log.debug(`Finally selecting app ${this.appIdKey}: ${simpleStringify(pageArray)}`);
|
|
120
|
+
this.log.debug(`Finally selecting app ${this.appIdKey}`);
|
|
156
121
|
|
|
157
122
|
/** @type {Page[]} */
|
|
158
123
|
const fullPageArray = [];
|
|
@@ -184,80 +149,85 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
184
149
|
* @param {string?} currentUrl
|
|
185
150
|
* @param {number} maxTries
|
|
186
151
|
* @param {boolean} ignoreAboutBlankUrl
|
|
187
|
-
* @returns {Promise<
|
|
152
|
+
* @returns {Promise<AppPage>}
|
|
188
153
|
*/
|
|
189
154
|
export async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
190
155
|
const bundleIds = this.includeSafari && !this.isSafari
|
|
191
156
|
? [this.bundleId, ...this.additionalBundleIds, SAFARI_BUNDLE_ID]
|
|
192
157
|
: [this.bundleId, ...this.additionalBundleIds];
|
|
193
158
|
let retryCount = 0;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
159
|
+
return /** @type {AppPage} */ (await retryInterval(maxTries, SELECT_APP_RETRY_SLEEP_MS, async () => {
|
|
160
|
+
logApplicationDictionary.bind(this)();
|
|
161
|
+
const possibleAppIds = getPossibleDebuggerAppKeys(/** @type {string[]} */ (bundleIds), this.appDict);
|
|
162
|
+
this.log.debug(`Trying out the possible app ids: ${possibleAppIds.join(', ')} (try #${retryCount + 1} of ${maxTries})`);
|
|
163
|
+
for (const attemptedAppIdKey of possibleAppIds) {
|
|
164
|
+
try {
|
|
165
|
+
if (!this.appDict[attemptedAppIdKey].isActive) {
|
|
166
|
+
this.log.debug(`Skipping app '${attemptedAppIdKey}' because it is not active`);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.log.debug(`Attempting app '${attemptedAppIdKey}'`);
|
|
171
|
+
/** @type {string} */
|
|
172
|
+
let appIdKey;
|
|
173
|
+
/** @type {import('@appium/types').StringRecord} */
|
|
174
|
+
let pageDict;
|
|
200
175
|
try {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const [appIdKey, pageDict] = await this.requireRpcClient().selectApp(attemptedAppIdKey);
|
|
207
|
-
// in iOS 8.2 the connect logic happens, but with an empty dictionary
|
|
208
|
-
// which leads to the remote debugger getting disconnected, and into a loop
|
|
209
|
-
if (_.isEmpty(pageDict)) {
|
|
210
|
-
this.log.debug('Empty page dictionary received. Trying again.');
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
176
|
+
[appIdKey, pageDict] = await this.requireRpcClient().selectApp(attemptedAppIdKey);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
this.log.info(`Skipping app '${attemptedAppIdKey}'. Original error: ${e.message}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
213
181
|
|
|
214
|
-
|
|
215
|
-
|
|
182
|
+
// save the page array for this app
|
|
183
|
+
this.appDict[appIdKey].pageArray = pageArrayFromDict(pageDict);
|
|
216
184
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
185
|
+
// if we are looking for a particular url, make sure we
|
|
186
|
+
// have the right page. Ignore empty or undefined urls.
|
|
187
|
+
// Ignore about:blank if requested.
|
|
188
|
+
const result = this.searchForPage(this.appDict, currentUrl, ignoreAboutBlankUrl);
|
|
189
|
+
if (result) {
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
224
192
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
} catch (err) {
|
|
231
|
-
this.log.debug(`Error checking application: '${err.message}'. Retrying connection`);
|
|
193
|
+
if (currentUrl) {
|
|
194
|
+
this.log.debug(`Received app, but expected url ('${currentUrl}') was not found. Trying again.`);
|
|
195
|
+
} else {
|
|
196
|
+
this.log.debug('Received app, but no match was found. Trying again.');
|
|
232
197
|
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
this.log.debug(err.stack);
|
|
200
|
+
this.log.warn(`Error checking application ${attemptedAppIdKey}: '${err.message}'`);
|
|
233
201
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
202
|
+
}
|
|
203
|
+
retryCount++;
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Could not connect to a valid webapp. Make sure it is debuggable and has at least one active page.`
|
|
206
|
+
);
|
|
207
|
+
}));
|
|
241
208
|
}
|
|
242
209
|
|
|
243
210
|
/**
|
|
244
211
|
*
|
|
245
212
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
246
|
-
* @param {Record<string,
|
|
213
|
+
* @param {Record<string, import('../utils').AppInfo>} appsDict
|
|
247
214
|
* @param {string?} currentUrl
|
|
248
215
|
* @param {boolean} [ignoreAboutBlankUrl]
|
|
249
|
-
* @returns {
|
|
216
|
+
* @returns {AppPage?}
|
|
250
217
|
*/
|
|
251
218
|
export function searchForPage (appsDict, currentUrl = null, ignoreAboutBlankUrl = false) {
|
|
252
219
|
for (const appDict of _.values(appsDict)) {
|
|
253
|
-
if (!appDict || !appDict.isActive || !appDict.pageArray || appDict.pageArray
|
|
220
|
+
if (!appDict || !appDict.isActive || !appDict.pageArray || _.isEmpty(appDict.pageArray)) {
|
|
254
221
|
continue;
|
|
255
222
|
}
|
|
256
223
|
|
|
257
|
-
for (const
|
|
258
|
-
if ((!ignoreAboutBlankUrl ||
|
|
259
|
-
(!currentUrl ||
|
|
260
|
-
return {
|
|
224
|
+
for (const page of appDict.pageArray) {
|
|
225
|
+
if ((!ignoreAboutBlankUrl || page.url !== BLANK_PAGE_URL) &&
|
|
226
|
+
(!currentUrl || page.url === currentUrl || page.url === `${currentUrl}/`)) {
|
|
227
|
+
return {
|
|
228
|
+
appIdKey: appDict.id,
|
|
229
|
+
pageDict: page
|
|
230
|
+
};
|
|
261
231
|
}
|
|
262
232
|
}
|
|
263
233
|
}
|
|
@@ -292,23 +262,11 @@ export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
|
292
262
|
|
|
293
263
|
/**
|
|
294
264
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
295
|
-
* @param {Record<string, any>} apps
|
|
296
265
|
* @returns {void}
|
|
297
266
|
*/
|
|
298
|
-
function logApplicationDictionary (
|
|
299
|
-
|
|
300
|
-
function getValueString (key, value) {
|
|
301
|
-
if (_.isFunction(value)) {
|
|
302
|
-
return '[Function]';
|
|
303
|
-
}
|
|
304
|
-
if (key === 'pageArray' && !_.isArray(value)) {
|
|
305
|
-
return `"Waiting for data"`;
|
|
306
|
-
}
|
|
307
|
-
return JSON.stringify(value);
|
|
308
|
-
}
|
|
309
|
-
|
|
267
|
+
function logApplicationDictionary () {
|
|
310
268
|
this.log.debug('Current applications available:');
|
|
311
|
-
for (const [app, info] of _.toPairs(
|
|
269
|
+
for (const [app, info] of _.toPairs(this.appDict)) {
|
|
312
270
|
this.log.debug(` Application: "${app}"`);
|
|
313
271
|
for (const [key, value] of _.toPairs(info)) {
|
|
314
272
|
if (key === 'pageArray' && Array.isArray(value) && value.length) {
|
|
@@ -321,9 +279,30 @@ function logApplicationDictionary (apps) {
|
|
|
321
279
|
}
|
|
322
280
|
}
|
|
323
281
|
} else {
|
|
324
|
-
const valueString =
|
|
282
|
+
const valueString = _.isFunction(value) ? '[Function]' : JSON.stringify(value);
|
|
325
283
|
this.log.debug(` ${key}: ${valueString}`);
|
|
326
284
|
}
|
|
327
285
|
}
|
|
328
286
|
}
|
|
329
287
|
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @typedef {Object} AppPage
|
|
291
|
+
* @property {string} appIdKey
|
|
292
|
+
* @property {Page} pageDict
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @typedef {Object} App
|
|
297
|
+
* @property {string} id
|
|
298
|
+
* @property {string} bundleId
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @typedef {Object} Page
|
|
303
|
+
* @property {string} url
|
|
304
|
+
* @property {string} title
|
|
305
|
+
* @property {number} id
|
|
306
|
+
* @property {boolean} isKey
|
|
307
|
+
* @property {string} [bundleId]
|
|
308
|
+
*/
|
|
@@ -2,9 +2,7 @@ import events from './events';
|
|
|
2
2
|
import {
|
|
3
3
|
pageArrayFromDict,
|
|
4
4
|
getDebuggerAppKey,
|
|
5
|
-
simpleStringify,
|
|
6
5
|
appInfoFromDict,
|
|
7
|
-
deferredPromise,
|
|
8
6
|
} from '../utils';
|
|
9
7
|
import _ from 'lodash';
|
|
10
8
|
|
|
@@ -21,48 +19,39 @@ import _ from 'lodash';
|
|
|
21
19
|
* @param {Record<string, any>} pageDict
|
|
22
20
|
* @returns {Promise<void>}
|
|
23
21
|
*/
|
|
22
|
+
// eslint-disable-next-line require-await
|
|
24
23
|
export async function onPageChange (err, appIdKey, pageDict) {
|
|
25
24
|
if (_.isEmpty(pageDict)) {
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// we have a pre-existing pageDict
|
|
41
|
-
if (_.isEqual(this.appDict[appIdKey].pageArray, pageArray)) {
|
|
42
|
-
this.log.debug(`Received page change notice for app '${appIdKey}' ` +
|
|
43
|
-
`but the listing has not changed. Ignoring.`);
|
|
44
|
-
return done();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// keep track of the page dictionary
|
|
49
|
-
this.appDict[appIdKey].pageArray = pageArray;
|
|
50
|
-
}
|
|
51
|
-
} finally {
|
|
52
|
-
done();
|
|
28
|
+
const currentPages = pageArrayFromDict(pageDict);
|
|
29
|
+
// save the page dict for this app
|
|
30
|
+
if (this.appDict[appIdKey]) {
|
|
31
|
+
const previousPages = this.appDict[appIdKey].pageArray;
|
|
32
|
+
// we have a pre-existing pageDict
|
|
33
|
+
if (previousPages && _.isEqual(previousPages, currentPages)) {
|
|
34
|
+
this.log.debug(
|
|
35
|
+
`Received page change notice for app '${appIdKey}' ` +
|
|
36
|
+
`but the listing has not changed. Ignoring.`
|
|
37
|
+
);
|
|
38
|
+
return;
|
|
53
39
|
}
|
|
54
|
-
|
|
40
|
+
// keep track of the page dictionary
|
|
41
|
+
this.appDict[appIdKey].pageArray = currentPages;
|
|
42
|
+
this.log.debug(
|
|
43
|
+
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
55
46
|
|
|
56
47
|
if (this._navigatingToPage) {
|
|
57
48
|
// in the middle of navigating, so reporting a page change will cause problems
|
|
58
49
|
return;
|
|
59
50
|
}
|
|
60
51
|
|
|
61
|
-
this.log.debug(`Page changed: ${simpleStringify(pageDict, true)}`);
|
|
62
|
-
|
|
63
52
|
this.emit(events.EVENT_PAGE_CHANGE, {
|
|
64
53
|
appIdKey: appIdKey.replace('PID:', ''),
|
|
65
|
-
pageArray,
|
|
54
|
+
pageArray: currentPages,
|
|
66
55
|
});
|
|
67
56
|
}
|
|
68
57
|
|
|
@@ -72,28 +61,23 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
72
61
|
* @param {Record<string, any>} dict
|
|
73
62
|
* @returns {Promise<void>}
|
|
74
63
|
*/
|
|
64
|
+
// eslint-disable-next-line require-await
|
|
75
65
|
export async function onAppConnect (err, dict) {
|
|
76
66
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
77
67
|
this.log.debug(`Notified that new application '${appIdKey}' has connected`);
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
updateAppsWithDict.bind(this)(dict);
|
|
81
|
-
} finally {
|
|
82
|
-
done();
|
|
83
|
-
}
|
|
84
|
-
});
|
|
68
|
+
updateAppsWithDict.bind(this)(dict);
|
|
85
69
|
}
|
|
86
70
|
|
|
87
71
|
/**
|
|
88
72
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
89
73
|
* @param {Error?} err
|
|
90
|
-
* @param {
|
|
74
|
+
* @param {import('@appium/types').StringRecord} dict
|
|
91
75
|
* @returns {void}
|
|
92
76
|
*/
|
|
93
77
|
export function onAppDisconnect (err, dict) {
|
|
94
78
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
95
79
|
this.log.debug(`Application '${appIdKey}' disconnected. Removing from app dictionary.`);
|
|
96
|
-
|
|
80
|
+
this.log.debug(`Current app is '${this.appIdKey}'`);
|
|
97
81
|
|
|
98
82
|
// get rid of the entry in our app dictionary,
|
|
99
83
|
// since it is no longer available
|
|
@@ -119,14 +103,10 @@ export function onAppDisconnect (err, dict) {
|
|
|
119
103
|
* @param {Record<string, any>} dict
|
|
120
104
|
* @returns {Promise<void>}
|
|
121
105
|
*/
|
|
106
|
+
// eslint-disable-next-line require-await
|
|
122
107
|
export async function onAppUpdate (err, dict) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
updateAppsWithDict.bind(this)(dict);
|
|
126
|
-
} finally {
|
|
127
|
-
done();
|
|
128
|
-
}
|
|
129
|
-
});
|
|
108
|
+
this.log.debug(`Notified that an application has been updated`);
|
|
109
|
+
updateAppsWithDict.bind(this)(dict);
|
|
130
110
|
}
|
|
131
111
|
|
|
132
112
|
/**
|
|
@@ -159,6 +139,7 @@ export function onCurrentState (err, state) {
|
|
|
159
139
|
* @param {Record<string, any>} apps
|
|
160
140
|
* @returns {Promise<void>}
|
|
161
141
|
*/
|
|
142
|
+
// eslint-disable-next-line require-await
|
|
162
143
|
export async function onConnectedApplicationList (err, apps) {
|
|
163
144
|
this.log.debug(`Received connected applications list: ${_.keys(apps).join(', ')}`);
|
|
164
145
|
|
|
@@ -173,25 +154,9 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
173
154
|
newDict[id] = entry;
|
|
174
155
|
}
|
|
175
156
|
// update the object's list of apps
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
_.defaults(this.appDict, newDict);
|
|
179
|
-
} finally {
|
|
180
|
-
done();
|
|
181
|
-
}
|
|
182
|
-
});
|
|
157
|
+
_.defaults(this.appDict, newDict);
|
|
183
158
|
}
|
|
184
159
|
|
|
185
|
-
/**
|
|
186
|
-
* @this {import('../remote-debugger').RemoteDebugger}
|
|
187
|
-
* @param {(done: () => any) => any} fn
|
|
188
|
-
* @returns {Promise<any>}
|
|
189
|
-
*/
|
|
190
|
-
async function useAppDictLock (fn) {
|
|
191
|
-
return await this._lock.acquire('appDict', fn);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
160
|
/**
|
|
196
161
|
*
|
|
197
162
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
@@ -201,19 +166,14 @@ async function useAppDictLock (fn) {
|
|
|
201
166
|
function updateAppsWithDict (dict) {
|
|
202
167
|
// get the dictionary entry into a nice form, and add it to the
|
|
203
168
|
// application dictionary
|
|
204
|
-
this.appDict
|
|
205
|
-
|
|
169
|
+
this.appDict ??= {};
|
|
170
|
+
const [id, entry] = appInfoFromDict(dict);
|
|
206
171
|
if (this.appDict[id]) {
|
|
207
172
|
// preserve the page dictionary for this entry
|
|
208
173
|
entry.pageArray = this.appDict[id].pageArray;
|
|
209
174
|
}
|
|
210
175
|
this.appDict[id] = entry;
|
|
211
176
|
|
|
212
|
-
// add a promise to get the page dictionary
|
|
213
|
-
if (_.isUndefined(entry.pageArray)) {
|
|
214
|
-
entry.pageArray = deferredPromise();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
177
|
// try to get the app id from our connected apps
|
|
218
178
|
if (!this.appIdKey) {
|
|
219
179
|
this.appIdKey = getDebuggerAppKey(/** @type {string} */ (this.bundleId), this.appDict);
|
package/lib/remote-debugger.js
CHANGED
|
@@ -11,7 +11,7 @@ import * as screenshotMixins from './mixins/screenshot';
|
|
|
11
11
|
import * as eventMixins from './mixins/events';
|
|
12
12
|
import * as miscellaneousMixins from './mixins/misc';
|
|
13
13
|
import _ from 'lodash';
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
|
|
16
16
|
export const REMOTE_DEBUGGER_PORT = 27753;
|
|
17
17
|
/* How many milliseconds to wait for webkit to return a response before timing out */
|
|
@@ -160,8 +160,6 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
160
160
|
this.fullPageInitialization = fullPageInitialization;
|
|
161
161
|
|
|
162
162
|
this.pageLoadStrategy = pageLoadStrategy;
|
|
163
|
-
|
|
164
|
-
this._lock = new AsyncLock();
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
/**
|
package/lib/rpc/rpc-client.js
CHANGED
|
@@ -745,29 +745,24 @@ export class RpcClient {
|
|
|
745
745
|
|
|
746
746
|
reject(new Error('New application has connected'));
|
|
747
747
|
};
|
|
748
|
-
|
|
749
|
-
this.messageHandler.prependOnceListener('_rpc_applicationConnected:', onAppChange);
|
|
748
|
+
this.messageHandler?.prependOnceListener('_rpc_applicationConnected:', onAppChange);
|
|
750
749
|
|
|
751
750
|
// do the actual connecting to the app
|
|
752
|
-
|
|
753
|
-
let pageDict, connectedAppIdKey;
|
|
751
|
+
(async () => {
|
|
754
752
|
try {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
753
|
+
const [connectedAppIdKey, pageDict] = await this.send('connectToApp', {appIdKey});
|
|
754
|
+
// sometimes the connect logic happens, but with an empty dictionary
|
|
755
|
+
// which leads to the remote debugger getting disconnected, and into a loop
|
|
756
|
+
if (_.isEmpty(pageDict)) {
|
|
757
|
+
reject(new Error('Empty page dictionary received'));
|
|
758
|
+
} else {
|
|
759
|
+
resolve([connectedAppIdKey, pageDict]);
|
|
760
|
+
}
|
|
758
761
|
} catch (err) {
|
|
759
|
-
log.warn(`Unable to connect to app: ${err.message}`);
|
|
762
|
+
log.warn(`Unable to connect to the app: ${err.message}`);
|
|
760
763
|
reject(err);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
// sometimes the connect logic happens, but with an empty dictionary
|
|
764
|
-
// which leads to the remote debugger getting disconnected, and into a loop
|
|
765
|
-
if (_.isEmpty(pageDict)) {
|
|
766
|
-
let msg = 'Empty page dictionary received';
|
|
767
|
-
log.debug(msg);
|
|
768
|
-
reject(new Error(msg));
|
|
769
|
-
} else {
|
|
770
|
-
resolve([connectedAppIdKey, pageDict]);
|
|
764
|
+
} finally {
|
|
765
|
+
this.messageHandler?.off('_rpc_applicationConnected:', onAppChange);
|
|
771
766
|
}
|
|
772
767
|
})();
|
|
773
768
|
});
|
package/lib/utils.js
CHANGED
|
@@ -38,10 +38,10 @@ export const RESPONSE_LOG_LENGTH = 100;
|
|
|
38
38
|
* @property {boolean} isProxy
|
|
39
39
|
* @property {string} name
|
|
40
40
|
* @property {string} bundleId
|
|
41
|
-
* @property {string} hostId
|
|
41
|
+
* @property {string} [hostId]
|
|
42
42
|
* @property {boolean} isActive
|
|
43
43
|
* @property {boolean|string} isAutomationEnabled
|
|
44
|
-
* @property {
|
|
44
|
+
* @property {import('./mixins/connect').Page[]} [pageArray]
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -83,28 +83,23 @@ export function appInfoFromDict (dict) {
|
|
|
83
83
|
return [id, entry];
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
/**
|
|
87
87
|
* Take a dictionary from the remote debugger and makes a more manageable
|
|
88
88
|
* dictionary of pages available.
|
|
89
|
+
*
|
|
90
|
+
* @param {import('@appium/types').StringRecord} pageDict
|
|
91
|
+
* @returns {import('./mixins/connect').Page[]}
|
|
89
92
|
*/
|
|
90
93
|
export function pageArrayFromDict (pageDict) {
|
|
91
|
-
|
|
92
|
-
// the page is already translated, so wrap in an array and pass back
|
|
93
|
-
return [pageDict];
|
|
94
|
-
}
|
|
95
|
-
let newPageArray = [];
|
|
96
|
-
for (const dict of _.values(pageDict)) {
|
|
94
|
+
return _.values(pageDict)
|
|
97
95
|
// count only WIRTypeWeb pages and ignore all others (WIRTypeJavaScript etc)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return newPageArray;
|
|
96
|
+
.filter((dict) => _.isUndefined(dict.WIRTypeKey) || ACCEPTED_PAGE_TYPES.includes(dict.WIRTypeKey))
|
|
97
|
+
.map((dict) => ({
|
|
98
|
+
id: dict.WIRPageIdentifierKey,
|
|
99
|
+
title: dict.WIRTitleKey,
|
|
100
|
+
url: dict.WIRURLKey,
|
|
101
|
+
isKey: !_.isUndefined(dict.WIRConnectionIdentifierKey),
|
|
102
|
+
}));
|
|
108
103
|
}
|
|
109
104
|
|
|
110
105
|
/**
|
|
@@ -147,7 +142,7 @@ export function getDebuggerAppKey (bundleId, appDict) {
|
|
|
147
142
|
* Find app keys based on assigned bundleIds from appDict
|
|
148
143
|
* When bundleIds includes a wildcard ('*'), returns all appKeys in appDict.
|
|
149
144
|
* @param {string[]} bundleIds
|
|
150
|
-
* @param {Record<string,
|
|
145
|
+
* @param {Record<string, AppInfo>} appDict
|
|
151
146
|
* @returns {string[]}
|
|
152
147
|
*/
|
|
153
148
|
export function getPossibleDebuggerAppKeys(bundleIds, appDict) {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"keywords": [
|
|
5
5
|
"appium"
|
|
6
6
|
],
|
|
7
|
-
"version": "11.5.
|
|
7
|
+
"version": "11.5.5",
|
|
8
8
|
"author": "Appium Contributors",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"repository": {
|
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
"@appium/base-driver": "^9.0.0",
|
|
37
37
|
"@appium/support": "^5.0.3",
|
|
38
38
|
"appium-ios-device": "^2.0.0",
|
|
39
|
-
"async-lock": "^1.2.2",
|
|
40
39
|
"asyncbox": "^3.0.0",
|
|
41
40
|
"bluebird": "^3.4.7",
|
|
42
41
|
"fancy-log": "^2.0.0",
|