appium-remote-debugger 15.0.0 → 15.0.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 +6 -0
- package/build/lib/mixins/connect.js +5 -4
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/execute.js +3 -3
- package/build/lib/mixins/execute.js.map +1 -1
- package/build/lib/mixins/navigate.d.ts.map +1 -1
- package/build/lib/mixins/navigate.js +12 -11
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts +18 -3
- package/build/lib/rpc/rpc-client.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client.js +80 -6
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/utils.d.ts +1 -1
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +2 -2
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/mixins/connect.js +5 -5
- package/lib/mixins/execute.js +4 -4
- package/lib/mixins/navigate.js +12 -13
- package/lib/rpc/rpc-client.js +100 -7
- package/lib/utils.js +1 -1
- package/package.json +1 -1
package/lib/mixins/connect.js
CHANGED
|
@@ -173,11 +173,11 @@ export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
|
173
173
|
|
|
174
174
|
const timer = new timing.Timer().start();
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
const pageReadinessDetector = skipReadyCheck ? undefined : {
|
|
177
|
+
timeoutMs: this.pageLoadMs,
|
|
178
|
+
readinessDetector: (/** @type {string} */ readyState) => this.isPageLoadingCompleted(readyState),
|
|
179
|
+
};
|
|
180
|
+
await this.requireRpcClient().selectPage(fullAppIdKey, pageIdKey, pageReadinessDetector);
|
|
181
181
|
|
|
182
182
|
this.log.debug(`Selected page after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
183
183
|
}
|
package/lib/mixins/execute.js
CHANGED
|
@@ -2,7 +2,7 @@ import { errors } from '@appium/base-driver';
|
|
|
2
2
|
import {
|
|
3
3
|
checkParams,
|
|
4
4
|
simpleStringify,
|
|
5
|
-
|
|
5
|
+
convertJavascriptEvaluationResult,
|
|
6
6
|
RESPONSE_LOG_LENGTH,
|
|
7
7
|
} from '../utils';
|
|
8
8
|
import { getScriptForAtom } from '../atoms';
|
|
@@ -123,7 +123,7 @@ export async function executeAtomAsync (atom, args = [], frames = []) {
|
|
|
123
123
|
);
|
|
124
124
|
} catch {}
|
|
125
125
|
}
|
|
126
|
-
return
|
|
126
|
+
return convertJavascriptEvaluationResult(res);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
@@ -155,7 +155,7 @@ export async function execute (command, override) {
|
|
|
155
155
|
appIdKey,
|
|
156
156
|
pageIdKey,
|
|
157
157
|
});
|
|
158
|
-
return
|
|
158
|
+
return convertJavascriptEvaluationResult(res);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/**
|
|
@@ -184,7 +184,7 @@ export async function callFunction (objectId, fn, args) {
|
|
|
184
184
|
pageIdKey,
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
-
return
|
|
187
|
+
return convertJavascriptEvaluationResult(res);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
package/lib/mixins/navigate.js
CHANGED
|
@@ -20,11 +20,11 @@ const PAGE_READINESS_CHECK_INTERVAL_MS = 50;
|
|
|
20
20
|
/**
|
|
21
21
|
* pageLoadStrategy in WebDriver definitions.
|
|
22
22
|
*/
|
|
23
|
-
const PAGE_LOAD_STRATEGY = {
|
|
23
|
+
const PAGE_LOAD_STRATEGY = Object.freeze({
|
|
24
24
|
EAGER: 'eager',
|
|
25
25
|
NONE: 'none',
|
|
26
26
|
NORMAL: 'normal'
|
|
27
|
-
};
|
|
27
|
+
});
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* @this {RemoteDebugger}
|
|
@@ -53,18 +53,17 @@ export function cancelPageLoad () {
|
|
|
53
53
|
* @returns {boolean}
|
|
54
54
|
*/
|
|
55
55
|
export function isPageLoadingCompleted (readyState) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
const pageLoadStrategy = _.toLower(getPageLoadStartegy(this));
|
|
57
|
+
switch (pageLoadStrategy) {
|
|
58
|
+
case PAGE_LOAD_STRATEGY.EAGER:
|
|
59
|
+
// This could include 'interactive' or 'complete'
|
|
60
|
+
return readyState !== 'loading';
|
|
61
|
+
case PAGE_LOAD_STRATEGY.NONE:
|
|
62
|
+
return true;
|
|
63
|
+
case PAGE_LOAD_STRATEGY.NORMAL:
|
|
64
|
+
default:
|
|
65
|
+
return readyState === 'complete';
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
if (_pageLoadStrategy === PAGE_LOAD_STRATEGY.EAGER) {
|
|
62
|
-
// This could include 'interactive' or 'complete'
|
|
63
|
-
return readyState !== 'loading';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Default behavior. It includes pageLoadStrategy is 'normal' as well.
|
|
67
|
-
return readyState === 'complete';
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
/**
|
package/lib/rpc/rpc-client.js
CHANGED
|
@@ -7,6 +7,7 @@ import RpcMessageHandler from './rpc-message-handler';
|
|
|
7
7
|
import { util, timing } from '@appium/support';
|
|
8
8
|
import { EventEmitter } from 'node:events';
|
|
9
9
|
import AsyncLock from 'async-lock';
|
|
10
|
+
import { convertJavascriptEvaluationResult } from '../utils';
|
|
10
11
|
|
|
11
12
|
const DATA_LOG_LENGTH = {length: 200};
|
|
12
13
|
const MIN_WAIT_FOR_TARGET_TIMEOUT_MS = 30000;
|
|
@@ -83,7 +84,7 @@ export class RpcClient {
|
|
|
83
84
|
/** @type {EventEmitter} */
|
|
84
85
|
_targetSubscriptions;
|
|
85
86
|
|
|
86
|
-
/** @type {
|
|
87
|
+
/** @type {PendingTargetNotification | undefined} */
|
|
87
88
|
_pendingTargetNotification;
|
|
88
89
|
|
|
89
90
|
/**
|
|
@@ -454,7 +455,7 @@ export class RpcClient {
|
|
|
454
455
|
return;
|
|
455
456
|
}
|
|
456
457
|
|
|
457
|
-
const [appIdKey, pageIdKey] = this._pendingTargetNotification;
|
|
458
|
+
const [appIdKey, pageIdKey, pageReadinessDetector] = this._pendingTargetNotification;
|
|
458
459
|
if (appIdKey !== app) {
|
|
459
460
|
log.info(
|
|
460
461
|
`Received 'Target.targetCreated' event for app '${app}' with no pending request: ${JSON.stringify(targetInfo)}`
|
|
@@ -470,6 +471,24 @@ export class RpcClient {
|
|
|
470
471
|
}
|
|
471
472
|
const timer = new timing.Timer().start();
|
|
472
473
|
|
|
474
|
+
const adjustPageReadinessDetector = () => {
|
|
475
|
+
if (!pageReadinessDetector) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const elapsedMs = timer.getDuration().asMilliSeconds;
|
|
480
|
+
if (elapsedMs >= pageReadinessDetector.timeoutMs) {
|
|
481
|
+
log.warn(
|
|
482
|
+
`Page '${pageIdKey}' took too long to initialize, skipping readiness check`
|
|
483
|
+
);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
timeoutMs: pageReadinessDetector.timeoutMs - elapsedMs,
|
|
488
|
+
readinessDetector: pageReadinessDetector.readinessDetector,
|
|
489
|
+
};
|
|
490
|
+
};
|
|
491
|
+
|
|
473
492
|
if (targetInfo.isProvisional) {
|
|
474
493
|
log.debug(
|
|
475
494
|
`Provisional target created for app '${appIdKey}' and page '${pageIdKey}': '${JSON.stringify(targetInfo)}'`
|
|
@@ -478,8 +497,9 @@ export class RpcClient {
|
|
|
478
497
|
this._provisionedPages.add(pageIdKey);
|
|
479
498
|
try {
|
|
480
499
|
await this.targets[appIdKey].lock.acquire(pageIdKey, async () => {
|
|
500
|
+
let wasInitialized = false;
|
|
481
501
|
try {
|
|
482
|
-
await this._initializePage(appIdKey, pageIdKey, targetInfo.targetId);
|
|
502
|
+
wasInitialized = await this._initializePage(appIdKey, pageIdKey, targetInfo.targetId);
|
|
483
503
|
} finally {
|
|
484
504
|
if (targetInfo.isPaused) {
|
|
485
505
|
await this._resumeTarget(appIdKey, pageIdKey, targetInfo.targetId);
|
|
@@ -489,6 +509,11 @@ export class RpcClient {
|
|
|
489
509
|
);
|
|
490
510
|
}
|
|
491
511
|
}
|
|
512
|
+
if (wasInitialized) {
|
|
513
|
+
await this._waitForPageReadiness(
|
|
514
|
+
appIdKey, pageIdKey, targetInfo.targetId, adjustPageReadinessDetector()
|
|
515
|
+
);
|
|
516
|
+
}
|
|
492
517
|
});
|
|
493
518
|
} catch (e) {
|
|
494
519
|
log.warn(
|
|
@@ -522,18 +547,24 @@ export class RpcClient {
|
|
|
522
547
|
|
|
523
548
|
try {
|
|
524
549
|
await this.targets[appIdKey].lock.acquire(pageIdKey, async () => {
|
|
550
|
+
let wasInitialized = false;
|
|
525
551
|
try {
|
|
526
552
|
if (this._provisionedPages.has(pageIdKey)) {
|
|
527
553
|
log.debug(`Page '${pageIdKey}' has been already provisioned`);
|
|
528
554
|
this._provisionedPages.delete(pageIdKey);
|
|
529
555
|
} else {
|
|
530
|
-
await this._initializePage(appIdKey, pageIdKey);
|
|
556
|
+
wasInitialized = await this._initializePage(appIdKey, pageIdKey);
|
|
531
557
|
}
|
|
532
558
|
} finally {
|
|
533
559
|
if (targetInfo.isPaused) {
|
|
534
560
|
await this._resumeTarget(appIdKey, pageIdKey, targetInfo.targetId);
|
|
535
561
|
}
|
|
536
562
|
}
|
|
563
|
+
if (wasInitialized) {
|
|
564
|
+
await this._waitForPageReadiness(
|
|
565
|
+
appIdKey, pageIdKey, targetInfo.targetId, adjustPageReadinessDetector()
|
|
566
|
+
);
|
|
567
|
+
}
|
|
537
568
|
});
|
|
538
569
|
} catch (e) {
|
|
539
570
|
log.warn(e.message);
|
|
@@ -633,10 +664,11 @@ export class RpcClient {
|
|
|
633
664
|
/**
|
|
634
665
|
* @param {import('../types').AppIdKey} appIdKey
|
|
635
666
|
* @param {import('../types').PageIdKey} pageIdKey
|
|
667
|
+
* @param {PageReadinessDetector} [pageReadinessDetector]
|
|
636
668
|
* @returns {Promise<void>}
|
|
637
669
|
*/
|
|
638
|
-
async selectPage (appIdKey, pageIdKey) {
|
|
639
|
-
this._pendingTargetNotification = [appIdKey, pageIdKey];
|
|
670
|
+
async selectPage (appIdKey, pageIdKey, pageReadinessDetector) {
|
|
671
|
+
this._pendingTargetNotification = [appIdKey, pageIdKey, pageReadinessDetector];
|
|
640
672
|
this._provisionedPages.clear();
|
|
641
673
|
|
|
642
674
|
// go through the steps that the Desktop Safari system
|
|
@@ -900,6 +932,56 @@ export class RpcClient {
|
|
|
900
932
|
}
|
|
901
933
|
}
|
|
902
934
|
|
|
935
|
+
/**
|
|
936
|
+
*
|
|
937
|
+
* @param {import('../types').AppIdKey} appIdKey
|
|
938
|
+
* @param {import('../types').PageIdKey} pageIdKey
|
|
939
|
+
* @param {import('../types').TargetId} targetId
|
|
940
|
+
* @param {PageReadinessDetector} [pageReadinessDetector]
|
|
941
|
+
* @returns {Promise<void>}
|
|
942
|
+
*/
|
|
943
|
+
async _waitForPageReadiness(appIdKey, pageIdKey, targetId, pageReadinessDetector) {
|
|
944
|
+
if (!pageReadinessDetector) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
log.debug(`Waiting up to ${pageReadinessDetector.timeoutMs}ms for page readiness`);
|
|
949
|
+
const timer = new timing.Timer().start();
|
|
950
|
+
while (pageReadinessDetector.timeoutMs - timer.getDuration().asMilliSeconds > 0) {
|
|
951
|
+
/** @type {string} */
|
|
952
|
+
let readyState;
|
|
953
|
+
try {
|
|
954
|
+
const commandTimeoutMs = Math.max(
|
|
955
|
+
100,
|
|
956
|
+
Math.trunc((pageReadinessDetector.timeoutMs - timer.getDuration().asMilliSeconds) * 0.8)
|
|
957
|
+
);
|
|
958
|
+
const rawResult = await B.resolve(this.send('Runtime.evaluate', {
|
|
959
|
+
expression: 'document.readyState;',
|
|
960
|
+
returnByValue: true,
|
|
961
|
+
appIdKey,
|
|
962
|
+
pageIdKey,
|
|
963
|
+
targetId,
|
|
964
|
+
})).timeout(commandTimeoutMs);
|
|
965
|
+
readyState = convertJavascriptEvaluationResult(rawResult);
|
|
966
|
+
} catch (e) {
|
|
967
|
+
log.debug(`Cannot determine page readiness: ${e.message}`);
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
if (pageReadinessDetector.readinessDetector(readyState)) {
|
|
971
|
+
log.info(
|
|
972
|
+
`Page '${pageIdKey}' for app '${appIdKey}' is ready after ` +
|
|
973
|
+
`${timer.getDuration().asMilliSeconds}ms`
|
|
974
|
+
);
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
await B.delay(100);
|
|
978
|
+
}
|
|
979
|
+
log.warn(
|
|
980
|
+
`Page '${pageIdKey}' for app '${appIdKey}' is not ready after ` +
|
|
981
|
+
`${timer.getDuration().asMilliSeconds}ms. Continuing anyway`
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
|
|
903
985
|
/**
|
|
904
986
|
*
|
|
905
987
|
* @param {import('../types').AppIdKey} appIdKey
|
|
@@ -943,4 +1025,15 @@ export default RpcClient;
|
|
|
943
1025
|
/**
|
|
944
1026
|
* @typedef {PageDict & {provisional?: import('../types').ProvisionalTargetInfo, lock: AsyncLock}} PagesToTargets
|
|
945
1027
|
* @typedef {{[key: import('../types').AppIdKey]: PagesToTargets}} AppToTargetsMap
|
|
946
|
-
*/
|
|
1028
|
+
*/
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* @typedef {Object} PageReadinessDetector
|
|
1032
|
+
* @property {number} timeoutMs
|
|
1033
|
+
* @property {(readyState: string) => boolean} readinessDetector
|
|
1034
|
+
*/
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* @typedef {[import('../types').AppIdKey, import('../types').PageIdKey, PageReadinessDetector | undefined]} PendingTargetNotification
|
|
1038
|
+
*/
|
|
1039
|
+
|
package/lib/utils.js
CHANGED
|
@@ -157,7 +157,7 @@ export function deferredPromise () {
|
|
|
157
157
|
* @param {any} res
|
|
158
158
|
* @returns {any}
|
|
159
159
|
*/
|
|
160
|
-
export function
|
|
160
|
+
export function convertJavascriptEvaluationResult (res) {
|
|
161
161
|
if (_.isUndefined(res)) {
|
|
162
162
|
throw new Error(`Did not get OK result from remote debugger. Result was: ${_.truncate(simpleStringify(res), {length: RESPONSE_LOG_LENGTH})}`);
|
|
163
163
|
} else if (_.isString(res)) {
|