Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions lib/commands/app-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,38 @@ import {util} from '@appium/support';
import type {UninstallOptions, InstallOptions, StartAppOptions, ListInstalledPackagesOptions} from 'appium-adb';
import {waitForCondition, longSleep} from 'asyncbox';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver, AndroidDriverOpts} from '../driver.js';
import type {AppInfoMap, AppState, IsAppInstalledOptions, TerminateAppOpts} from './types.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
getThirdPartyPackages(...args: Parameters<typeof getThirdPartyPackages>): ReturnType<typeof getThirdPartyPackages>;
uninstallOtherPackages(
...args: Parameters<typeof uninstallOtherPackages>
): ReturnType<typeof uninstallOtherPackages>;
installOtherApks(...args: Parameters<typeof installOtherApks>): ReturnType<typeof installOtherApks>;
installAUT(...args: Parameters<typeof installAUT>): ReturnType<typeof installAUT>;
resetAUT(...args: Parameters<typeof resetAUT>): ReturnType<typeof resetAUT>;
background(...args: Parameters<typeof background>): ReturnType<typeof background>;
getCurrentActivity(...args: Parameters<typeof getCurrentActivity>): ReturnType<typeof getCurrentActivity>;
getCurrentPackage(...args: Parameters<typeof getCurrentPackage>): ReturnType<typeof getCurrentPackage>;
mobileClearApp(...args: Parameters<typeof mobileClearApp>): ReturnType<typeof mobileClearApp>;
mobileInstallApp(...args: Parameters<typeof mobileInstallApp>): ReturnType<typeof mobileInstallApp>;
installApp(...args: Parameters<typeof installApp>): ReturnType<typeof installApp>;
mobileIsAppInstalled(...args: Parameters<typeof mobileIsAppInstalled>): ReturnType<typeof mobileIsAppInstalled>;
mobileRemoveApp(...args: Parameters<typeof mobileRemoveApp>): ReturnType<typeof mobileRemoveApp>;
mobileTerminateApp(...args: Parameters<typeof mobileTerminateApp>): ReturnType<typeof mobileTerminateApp>;
mobileListApps(...args: Parameters<typeof mobileListApps>): ReturnType<typeof mobileListApps>;
terminateApp(...args: Parameters<typeof terminateApp>): ReturnType<typeof terminateApp>;
removeApp(...args: Parameters<typeof removeApp>): ReturnType<typeof removeApp>;
activateApp(...args: Parameters<typeof activateApp>): ReturnType<typeof activateApp>;
queryAppState(...args: Parameters<typeof queryAppState>): ReturnType<typeof queryAppState>;
isAppInstalled(...args: Parameters<typeof isAppInstalled>): ReturnType<typeof isAppInstalled>;
mobileBackgroundApp(...args: Parameters<typeof mobileBackgroundApp>): ReturnType<typeof mobileBackgroundApp>;
}
}

const APP_EXTENSIONS = ['.apk', '.apks'] as const;
const PACKAGE_INSTALL_TIMEOUT_MS = 90000;
// These constants are in sync with
Expand Down Expand Up @@ -608,7 +637,7 @@ export async function uninstallOtherPackages(
appPackages = await getThirdPartyPackages.bind(this)(filterPackages);
}

this.log.debug(`Uninstalling packages: ${appPackages}`);
this.log.debug(`Uninstalling packages: ${appPackages.join(', ')}`);
await Promise.all(appPackages.map((appPackage) => this.adb.uninstallApk(appPackage)));
}

Expand All @@ -630,7 +659,7 @@ export async function getThirdPartyPackages(this: AndroidDriver, filterPackages:
.trim()
.replace(/package:/g, '')
.split(EOL);
this.log.debug(`'${appPackagesArray}' filtered with '${filterPackages}'`);
this.log.debug(`'${appPackagesArray.join(', ')}' filtered with '${filterPackages.join(', ')}'`);
return appPackagesArray.filter((pkg) => !filterPackagesSet.has(pkg));
} catch (err) {
const error = err as Error;
Expand Down
8 changes: 8 additions & 0 deletions lib/commands/appearance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
mobileGetUiMode(...args: Parameters<typeof mobileGetUiMode>): ReturnType<typeof mobileGetUiMode>;
mobileSetUiMode(...args: Parameters<typeof mobileSetUiMode>): ReturnType<typeof mobileSetUiMode>;
}
}

const RESPONSE_PATTERN = /:\s+(\w+)/;

/**
Expand Down
9 changes: 8 additions & 1 deletion lib/commands/bluetooth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import {errors} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
mobileBluetooth(...args: Parameters<typeof mobileBluetooth>): ReturnType<typeof mobileBluetooth>;
}
}

const SUPPORTED_ACTIONS = {
ENABLE: 'enable',
DISABLE: 'disable',
Expand Down Expand Up @@ -32,7 +39,7 @@ export async function mobileBluetooth(this: AndroidDriver, action: BluetoothActi
break;
default:
throw new errors.InvalidArgumentError(
`You must provide a valid 'action' argument. Supported actions are: ${Object.values(SUPPORTED_ACTIONS)}`,
`You must provide a valid 'action' argument. Supported actions are: ${Object.values(SUPPORTED_ACTIONS).join(', ')}`,
);
}
}
36 changes: 36 additions & 0 deletions lib/commands/context/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {StringRecord} from '@appium/types';
import {Chromedriver} from 'appium-chromedriver';
import {errors, PROTOCOLS} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../../constraints.js';
import type {AndroidDriver} from '../../driver.js';
import {APP_STATE} from '../app-management.js';
import {BIDI_EVENT_NAME} from '../bidi/constants.js';
Expand All @@ -22,6 +23,41 @@ import {
shouldDismissChromeWelcome,
} from './helpers.js';

declare module '../../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
getContexts(...args: Parameters<typeof getContexts>): ReturnType<typeof getContexts>;
getCurrentContext(...args: Parameters<typeof getCurrentContext>): ReturnType<typeof getCurrentContext>;
defaultContextName(...args: Parameters<typeof defaultContextName>): ReturnType<typeof defaultContextName>;
assignContexts(...args: Parameters<typeof assignContexts>): ReturnType<typeof assignContexts>;
switchContext(...args: Parameters<typeof switchContext>): ReturnType<typeof switchContext>;
defaultWebviewName(...args: Parameters<typeof defaultWebviewName>): ReturnType<typeof defaultWebviewName>;
isChromedriverContext(...args: Parameters<typeof isChromedriverContext>): ReturnType<typeof isChromedriverContext>;
startChromedriverProxy(
...args: Parameters<typeof startChromedriverProxy>
): ReturnType<typeof startChromedriverProxy>;
stopChromedriverProxies(
...args: Parameters<typeof stopChromedriverProxies>
): ReturnType<typeof stopChromedriverProxies>;
suspendChromedriverProxy(
...args: Parameters<typeof suspendChromedriverProxy>
): ReturnType<typeof suspendChromedriverProxy>;
startChromeSession(...args: Parameters<typeof startChromeSession>): ReturnType<typeof startChromeSession>;
onChromedriverStop(...args: Parameters<typeof onChromedriverStop>): ReturnType<typeof onChromedriverStop>;
isWebContext(...args: Parameters<typeof isWebContext>): ReturnType<typeof isWebContext>;
mobileGetContexts(...args: Parameters<typeof mobileGetContexts>): ReturnType<typeof mobileGetContexts>;
mobileGetChromeCapabilities(
...args: Parameters<typeof mobileGetChromeCapabilities>
): ReturnType<typeof mobileGetChromeCapabilities>;
setContext(name?: string): Promise<void>;
setWindow(...args: Parameters<typeof setWindow>): ReturnType<typeof setWindow>;
getWindowHandle(...args: Parameters<typeof getWindowHandle>): ReturnType<typeof getWindowHandle>;
getWindowHandles(...args: Parameters<typeof getWindowHandles>): ReturnType<typeof getWindowHandles>;
notifyBiDiContextChange(
...args: Parameters<typeof notifyBiDiContextChange>
): ReturnType<typeof notifyBiDiContextChange>;
}
}

// https://github.com/appium/appium/issues/20710
const DEFAULT_NATIVE_WINDOW_HANDLE = '1';

Expand Down
12 changes: 11 additions & 1 deletion lib/commands/device/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {retryInterval} from 'asyncbox';
import {SETTINGS_HELPER_ID} from 'io.appium.settings';
import * as semver from 'semver';

import type {AndroidDriverConstraints} from '../../constraints.js';
import type {AndroidDriver} from '../../driver.js';
import {GET_SERVER_LOGS_FEATURE, nativeLogEntryToSeleniumEntry} from '../../utils.js';
import {setMockLocationApp} from '../geolocation.js';
Expand All @@ -13,6 +14,15 @@ import {adjustTimeZone} from '../time.js';
import type {ADBDeviceInfo, ADBLaunchInfo} from '../types.js';
import {createBaseADB, prepareEmulator, pushSettingsApp} from './utils.js';

declare module '../../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
getDeviceInfoFromCaps(...args: Parameters<typeof getDeviceInfoFromCaps>): ReturnType<typeof getDeviceInfoFromCaps>;
createADB(...args: Parameters<typeof createADB>): ReturnType<typeof createADB>;
getLaunchInfo(...args: Parameters<typeof getLaunchInfo>): ReturnType<typeof getLaunchInfo>;
initDevice(...args: Parameters<typeof initDevice>): ReturnType<typeof initDevice>;
}
}

/**
* Gets device information from capabilities, including UDID and emulator port.
*
Expand Down Expand Up @@ -48,7 +58,7 @@ export async function getDeviceInfoFromCaps(this: AndroidDriver): Promise<ADBDev

// a platform version was given. lets try to find a device with the same os
const platformVersion = semver.coerce(this.opts.platformVersion) || this.opts.platformVersion;
this.log.info(`Looking for a device with Android '${platformVersion}'`);
this.log.info(`Looking for a device with Android '${String(platformVersion)}'`);

// in case we fail to find something, give the user a useful log that has
// the device udids and os versions so they know what's available
Expand Down
23 changes: 23 additions & 0 deletions lib/commands/device/emulator-actions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
import {util} from '@appium/support';
import {errors} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../../constraints.js';
import type {AndroidDriver} from '../../driver.js';
import type {GsmAction, GsmSignalStrength, GsmVoiceState, PowerACState, NetworkSpeed} from '../types.js';
import {requireEmulator} from './utils.js';

declare module '../../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
fingerprint(...args: Parameters<typeof fingerprint>): ReturnType<typeof fingerprint>;
mobileFingerprint(...args: Parameters<typeof mobileFingerprint>): ReturnType<typeof mobileFingerprint>;
sendSMS(...args: Parameters<typeof sendSMS>): ReturnType<typeof sendSMS>;
mobileSendSms(...args: Parameters<typeof mobileSendSms>): ReturnType<typeof mobileSendSms>;
gsmCall(...args: Parameters<typeof gsmCall>): ReturnType<typeof gsmCall>;
mobileGsmCall(...args: Parameters<typeof mobileGsmCall>): ReturnType<typeof mobileGsmCall>;
gsmSignal(...args: Parameters<typeof gsmSignal>): ReturnType<typeof gsmSignal>;
mobileGsmSignal(...args: Parameters<typeof mobileGsmSignal>): ReturnType<typeof mobileGsmSignal>;
gsmVoice(...args: Parameters<typeof gsmVoice>): ReturnType<typeof gsmVoice>;
mobileGsmVoice(...args: Parameters<typeof mobileGsmVoice>): ReturnType<typeof mobileGsmVoice>;
powerAC(...args: Parameters<typeof powerAC>): ReturnType<typeof powerAC>;
mobilePowerAc(...args: Parameters<typeof mobilePowerAc>): ReturnType<typeof mobilePowerAc>;
powerCapacity(...args: Parameters<typeof powerCapacity>): ReturnType<typeof powerCapacity>;
mobilePowerCapacity(...args: Parameters<typeof mobilePowerCapacity>): ReturnType<typeof mobilePowerCapacity>;
networkSpeed(...args: Parameters<typeof networkSpeed>): ReturnType<typeof networkSpeed>;
mobileNetworkSpeed(...args: Parameters<typeof mobileNetworkSpeed>): ReturnType<typeof mobileNetworkSpeed>;
sensorSet(...args: Parameters<typeof sensorSet>): ReturnType<typeof sensorSet>;
}
}

/**
* @deprecated Use mobile: extension
*/
Expand Down
9 changes: 9 additions & 0 deletions lib/commands/device/emulator-console.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import {errors} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../../constraints.js';
import type {AndroidDriver} from '../../driver.js';

declare module '../../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
mobileExecEmuConsoleCommand(
...args: Parameters<typeof mobileExecEmuConsoleCommand>
): ReturnType<typeof mobileExecEmuConsoleCommand>;
}
}

const EMU_CONSOLE_FEATURE = 'emulator_console';

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/commands/device/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function ensureNetworkSpeed(this: AndroidDriver, networkSpeed: string): s
}
this.log.warn(
`Wrong network speed param '${networkSpeed}', using default: ${this.adb.NETWORK_SPEED.FULL}. ` +
`Supported values: ${Object.values(this.adb.NETWORK_SPEED)}`,
`Supported values: ${Object.values(this.adb.NETWORK_SPEED).join(', ')}`,
);
return this.adb.NETWORK_SPEED.FULL;
}
Expand All @@ -50,8 +50,8 @@ export function prepareAvdArgs(this: AndroidDriver): string[] {
if (avdArgs) {
if (Array.isArray(avdArgs)) {
result.push(...avdArgs);
} else {
result.push(...util.shellParse(`${avdArgs}`).filter((entry): entry is string => typeof entry === 'string'));
} else if (typeof avdArgs === 'string') {
result.push(...util.shellParse(avdArgs).filter((entry): entry is string => typeof entry === 'string'));
}
}
if (networkSpeed) {
Expand Down
9 changes: 8 additions & 1 deletion lib/commands/deviceidle.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import {errors} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
mobileDeviceidle(...args: Parameters<typeof mobileDeviceidle>): ReturnType<typeof mobileDeviceidle>;
}
}

const SUPPORTED_ACTIONS = ['whitelistAdd', 'whitelistRemove'] as const;

/**
Expand Down Expand Up @@ -36,7 +43,7 @@ export async function mobileDeviceidle(
break;
default:
throw new errors.InvalidArgumentError(
`action must be one of ${JSON.stringify(SUPPORTED_ACTIONS)}. Got '${action}' instead`,
`action must be one of ${JSON.stringify(SUPPORTED_ACTIONS)}. Got '${String(action)}' instead`,
);
}
await this.adb.shellChunks(argsGenerator, packagesArr);
Expand Down
21 changes: 21 additions & 0 deletions lib/commands/element.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
import type {AndroidDriverConstraints} from '../constraints.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
getAttribute(...args: Parameters<typeof getAttribute>): ReturnType<typeof getAttribute>;
getName(...args: Parameters<typeof getName>): ReturnType<typeof getName>;
elementDisplayed(...args: Parameters<typeof elementDisplayed>): ReturnType<typeof elementDisplayed>;
elementEnabled(...args: Parameters<typeof elementEnabled>): ReturnType<typeof elementEnabled>;
elementSelected(...args: Parameters<typeof elementSelected>): ReturnType<typeof elementSelected>;
setElementValue(...args: Parameters<typeof setElementValue>): ReturnType<typeof setElementValue>;
doSetElementValue(...args: Parameters<typeof doSetElementValue>): ReturnType<typeof doSetElementValue>;
replaceValue(...args: Parameters<typeof replaceValue>): ReturnType<typeof replaceValue>;
setValueImmediate(...args: Parameters<typeof setValueImmediate>): ReturnType<typeof setValueImmediate>;
setValue(...args: Parameters<typeof setValue>): ReturnType<typeof setValue>;
click(...args: Parameters<typeof click>): ReturnType<typeof click>;
getLocationInView(...args: Parameters<typeof getLocationInView>): ReturnType<typeof getLocationInView>;
getText(...args: Parameters<typeof getText>): ReturnType<typeof getText>;
getLocation(...args: Parameters<typeof getLocation>): ReturnType<typeof getLocation>;
getSize(...args: Parameters<typeof getSize>): ReturnType<typeof getSize>;
}
}
/* eslint-disable @typescript-eslint/no-unused-vars */

import type {Position, Size} from '@appium/types';
Expand Down
7 changes: 7 additions & 0 deletions lib/commands/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import type {StringRecord, Element} from '@appium/types';
import type {Chromedriver} from 'appium-chromedriver';
import {errors, PROTOCOLS} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
execute(...args: Parameters<typeof execute>): ReturnType<typeof execute>;
}
}

const EXECUTE_SCRIPT_PREFIX = 'mobile:';

type ExecuteMethodArgs = readonly any[] | readonly [StringRecord] | Readonly<StringRecord>;
Expand Down
10 changes: 10 additions & 0 deletions lib/commands/file-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@ import {fs, util, zip, tempDir} from '@appium/support';
import type {ADB} from 'appium-adb';
import {errors} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
pullFile(...args: Parameters<typeof pullFile>): ReturnType<typeof pullFile>;
pullFolder(...args: Parameters<typeof pullFolder>): ReturnType<typeof pullFolder>;
pushFile(...args: Parameters<typeof pushFile>): ReturnType<typeof pushFile>;
mobileDeleteFile(...args: Parameters<typeof mobileDeleteFile>): ReturnType<typeof mobileDeleteFile>;
}
}

const CONTAINER_PATH_MARKER = '@';
const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`, 's');
const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE';
Expand Down
9 changes: 9 additions & 0 deletions lib/commands/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ import {util} from '@appium/support';
import type {Element} from '@appium/types';
import {errors, isErrorType} from 'appium/driver.js';

import type {AndroidDriverConstraints} from '../constraints.js';
import type {AndroidDriver} from '../driver.js';
import type {FindElementOpts} from './types.js';

declare module '../driver.js' {
interface AndroidDriver<C extends AndroidDriverConstraints> {
findElOrEls(strategy: string, selector: string, mult: true, context?: string): Promise<Element[]>;
findElOrEls(strategy: string, selector: string, mult: false, context?: string): Promise<Element>;
doFindElementOrEls(...args: Parameters<typeof doFindElementOrEls>): ReturnType<typeof doFindElementOrEls>;
}
}

/**
* @param strategy The element location strategy to use (e.g., 'id', 'xpath', 'class name').
* @param selector The selector value to search for.
Expand Down
Loading
Loading