Skip to content

Commit 3ba0a1c

Browse files
Tsenov/uiautomator2 (#122)
* feat: include support for UiAutomator2
1 parent fac8c09 commit 3ba0a1c

6 files changed

+82
-4
lines changed

Diff for: lib/interfaces/ns-capabilities.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import { IDevice } from "mobile-devices-controller";
2+
export declare enum AutomationName {
3+
UiAutomator2 = "UiAutomator2",
4+
Appium = "Appium",
5+
XCUITest = "XCUITest",
6+
}
27
export interface INsCapabilities {
38
projectDir: string;
49
projectBinary: string;
@@ -24,4 +29,5 @@ export interface INsCapabilities {
2429
ignoreDeviceController: boolean;
2530
wdaLocalPort: number;
2631
path: string;
32+
automationName: AutomationName;
2733
}

Diff for: lib/interfaces/ns-capabilities.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { IDevice } from "mobile-devices-controller";
22

3+
export enum AutomationName {
4+
UiAutomator2 = "UiAutomator2",
5+
Appium = "Appium",
6+
XCUITest = "XCUITest",
7+
}
8+
39
export interface INsCapabilities {
410
projectDir: string;
511
projectBinary: string;
@@ -25,4 +31,5 @@ export interface INsCapabilities {
2531
ignoreDeviceController: boolean;
2632
wdaLocalPort: number;
2733
path: string;
34+
automationName: AutomationName;
2835
}

Diff for: lib/ns-capabilities.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { INsCapabilities } from "./interfaces/ns-capabilities";
1+
import { INsCapabilities, AutomationName } from "./interfaces/ns-capabilities";
22
import { IDevice } from "mobile-devices-controller";
33
export declare class NsCapabilities implements INsCapabilities {
44
private _projectDir;
@@ -22,6 +22,7 @@ export declare class NsCapabilities implements INsCapabilities {
2222
private _appPath;
2323
private _path;
2424
private _emulatorOptions;
25+
private _automationName;
2526
private _device;
2627
private _ignoreDeviceController;
2728
private _wdaLocalPort;
@@ -45,13 +46,16 @@ export declare class NsCapabilities implements INsCapabilities {
4546
readonly isAndroid: any;
4647
readonly isIOS: any;
4748
readonly isSauceLab: any;
49+
readonly automationName: AutomationName;
4850
readonly appPath: string;
4951
appName: string;
5052
ignoreDeviceController: boolean;
5153
readonly wdaLocalPort: number;
5254
device: IDevice;
5355
readonly emulatorOptions: string;
5456
private isAndroidPlatform();
57+
private setAutomationName();
58+
tryGetAndroidApiLevel(): number;
5559
private resolveApplication();
5660
private checkMandatoryCapabiliies();
5761
private throwExceptions();

Diff for: lib/ns-capabilities.ts

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as parser from "./parser"
2-
import { INsCapabilities } from "./interfaces/ns-capabilities";
2+
import { INsCapabilities, AutomationName } from "./interfaces/ns-capabilities";
33
import { resolveCapabilities } from "./capabilities-helper";
44
import { getAppPath, fileExists, logErr } from "./utils";
55
import { IDevice } from "mobile-devices-controller";
@@ -26,6 +26,7 @@ export class NsCapabilities implements INsCapabilities {
2626
private _appPath: string;
2727
private _path: string;
2828
private _emulatorOptions: string;
29+
private _automationName: AutomationName;
2930
private _device: IDevice;
3031
private _ignoreDeviceController: boolean;
3132
private _wdaLocalPort: number;
@@ -53,6 +54,7 @@ export class NsCapabilities implements INsCapabilities {
5354
this._ignoreDeviceController = parser.ignoreDeviceController;
5455
this._wdaLocalPort = parser.wdaLocalPort;
5556
this._path = parser.path;
57+
this.setAutomationName();
5658
this.resolveApplication();
5759
this.checkMandatoryCapabiliies();
5860
this.throwExceptions();
@@ -76,6 +78,7 @@ export class NsCapabilities implements INsCapabilities {
7678
get isAndroid() { return this._isAndroid; }
7779
get isIOS() { return this._isIOS; }
7880
get isSauceLab() { return this._isSauceLab; }
81+
get automationName() { return this._automationName; }
7982
get appPath() { return this._appPath; }
8083
get appName() { return this._appName; }
8184
set appName(appName: string) { this._appName = appName; }
@@ -88,6 +91,40 @@ export class NsCapabilities implements INsCapabilities {
8891

8992
private isAndroidPlatform() { return this._appiumCaps.platformName.toLowerCase().includes("android"); }
9093

94+
private setAutomationName() {
95+
if (this.appiumCaps["automationName"]) {
96+
switch (this.appiumCaps["automationName"]) {
97+
case AutomationName.UiAutomator2.toString():
98+
this._automationName = AutomationName.UiAutomator2; break;
99+
case AutomationName.Appium.toString():
100+
this._automationName = AutomationName.Appium; break;
101+
case AutomationName.XCUITest.toString():
102+
this._automationName = AutomationName.XCUITest; break;
103+
}
104+
} else {
105+
if (this._isAndroid) {
106+
if (this.tryGetAndroidApiLevel() > 24 || (this.appiumCaps["apiLevel"] && this.appiumCaps["apiLevel"].toLowerCase().includes("p"))) {
107+
this._automationName = AutomationName.UiAutomator2;
108+
}
109+
}
110+
}
111+
112+
if (this._automationName) {
113+
this.appiumCaps["automationName"] = this._automationName.toString();
114+
console.log(`Automation name set to: ${this.appiumCaps["automationName"]}`);
115+
console.log(`To change automation name, you need to set it in appium capabilities!`);
116+
} else {
117+
console.log(`Appium will use default automation name`);
118+
}
119+
}
120+
121+
tryGetAndroidApiLevel() {
122+
try {
123+
return parseInt(this.appiumCaps["platformVersion"]);
124+
} catch (error) {
125+
}
126+
}
127+
91128
private resolveApplication() {
92129
if (this.isSauceLab) {
93130
this._appiumCaps.app = `sauce-storage:${this.appPath}`

Diff for: lib/ui-element.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ export declare class UIElement {
1515
* Click on element
1616
*/
1717
click(): Promise<any>;
18+
/**
19+
* Click a point by providing coordinates
20+
* @param x
21+
* @param y
22+
*/
23+
tapCenter(): Promise<void>;
1824
/**
1925
* Tap on element
2026
*/

Diff for: lib/ui-element.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Point } from "./point";
22
import { Direction } from "./direction";
3-
import { INsCapabilities } from "./interfaces/ns-capabilities";
3+
import { INsCapabilities, AutomationName } from "./interfaces/ns-capabilities";
44
import { IRectangle } from "./interfaces/rectangle";
55
import { calculateOffset } from "./utils";
66

@@ -22,11 +22,29 @@ export class UIElement {
2222
return await (await this.element()).click();
2323
}
2424

25+
/**
26+
* Click a point by providing coordinates
27+
* @param x
28+
* @param y
29+
*/
30+
public async tapCenter() {
31+
let action = new this._wd.TouchAction(this._driver);
32+
const rect = await this.getActualRectangle();
33+
action
34+
.tap({ x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 });
35+
await action.perform();
36+
await this._driver.sleep(150);
37+
}
38+
2539
/**
2640
* Tap on element
2741
*/
2842
public async tap() {
29-
return await (await this.element()).tap();
43+
if (this._args.automationName == AutomationName.UiAutomator2) {
44+
return await this.tapCenter();
45+
} else {
46+
return await (await this.element()).tap();
47+
}
3048
}
3149

3250
/**

0 commit comments

Comments
 (0)