From 0344a4667b8ed62760b6a5e63a234c50c8a127ef Mon Sep 17 00:00:00 2001 From: Zdravko Branzov Date: Thu, 29 Aug 2019 16:23:48 +0300 Subject: [PATCH 1/3] feature: add the ability to run adb shell commands --- lib/appium-driver.d.ts | 16 ++++++++++++++++ lib/appium-driver.ts | 28 +++++++++++++++++++++++++++- lib/ui-element.d.ts | 10 ++++++++-- lib/ui-element.ts | 35 ++++++++++++++++++++++++++++------- lib/utils.d.ts | 1 + lib/utils.ts | 5 +++++ 6 files changed, 85 insertions(+), 10 deletions(-) diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index 3563261..6c3ddb8 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -269,4 +269,20 @@ export declare class AppiumDriver { * This is convenient to use for some gestures on the screen */ getScreenViewPort(): IRectangle; + /** + * Android ONLY! Input key event via ADB. + * @param keyEvent The event number + */ + adbKeyEvent(keyEvent: number): Promise; + /** + * Android ONLY! Send text via ADB. + * @param text The string to send + */ + adbSendText(text: string): Promise; + /** + * Android ONLY! Execute shell command via ADB. + * @param command The command name + * @param args Additional arguments + */ + adbShellCommand(command: string, args: Array): Promise; } diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index fabc4a2..518ff07 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -33,7 +33,8 @@ import { getStorage, encodeImageToBase64, ensureReportsDirExists, - checkImageLogType + checkImageLogType, + adbShellCommand } from "./utils"; import { INsCapabilities } from "./interfaces/ns-capabilities"; @@ -1022,4 +1023,29 @@ export class AppiumDriver { } } } + + /** + * Android ONLY! Input key event via ADB. + * @param keyEvent The event number + */ + public async adbKeyEvent(keyEvent: number) { + await this.adbShellCommand("input", ["keyevent", keyEvent]); + } + + /** + * Android ONLY! Send text via ADB. + * @param text The string to send + */ + public async adbSendText(text: string) { + await this.adbShellCommand("input", ["text", text]); + } + + /** + * Android ONLY! Execute shell command via ADB. + * @param command The command name + * @param args Additional arguments + */ + public async adbShellCommand(command: string, args: Array) { + await adbShellCommand(this._driver, command, args); + } } \ No newline at end of file diff --git a/lib/ui-element.d.ts b/lib/ui-element.d.ts index 167d580..6fe5cc5 100644 --- a/lib/ui-element.d.ts +++ b/lib/ui-element.d.ts @@ -128,8 +128,9 @@ export declare class UIElement { * Send keys to field or other UI component * @param text * @param shouldClearText, default value is true + * @param useAdb, default value is false. Usable for Android ONLY ! */ - sendKeys(text: string, shouldClearText?: boolean): Promise; + sendKeys(text: string, shouldClearText?: boolean, useAdb?: boolean): Promise; /** * Type text to field or other UI component * @param text @@ -142,9 +143,14 @@ export declare class UIElement { */ pressKeycode(keyCode: number): Promise; /** - * Clears text form ui element + * Clears text from ui element */ clearText(): Promise; + /** + * Clears text from ui element with ADB. Android ONLY ! + * @param charactersCount Characters count to delete. (Optional - default value 10) + */ + adbDeleteText(charactersCount?: number): Promise; log(): Promise; refetch(): Promise; /** diff --git a/lib/ui-element.ts b/lib/ui-element.ts index 4b940e2..272ad95 100644 --- a/lib/ui-element.ts +++ b/lib/ui-element.ts @@ -2,7 +2,7 @@ import { Point } from "./point"; import { Direction } from "./direction"; import { INsCapabilities } from "./interfaces/ns-capabilities"; import { AutomationName } from "./automation-name"; -import { calculateOffset } from "./utils"; +import { calculateOffset, adbShellCommand } from "./utils"; import { AndroidKeyEvent } from "mobile-devices-controller"; export class UIElement { @@ -382,12 +382,21 @@ export class UIElement { * Send keys to field or other UI component * @param text * @param shouldClearText, default value is true + * @param useAdb, default value is false. Usable for Android ONLY ! */ - public async sendKeys(text: string, shouldClearText: boolean = true) { - if (shouldClearText) { - await this.clearText(); + public async sendKeys(text: string, shouldClearText: boolean = true, useAdb: boolean = false) { + if (useAdb && this._args.isAndroid) { + if (shouldClearText) { + await this.adbDeleteText(); + } + await this.click(); + await adbShellCommand(this._driver, "input", ["text", text]); + } else { + if (shouldClearText) { + await this.clearText(); + } + await this._element.sendKeys(text); } - await this._element.sendKeys(text); } /** @@ -407,17 +416,29 @@ export class UIElement { * @param key code */ public async pressKeycode(keyCode: number) { - await this._driver.pressKeycode(keyCode); + await this._driver.pressKeyCode(keyCode); } /** - * Clears text form ui element + * Clears text from ui element */ public async clearText() { await this.click(); await this._element.clear(); } + /** + * Clears text from ui element with ADB. Android ONLY ! + * @param charactersCount Characters count to delete. (Optional - default value 10) + */ + public async adbDeleteText(charactersCount: number = 10) { + await this.click(); + for (let index = 0; index < charactersCount; index++) { + // Keyevent 67 Delete (backspace) + await adbShellCommand(this._driver, "input", ["keyevent", 67]); + } + } + public async log() { const el = await this.element(); console.dir(el); diff --git a/lib/utils.d.ts b/lib/utils.d.ts index 764e2ca..b1be4f2 100644 --- a/lib/utils.d.ts +++ b/lib/utils.d.ts @@ -51,6 +51,7 @@ export declare function logWarn(info: any, obj?: any): void; export declare function logError(info: any, obj?: any): void; export declare function log(message: any, verbose: any): void; export declare const logColorized: (bgColor: ConsoleColor, frontColor: ConsoleColor, info: any) => void; +export declare function adbShellCommand(wd: any, command: string, args: Array): Promise; declare enum ConsoleColor { Reset = "\u001B[0m", Bright = "\u001B[1m", diff --git a/lib/utils.ts b/lib/utils.ts index 7df007e..aeda908 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -687,6 +687,11 @@ export const logColorized = (bgColor: ConsoleColor, frontColor: ConsoleColor, in console.log(`${ConsoleColor.BgYellow}${ConsoleColor.FgBlack}%s${ConsoleColor.Reset}`, info); } + +export async function adbShellCommand(wd: any, command: string, args: Array) { + await wd.execute('mobile: shell', {"command": command, "args": args}); +} + enum ConsoleColor { Reset = "\x1b[0m", Bright = "\x1b[1m", From 729c8aa2eab3fc945a49335d250941622890d789 Mon Sep 17 00:00:00 2001 From: Zdravko Branzov Date: Thu, 29 Aug 2019 16:42:48 +0300 Subject: [PATCH 2/3] chore: use AndroidKeyEvent enum --- lib/ui-element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui-element.ts b/lib/ui-element.ts index 272ad95..ae02dae 100644 --- a/lib/ui-element.ts +++ b/lib/ui-element.ts @@ -435,7 +435,7 @@ export class UIElement { await this.click(); for (let index = 0; index < charactersCount; index++) { // Keyevent 67 Delete (backspace) - await adbShellCommand(this._driver, "input", ["keyevent", 67]); + await adbShellCommand(this._driver, "input", ["keyevent", AndroidKeyEvent.KEYCODE_DEL]); } } From a7b55e5ca8c2f1874bea42aa1d501c303685b697 Mon Sep 17 00:00:00 2001 From: Dimitar Todorov Date: Fri, 30 Aug 2019 13:46:00 +0300 Subject: [PATCH 3/3] Chore: add | AndroidKeyEvent to parameters of adbKeyEvent method --- lib/appium-driver.d.ts | 3 ++- lib/appium-driver.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index 6c3ddb8..3e9e72b 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -11,6 +11,7 @@ import { ImageHelper } from "./image-helper"; import { ImageOptions } from "./image-options"; import { LogType } from "./log-types"; import { DeviceOrientation } from "./enums/device-orientation"; +import { AndroidKeyEvent } from "mobile-devices-controller"; export declare class AppiumDriver { private _driver; private _wd; @@ -273,7 +274,7 @@ export declare class AppiumDriver { * Android ONLY! Input key event via ADB. * @param keyEvent The event number */ - adbKeyEvent(keyEvent: number): Promise; + adbKeyEvent(keyEvent: number | AndroidKeyEvent): Promise; /** * Android ONLY! Send text via ADB. * @param text The string to send diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index 518ff07..2d16096 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -51,6 +51,7 @@ import { LogImageType } from "./enums/log-image-type"; import { DeviceOrientation } from "./enums/device-orientation"; import { NsCapabilities } from "./ns-capabilities"; import { AutomationName } from "./automation-name"; +import { AndroidKeyEvent } from "mobile-devices-controller"; export class AppiumDriver { private _defaultWaitTime: number = 5000; @@ -1028,7 +1029,7 @@ export class AppiumDriver { * Android ONLY! Input key event via ADB. * @param keyEvent The event number */ - public async adbKeyEvent(keyEvent: number) { + public async adbKeyEvent(keyEvent: number | AndroidKeyEvent) { await this.adbShellCommand("input", ["keyevent", keyEvent]); }