appium-uiautomator2-driver 2.43.3 → 2.44.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 +14 -0
- package/build/lib/driver.d.ts +3 -0
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +105 -85
- package/build/lib/driver.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/driver.ts +113 -97
- package/npm-shrinkwrap.json +16 -16
- package/package.json +3 -3
package/lib/driver.ts
CHANGED
|
@@ -520,129 +520,103 @@ class AndroidUiautomator2Driver
|
|
|
520
520
|
}
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
-
async
|
|
524
|
-
caps: Uiautomator2StartSessionOpts
|
|
525
|
-
): Promise<Uiautomator2SessionCaps> {
|
|
526
|
-
// get device udid for this session
|
|
527
|
-
const {udid, emPort} = await this.getDeviceInfoFromCaps();
|
|
528
|
-
this.opts.udid = udid;
|
|
529
|
-
// @ts-expect-error do not put random stuff on opts
|
|
530
|
-
this.opts.emPort = emPort;
|
|
531
|
-
|
|
532
|
-
// now that we know our java version and device info, we can create our
|
|
533
|
-
// ADB instance
|
|
534
|
-
this.adb = await this.createADB();
|
|
535
|
-
|
|
523
|
+
async performSessionPreExecSetup(): Promise<StringRecord|undefined> {
|
|
536
524
|
const apiLevel = await this.adb.getApiLevel();
|
|
537
|
-
|
|
538
525
|
if (apiLevel < 21) {
|
|
539
|
-
this.log.errorAndThrow(
|
|
526
|
+
throw this.log.errorAndThrow(
|
|
540
527
|
'UIAutomator2 is only supported since Android 5.0 (Lollipop). ' +
|
|
541
528
|
'You could still use other supported backends in order to automate older Android versions.'
|
|
542
529
|
);
|
|
543
530
|
}
|
|
544
531
|
|
|
532
|
+
const preflightPromises: Promise<any>[] = [];
|
|
545
533
|
if (apiLevel >= 28) {
|
|
546
534
|
// Android P
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
'
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
535
|
+
preflightPromises.push((async () => {
|
|
536
|
+
this.log.info('Relaxing hidden api policy');
|
|
537
|
+
try {
|
|
538
|
+
await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
|
|
539
|
+
} catch (err) {
|
|
540
|
+
throw this.log.errorAndThrow(
|
|
541
|
+
'Hidden API policy (https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces) cannot be enabled. ' +
|
|
542
|
+
'This might be happening because the device under test is not configured properly. ' +
|
|
543
|
+
'Please check https://github.com/appium/appium/issues/13802 for more details. ' +
|
|
544
|
+
'You could also set the "appium:ignoreHiddenApiPolicyError" capability to true in order to ' +
|
|
545
|
+
'ignore this error, which might later lead to unexpected crashes or behavior of ' +
|
|
546
|
+
`the automation server. Original error: ${err.message}`
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
})());
|
|
560
550
|
}
|
|
561
|
-
|
|
562
|
-
// check if we have to enable/disable gps before running the application
|
|
563
551
|
if (util.hasValue(this.opts.gpsEnabled)) {
|
|
564
|
-
|
|
552
|
+
preflightPromises.push((async () => {
|
|
565
553
|
this.log.info(
|
|
566
554
|
`Trying to ${this.opts.gpsEnabled ? 'enable' : 'disable'} gps location provider`
|
|
567
555
|
);
|
|
568
|
-
await this.adb.toggleGPSLocationProvider(this.opts.gpsEnabled);
|
|
569
|
-
}
|
|
570
|
-
this.log.warn(`Sorry! 'gpsEnabled' capability is only available for emulators`);
|
|
571
|
-
}
|
|
556
|
+
await this.adb.toggleGPSLocationProvider(Boolean(this.opts.gpsEnabled));
|
|
557
|
+
})());
|
|
572
558
|
}
|
|
573
|
-
|
|
574
|
-
// get appPackage et al from manifest if necessary
|
|
575
|
-
const appInfo = await this.getLaunchInfo();
|
|
576
|
-
// and get it onto our 'opts' object so we use it from now on
|
|
577
|
-
this.opts = {...this.opts, ...(appInfo ?? {})};
|
|
578
|
-
|
|
579
|
-
// set actual device name, udid, platform version, screen size, screen density, model and manufacturer details
|
|
580
|
-
const sessionInfo: Uiautomator2SessionInfo = {
|
|
581
|
-
deviceName: this.adb.curDeviceId!,
|
|
582
|
-
deviceUDID: this.opts.udid!,
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
const capsWithSessionInfo = {
|
|
586
|
-
...caps,
|
|
587
|
-
...sessionInfo,
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
// start an avd, set the language/locale, pick an emulator, etc...
|
|
591
559
|
if (this.opts.hideKeyboard) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
// Prepare the device by forwarding the UiAutomator2 port
|
|
597
|
-
// This call mutates this.systemPort if it is not set explicitly
|
|
598
|
-
await this.allocateSystemPort();
|
|
599
|
-
|
|
600
|
-
// Prepare the device by forwarding the UiAutomator2 MJPEG server port (if
|
|
601
|
-
// applicable)
|
|
602
|
-
await this.allocateMjpegServerPort();
|
|
603
|
-
|
|
604
|
-
// set up the modified UiAutomator2 server etc
|
|
605
|
-
const uiautomator2 = await this.initUiAutomator2Server();
|
|
606
|
-
|
|
607
|
-
// Should be after installing io.appium.settings in helpers.initDevice
|
|
608
|
-
if (this.opts.disableWindowAnimation && (await this.adb.getApiLevel()) < 26) {
|
|
609
|
-
// API level 26 is Android 8.0.
|
|
610
|
-
// Granting android.permission.SET_ANIMATION_SCALE is necessary to handle animations under API level 26
|
|
611
|
-
// Read https://github.com/appium/appium/pull/11640#issuecomment-438260477
|
|
612
|
-
// `--no-window-animation` works over Android 8 to disable all of animations
|
|
613
|
-
if (await this.adb.isAnimationOn()) {
|
|
614
|
-
this.log.info('Disabling animation via io.appium.settings');
|
|
615
|
-
await this.settingsApp.setAnimationState(false);
|
|
616
|
-
this._wasWindowAnimationDisabled = true;
|
|
617
|
-
} else {
|
|
618
|
-
this.log.info('Window animation is already disabled');
|
|
619
|
-
}
|
|
560
|
+
preflightPromises.push((async () => {
|
|
561
|
+
this._originalIme = await this.adb.defaultIME();
|
|
562
|
+
})());
|
|
620
563
|
}
|
|
564
|
+
let appInfo;
|
|
565
|
+
preflightPromises.push((async () => {
|
|
566
|
+
// get appPackage et al from manifest if necessary
|
|
567
|
+
appInfo = await this.getLaunchInfo();
|
|
568
|
+
})());
|
|
569
|
+
// start settings app, set the language/locale, start logcat etc...
|
|
570
|
+
preflightPromises.push(this.initDevice());
|
|
621
571
|
|
|
622
|
-
|
|
623
|
-
// prepare our actual AUT, get it on the device, etc...
|
|
624
|
-
await this.initAUT();
|
|
572
|
+
await B.all(preflightPromises);
|
|
625
573
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
574
|
+
this.opts = {...this.opts, ...(appInfo ?? {})};
|
|
575
|
+
return appInfo;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
async performSessionExecution(capsWithSessionInfo: StringRecord): Promise<void> {
|
|
579
|
+
await B.all([
|
|
580
|
+
// Prepare the device by forwarding the UiAutomator2 port
|
|
581
|
+
// This call mutates this.systemPort if it is not set explicitly
|
|
582
|
+
this.allocateSystemPort(),
|
|
583
|
+
// Prepare the device by forwarding the UiAutomator2 MJPEG server port (if
|
|
584
|
+
// applicable)
|
|
585
|
+
this.allocateMjpegServerPort(),
|
|
586
|
+
]);
|
|
587
|
+
|
|
588
|
+
const [uiautomator2,] = await B.all([
|
|
589
|
+
// set up the modified UiAutomator2 server etc
|
|
590
|
+
this.initUiAutomator2Server(),
|
|
591
|
+
(async () => {
|
|
592
|
+
// Should be after installing io.appium.settings
|
|
593
|
+
if (this.opts.disableWindowAnimation && await this.adb.getApiLevel() < 26) {
|
|
594
|
+
// API level 26 is Android 8.0.
|
|
595
|
+
// Granting android.permission.SET_ANIMATION_SCALE is necessary to handle animations under API level 26
|
|
596
|
+
// Read https://github.com/appium/appium/pull/11640#issuecomment-438260477
|
|
597
|
+
// `--no-window-animation` works over Android 8 to disable all of animations
|
|
598
|
+
if (await this.adb.isAnimationOn()) {
|
|
599
|
+
this.log.info('Disabling animation via io.appium.settings');
|
|
600
|
+
await this.settingsApp.setAnimationState(false);
|
|
601
|
+
this._wasWindowAnimationDisabled = true;
|
|
602
|
+
} else {
|
|
603
|
+
this.log.info('Window animation is already disabled');
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
})(),
|
|
607
|
+
// set up app under test
|
|
608
|
+
// prepare our actual AUT, get it on the device, etc...
|
|
609
|
+
this.initAUT(),
|
|
610
|
+
]);
|
|
630
611
|
|
|
631
612
|
// launch UiAutomator2 and wait till its online and we have a session
|
|
632
613
|
await uiautomator2.startSession(capsWithSessionInfo);
|
|
633
614
|
// now that everything has started successfully, turn on proxying so all
|
|
634
615
|
// subsequent session requests go straight to/from uiautomator2
|
|
635
616
|
this.jwpProxyActive = true;
|
|
617
|
+
}
|
|
636
618
|
|
|
637
|
-
|
|
638
|
-
try {
|
|
639
|
-
return await this.getDeviceDetails();
|
|
640
|
-
} catch (e) {
|
|
641
|
-
this.log.warn(`Cannot fetch device details. Original error: ${e.message}`);
|
|
642
|
-
return {};
|
|
643
|
-
}
|
|
644
|
-
})();
|
|
645
|
-
|
|
619
|
+
async performSessionPostExecSetup(): Promise<void> {
|
|
646
620
|
// Unlock the device after the session is started.
|
|
647
621
|
if (!this.opts.skipUnlock) {
|
|
648
622
|
// unlock the device to prepare it for testing
|
|
@@ -672,6 +646,48 @@ class AndroidUiautomator2Driver
|
|
|
672
646
|
this.log.info(`Setting auto webview to context '${viewName}' with timeout ${timeout}ms`);
|
|
673
647
|
await retryInterval(timeout / 500, 500, this.setContext.bind(this), viewName);
|
|
674
648
|
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
async startUiAutomator2Session(
|
|
652
|
+
caps: Uiautomator2StartSessionOpts
|
|
653
|
+
): Promise<Uiautomator2SessionCaps> {
|
|
654
|
+
// get device udid for this session
|
|
655
|
+
const {udid, emPort} = await this.getDeviceInfoFromCaps();
|
|
656
|
+
this.opts.udid = udid;
|
|
657
|
+
// @ts-expect-error do not put random stuff on opts
|
|
658
|
+
this.opts.emPort = emPort;
|
|
659
|
+
|
|
660
|
+
// now that we know our java version and device info, we can create our
|
|
661
|
+
// ADB instance
|
|
662
|
+
this.adb = await this.createADB();
|
|
663
|
+
|
|
664
|
+
const appInfo = await this.performSessionPreExecSetup();
|
|
665
|
+
// set actual device name, udid, platform version, screen size, screen density, model and manufacturer details
|
|
666
|
+
const sessionInfo: Uiautomator2SessionInfo = {
|
|
667
|
+
deviceName: this.adb.curDeviceId!,
|
|
668
|
+
deviceUDID: this.opts.udid!,
|
|
669
|
+
};
|
|
670
|
+
const capsWithSessionInfo = {
|
|
671
|
+
...caps,
|
|
672
|
+
...sessionInfo,
|
|
673
|
+
};
|
|
674
|
+
// Adding AUT package name in the capabilities if package name not exist in caps
|
|
675
|
+
if (!capsWithSessionInfo.appPackage && appInfo) {
|
|
676
|
+
capsWithSessionInfo.appPackage = appInfo.appPackage;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
await this.performSessionExecution(capsWithSessionInfo);
|
|
680
|
+
|
|
681
|
+
const deviceInfoPromise: Promise<Uiautomator2DeviceDetails|EmptyObject> = (async () => {
|
|
682
|
+
try {
|
|
683
|
+
return await this.getDeviceDetails();
|
|
684
|
+
} catch (e) {
|
|
685
|
+
this.log.warn(`Cannot fetch device details. Original error: ${e.message}`);
|
|
686
|
+
return {};
|
|
687
|
+
}
|
|
688
|
+
})();
|
|
689
|
+
|
|
690
|
+
await this.performSessionPostExecSetup();
|
|
675
691
|
|
|
676
692
|
return {...capsWithSessionInfo, ...(await deviceInfoPromise)};
|
|
677
693
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-uiautomator2-driver",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "appium-uiautomator2-driver",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.44.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"appium-adb": "^12.0.0",
|
|
13
|
-
"appium-android-driver": "^8.
|
|
13
|
+
"appium-android-driver": "^8.2.0",
|
|
14
14
|
"appium-chromedriver": "^5.6.28",
|
|
15
|
-
"appium-uiautomator2-server": "^6.0.
|
|
15
|
+
"appium-uiautomator2-server": "^6.0.7",
|
|
16
16
|
"asyncbox": "^3.0.0",
|
|
17
17
|
"axios": "^1.6.5",
|
|
18
18
|
"bluebird": "^3.5.1",
|
|
@@ -960,9 +960,9 @@
|
|
|
960
960
|
}
|
|
961
961
|
},
|
|
962
962
|
"node_modules/@types/node": {
|
|
963
|
-
"version": "20.11.
|
|
964
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.
|
|
965
|
-
"integrity": "sha512-
|
|
963
|
+
"version": "20.11.16",
|
|
964
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz",
|
|
965
|
+
"integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==",
|
|
966
966
|
"dependencies": {
|
|
967
967
|
"undici-types": "~5.26.4"
|
|
968
968
|
}
|
|
@@ -1227,9 +1227,9 @@
|
|
|
1227
1227
|
}
|
|
1228
1228
|
},
|
|
1229
1229
|
"node_modules/appium-android-driver": {
|
|
1230
|
-
"version": "8.
|
|
1231
|
-
"resolved": "https://registry.npmjs.org/appium-android-driver/-/appium-android-driver-8.
|
|
1232
|
-
"integrity": "sha512-
|
|
1230
|
+
"version": "8.2.0",
|
|
1231
|
+
"resolved": "https://registry.npmjs.org/appium-android-driver/-/appium-android-driver-8.2.0.tgz",
|
|
1232
|
+
"integrity": "sha512-bHz7o+HT2jjJ/b398rRdM2QCu3dPyrkVALOU1SrUxQa18n3PIIRquQENINyhsKQChvi8uAFrDJtD8XOd618eLw==",
|
|
1233
1233
|
"dependencies": {
|
|
1234
1234
|
"@appium/support": "^4.2.0",
|
|
1235
1235
|
"@colors/colors": "^1.6.0",
|
|
@@ -1285,9 +1285,9 @@
|
|
|
1285
1285
|
}
|
|
1286
1286
|
},
|
|
1287
1287
|
"node_modules/appium-uiautomator2-server": {
|
|
1288
|
-
"version": "6.0.
|
|
1289
|
-
"resolved": "https://registry.npmjs.org/appium-uiautomator2-server/-/appium-uiautomator2-server-6.0.
|
|
1290
|
-
"integrity": "sha512-
|
|
1288
|
+
"version": "6.0.7",
|
|
1289
|
+
"resolved": "https://registry.npmjs.org/appium-uiautomator2-server/-/appium-uiautomator2-server-6.0.7.tgz",
|
|
1290
|
+
"integrity": "sha512-huBKtK440DWMpfrdLSCuwkwIM3XZoPEzwcAh3IlNyVW3wo56OG9Q9OL3GgtlZh1vU86QHV2dQl1p9nRwAkkVtA==",
|
|
1291
1291
|
"engines": {
|
|
1292
1292
|
"node": ">=14",
|
|
1293
1293
|
"npm": ">=8"
|
|
@@ -4376,9 +4376,9 @@
|
|
|
4376
4376
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
|
4377
4377
|
},
|
|
4378
4378
|
"node_modules/type-fest": {
|
|
4379
|
-
"version": "4.10.
|
|
4380
|
-
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.
|
|
4381
|
-
"integrity": "sha512-
|
|
4379
|
+
"version": "4.10.2",
|
|
4380
|
+
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz",
|
|
4381
|
+
"integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==",
|
|
4382
4382
|
"engines": {
|
|
4383
4383
|
"node": ">=16"
|
|
4384
4384
|
},
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"automated testing",
|
|
8
8
|
"android"
|
|
9
9
|
],
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.44.0",
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/appium/appium-uiautomator2-driver/issues"
|
|
13
13
|
},
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"appium-adb": "^12.0.0",
|
|
60
|
-
"appium-android-driver": "^8.
|
|
60
|
+
"appium-android-driver": "^8.2.0",
|
|
61
61
|
"appium-chromedriver": "^5.6.28",
|
|
62
|
-
"appium-uiautomator2-server": "^6.0.
|
|
62
|
+
"appium-uiautomator2-server": "^6.0.7",
|
|
63
63
|
"asyncbox": "^3.0.0",
|
|
64
64
|
"axios": "^1.6.5",
|
|
65
65
|
"bluebird": "^3.5.1",
|