Skip to content

Commit 7246bce

Browse files
ZdravkoDimitarTodorov
Zdravko
authored andcommitted
feat: add the ability to run adb shell commands (#251)
* feature: add the ability to run adb shell commands * chore: use AndroidKeyEvent enum * Chore: add | AndroidKeyEvent to parameters of adbKeyEvent method
1 parent a997bd7 commit 7246bce

File tree

6 files changed

+87
-10
lines changed

6 files changed

+87
-10
lines changed

Diff for: lib/appium-driver.d.ts

+17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ImageHelper } from "./image-helper";
1111
import { ImageOptions } from "./image-options";
1212
import { LogType } from "./log-types";
1313
import { DeviceOrientation } from "./enums/device-orientation";
14+
import { AndroidKeyEvent } from "mobile-devices-controller";
1415
export declare class AppiumDriver {
1516
private _driver;
1617
private _wd;
@@ -269,4 +270,20 @@ export declare class AppiumDriver {
269270
* This is convenient to use for some gestures on the screen
270271
*/
271272
getScreenViewPort(): IRectangle;
273+
/**
274+
* Android ONLY! Input key event via ADB.
275+
* @param keyEvent The event number
276+
*/
277+
adbKeyEvent(keyEvent: number | AndroidKeyEvent): Promise<void>;
278+
/**
279+
* Android ONLY! Send text via ADB.
280+
* @param text The string to send
281+
*/
282+
adbSendText(text: string): Promise<void>;
283+
/**
284+
* Android ONLY! Execute shell command via ADB.
285+
* @param command The command name
286+
* @param args Additional arguments
287+
*/
288+
adbShellCommand(command: string, args: Array<any>): Promise<void>;
272289
}

Diff for: lib/appium-driver.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import {
3333
getStorage,
3434
encodeImageToBase64,
3535
ensureReportsDirExists,
36-
checkImageLogType
36+
checkImageLogType,
37+
adbShellCommand
3738
} from "./utils";
3839

3940
import { INsCapabilities } from "./interfaces/ns-capabilities";
@@ -50,6 +51,7 @@ import { LogImageType } from "./enums/log-image-type";
5051
import { DeviceOrientation } from "./enums/device-orientation";
5152
import { NsCapabilities } from "./ns-capabilities";
5253
import { AutomationName } from "./automation-name";
54+
import { AndroidKeyEvent } from "mobile-devices-controller";
5355

5456
export class AppiumDriver {
5557
private _defaultWaitTime: number = 5000;
@@ -1022,4 +1024,29 @@ export class AppiumDriver {
10221024
}
10231025
}
10241026
}
1027+
1028+
/**
1029+
* Android ONLY! Input key event via ADB.
1030+
* @param keyEvent The event number
1031+
*/
1032+
public async adbKeyEvent(keyEvent: number | AndroidKeyEvent) {
1033+
await this.adbShellCommand("input", ["keyevent", keyEvent]);
1034+
}
1035+
1036+
/**
1037+
* Android ONLY! Send text via ADB.
1038+
* @param text The string to send
1039+
*/
1040+
public async adbSendText(text: string) {
1041+
await this.adbShellCommand("input", ["text", text]);
1042+
}
1043+
1044+
/**
1045+
* Android ONLY! Execute shell command via ADB.
1046+
* @param command The command name
1047+
* @param args Additional arguments
1048+
*/
1049+
public async adbShellCommand(command: string, args: Array<any>) {
1050+
await adbShellCommand(this._driver, command, args);
1051+
}
10251052
}

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ export declare class UIElement {
128128
* Send keys to field or other UI component
129129
* @param text
130130
* @param shouldClearText, default value is true
131+
* @param useAdb, default value is false. Usable for Android ONLY !
131132
*/
132-
sendKeys(text: string, shouldClearText?: boolean): Promise<void>;
133+
sendKeys(text: string, shouldClearText?: boolean, useAdb?: boolean): Promise<void>;
133134
/**
134135
* Type text to field or other UI component
135136
* @param text
@@ -142,9 +143,14 @@ export declare class UIElement {
142143
*/
143144
pressKeycode(keyCode: number): Promise<void>;
144145
/**
145-
* Clears text form ui element
146+
* Clears text from ui element
146147
*/
147148
clearText(): Promise<void>;
149+
/**
150+
* Clears text from ui element with ADB. Android ONLY !
151+
* @param charactersCount Characters count to delete. (Optional - default value 10)
152+
*/
153+
adbDeleteText(charactersCount?: number): Promise<void>;
148154
log(): Promise<void>;
149155
refetch(): Promise<any>;
150156
/**

Diff for: lib/ui-element.ts

+28-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Point } from "./point";
22
import { Direction } from "./direction";
33
import { INsCapabilities } from "./interfaces/ns-capabilities";
44
import { AutomationName } from "./automation-name";
5-
import { calculateOffset } from "./utils";
5+
import { calculateOffset, adbShellCommand } from "./utils";
66
import { AndroidKeyEvent } from "mobile-devices-controller";
77

88
export class UIElement {
@@ -382,12 +382,21 @@ export class UIElement {
382382
* Send keys to field or other UI component
383383
* @param text
384384
* @param shouldClearText, default value is true
385+
* @param useAdb, default value is false. Usable for Android ONLY !
385386
*/
386-
public async sendKeys(text: string, shouldClearText: boolean = true) {
387-
if (shouldClearText) {
388-
await this.clearText();
387+
public async sendKeys(text: string, shouldClearText: boolean = true, useAdb: boolean = false) {
388+
if (useAdb && this._args.isAndroid) {
389+
if (shouldClearText) {
390+
await this.adbDeleteText();
391+
}
392+
await this.click();
393+
await adbShellCommand(this._driver, "input", ["text", text]);
394+
} else {
395+
if (shouldClearText) {
396+
await this.clearText();
397+
}
398+
await this._element.sendKeys(text);
389399
}
390-
await this._element.sendKeys(text);
391400
}
392401

393402
/**
@@ -407,17 +416,29 @@ export class UIElement {
407416
* @param key code
408417
*/
409418
public async pressKeycode(keyCode: number) {
410-
await this._driver.pressKeycode(keyCode);
419+
await this._driver.pressKeyCode(keyCode);
411420
}
412421

413422
/**
414-
* Clears text form ui element
423+
* Clears text from ui element
415424
*/
416425
public async clearText() {
417426
await this.click();
418427
await this._element.clear();
419428
}
420429

430+
/**
431+
* Clears text from ui element with ADB. Android ONLY !
432+
* @param charactersCount Characters count to delete. (Optional - default value 10)
433+
*/
434+
public async adbDeleteText(charactersCount: number = 10) {
435+
await this.click();
436+
for (let index = 0; index < charactersCount; index++) {
437+
// Keyevent 67 Delete (backspace)
438+
await adbShellCommand(this._driver, "input", ["keyevent", AndroidKeyEvent.KEYCODE_DEL]);
439+
}
440+
}
441+
421442
public async log() {
422443
const el = await this.element();
423444
console.dir(el);

Diff for: lib/utils.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export declare function logWarn(info: any, obj?: any): void;
5151
export declare function logError(info: any, obj?: any): void;
5252
export declare function log(message: any, verbose: any): void;
5353
export declare const logColorized: (bgColor: ConsoleColor, frontColor: ConsoleColor, info: any) => void;
54+
export declare function adbShellCommand(wd: any, command: string, args: Array<any>): Promise<void>;
5455
declare enum ConsoleColor {
5556
Reset = "\u001B[0m",
5657
Bright = "\u001B[1m",

Diff for: lib/utils.ts

+5
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,11 @@ export const logColorized = (bgColor: ConsoleColor, frontColor: ConsoleColor, in
687687
console.log(`${ConsoleColor.BgYellow}${ConsoleColor.FgBlack}%s${ConsoleColor.Reset}`, info);
688688
}
689689

690+
691+
export async function adbShellCommand(wd: any, command: string, args: Array<any>) {
692+
await wd.execute('mobile: shell', {"command": command, "args": args});
693+
}
694+
690695
enum ConsoleColor {
691696
Reset = "\x1b[0m",
692697
Bright = "\x1b[1m",

0 commit comments

Comments
 (0)