Skip to content

Commit

Permalink
feat: Add support of executeMethodMap (#982)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The following driver methods and properties were removed:

- executeMobile
- mobileCommandsMapping
- mobileLock
- mobilePushFile
- mobilePullFolder
- mobilePullFile
- mobileActivateApp
- mobileQueryAppState

BREAKING CHANGE: Arguments of the following driver methods were changed:

- mobileExecEmuConsoleCommand
- mobileShell
- mobileChangePermissions
- mobileGetPermissions
- mobilePerformEditorAction
- mobileGetDeviceTime
- mobileStartScreenStreaming
- mobileDeleteFile
- mobileIsAppInstalled
- mobileRemoveApp
- mobileTerminateApp
- mobileInstallApp
- mobileClearApp
- mobileStartService
- mobileStopService
- mobileStartActivity
- mobileBroadcast
- mobileGetContexts
- mobileUnlock
- mobileRefreshGpsCache
- mobileStartMediaProjectionRecording
- mobileStopMediaProjectionRecording
- mobileGetConnectivity
- mobileSetConnectivity
- mobileDeviceidle
- mobileBluetooth
- mobileNfc
- mobileSetUiMode
- mobileGetUiMode
- mobileInjectEmulatorCameraImage
- mobileSendTrimMemory
- mobileGetPerformanceData
- mobilePerformStatusBarCommand
- mobileFingerprint
- mobileSendSms
- mobileGsmCall
- mobileGsmSignal
- mobileGsmVoice
- mobilePowerAc
- mobilePowerCapacity
- mobileNetworkSpeed
- sensorSet
- mobileSetGeolocation

BREAKING CHANGE: The following obsolete type definitions were removed:

- ExecOptions
- ShellOpts
- ChangePermissionsOpts
- GetPermissionsOpts
- PerformEditorActionOpts
- DeviceTimeOpts
- StartScreenStreamingOpts
- PushFileOpts
- PullFolderOpts
- PullFileOpts
- DeleteFileOpts
- IsAppInstalledOpts
- ActivateAppOpts
- QueryAppStateOpts
- RemoveAppOpts
- TerminateAppOpts
- InstallAppOpts
- ClearAppOpts
- StartServiceOpts
- StopServiceOpts
- StartActivityOpts
- BroadcastOpts
- LockOpts
- UnlockOptions
- GpsCacheRefreshOpts
- StartMediaProjectionRecordingOpts
- StopMediaProjectionRecordingOpts
- GetConnectivityOpts
- SetConnectivityOpts
- DeviceidleOpts
- BluetoothOptions
- NfcOptions
- SetUiModeOpts
- GetUiModeOpts
- ImageInjectionOpts
- SendTrimMemoryOpts
- PerformanceDataOpts
- StatusBarCommandOpts
- FingerprintOpts
- SendSMSOpts
- GsmCallOpts
- GsmSignalStrengthOpts
- GsmVoiceState
- PowerACOpts
- PowerCapacityOpts
- NetworkSpeedOpts
- SensorSetOpts
- DragOpts
- SwipeOpts
  • Loading branch information
mykola-mokhnach authored Jan 31, 2025
1 parent dd55883 commit b68f3fa
Show file tree
Hide file tree
Showing 29 changed files with 1,034 additions and 1,057 deletions.
110 changes: 68 additions & 42 deletions lib/commands/app-management.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {util} from '@appium/support';
import {waitForCondition, longSleep} from 'asyncbox';
import _ from 'lodash';
import {requireArgs} from '../utils';
import {EOL} from 'node:os';
import B from 'bluebird';

Expand Down Expand Up @@ -33,11 +32,12 @@ export async function isAppInstalled(appId, opts = {}) {

/**
* @this {AndroidDriver}
* @param {import('./types').IsAppInstalledOpts} opts
* @param {string} appId Application package identifier
* @param {string | number} [user] The user ID for which the package is installed.
* The `current` user id is used by default.
* @returns {Promise<boolean>}
*/
export async function mobileIsAppInstalled(opts) {
const {appId, user} = requireArgs('appId', opts);
export async function mobileIsAppInstalled(appId, user) {
const _opts = {};
if (util.hasValue(user)) {
_opts.user = `${user}`;
Expand All @@ -47,7 +47,7 @@ export async function mobileIsAppInstalled(opts) {

/**
* @this {AndroidDriver}
* @param {string} appId
* @param {string} appId Application package identifier
* @returns {Promise<import('./types').AppState>}
*/
export async function queryAppState(appId) {
Expand All @@ -69,33 +69,13 @@ export async function queryAppState(appId) {

/**
* @this {AndroidDriver}
* @param {import('./types').QueryAppStateOpts} opts
* @returns {Promise<import('./types').AppState>}
*/
export async function mobileQueryAppState(opts) {
const {appId} = requireArgs('appId', opts);
return await this.queryAppState(appId);
}

/**
* @this {AndroidDriver}
* @param {string} appId
* @param {string} appId Application package identifier
* @returns {Promise<void>}
*/
export async function activateApp(appId) {
return await this.adb.activateApp(appId);
}

/**
* @this {AndroidDriver}
* @param {import('./types').ActivateAppOpts} opts
* @returns {Promise<void>}
*/
export async function mobileActivateApp(opts) {
const {appId} = requireArgs('appId', opts);
return await this.adb.activateApp(appId);
}

/**
* @this {AndroidDriver}
* @param {string} appId
Expand All @@ -108,18 +88,27 @@ export async function removeApp(appId, opts = {}) {

/**
* @this {import('../driver').AndroidDriver}
* @param {import('./types').RemoveAppOpts} opts
* @param {string} appId Application package identifier
* @param {number} [timeout] The count of milliseconds to wait until the
* app is uninstalled.
* @param {boolean} [keepData] Set to true in order to keep the
* application data and cache folders after uninstall.
* @param {boolean} [skipInstallCheck] Whether to check if the app is installed prior to
* uninstalling it. By default this is checked.
* @returns {Promise<boolean>}
*/
export async function mobileRemoveApp(opts) {
const {appId} = requireArgs('appId', opts);
return await this.removeApp(appId, opts);
export async function mobileRemoveApp(appId, timeout, keepData, skipInstallCheck) {
return await this.removeApp(appId, {
timeout,
keepData,
skipInstallCheck,
});
}

/**
* @this {AndroidDriver}
* @param {string} appId
* @param {Omit<import('./types').TerminateAppOpts, 'appId'>} [options={}]
* @param {import('./types').TerminateAppOpts} [options={}]
* @returns {Promise<boolean>}
*/
export async function terminateApp(appId, options = {}) {
Expand Down Expand Up @@ -180,12 +169,15 @@ export async function terminateApp(appId, options = {}) {

/**
* @this {AndroidDriver}
* @param {import('./types').TerminateAppOpts} opts
* @param {string} appId Application package identifier
* @param {number|string} [timeout] The count of milliseconds to wait until the app is terminated.
* 500ms by default.
* @returns {Promise<boolean>}
*/
export async function mobileTerminateApp(opts) {
const {appId} = requireArgs('appId', opts);
return await this.terminateApp(appId, opts);
export async function mobileTerminateApp(appId, timeout) {
return await this.terminateApp(appId, {
timeout,
});
}

/**
Expand All @@ -201,14 +193,49 @@ export async function installApp(appPath, opts) {

/**
* @this {AndroidDriver}
* @param {import('./types').InstallAppOpts} opts
* @param {string} appPath
* @param {boolean} [checkVersion]
* @param {number} [timeout] The count of milliseconds to wait until the app is installed.
* 20000ms by default.
* @param {boolean} [allowTestPackages] Set to true in order to allow test packages installation.
* `false` by default.
* @param {boolean} [useSdcard] Set to true to install the app on sdcard instead of the device memory.
* `false` by default.
* @param {boolean} [grantPermissions] Set to true in order to grant all the
* permissions requested in the application's manifest automatically after the installation is completed
* under Android 6+. `false` by default.
* @param {boolean} [replace] Set it to false if you don't want the application to be upgraded/reinstalled
* if it is already present on the device. `true` by default.
* @param {boolean} [noIncremental] Forcefully disables incremental installs if set to `true`.
* Read https://developer.android.com/preview/features#incremental for more details.
* `false` by default.
* @returns {Promise<void>}
*/
export async function mobileInstallApp(opts) {
const {appPath, checkVersion} = requireArgs('appPath', opts);
export async function mobileInstallApp(
appPath,
checkVersion,
timeout,
allowTestPackages,
useSdcard,
grantPermissions,
replace,
noIncremental,
) {
const opts = {
timeout,
allowTestPackages,
useSdcard,
grantPermissions,
replace,
noIncremental,
};
if (checkVersion) {
const localPath = await this.helpers.configureApp(appPath, APP_EXTENSIONS);
await this.adb.installOrUpgrade(localPath, null, Object.assign({}, opts, {enforceCurrentBuild: false}));
await this.adb.installOrUpgrade(localPath, null, Object.assign({}, {
appPath,
checkVersion,
...opts,
}, {enforceCurrentBuild: false}));
return;
}

Expand All @@ -217,11 +244,10 @@ export async function mobileInstallApp(opts) {

/**
* @this {AndroidDriver}
* @param {import('./types').ClearAppOpts} opts
* @param {string} appId Application package identifier
* @returns {Promise<void>}
*/
export async function mobileClearApp(opts) {
const {appId} = requireArgs('appId', opts);
export async function mobileClearApp(appId) {
await this.adb.clear(appId);
}

Expand Down
18 changes: 10 additions & 8 deletions lib/commands/appearance.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import {requireArgs} from '../utils';

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

/**
* Set the Ui appearance.
*
* @since Android 10
* @this {import('../driver').AndroidDriver}
* @property {import('./types').SetUiModeOpts}
* @param {string} mode The UI mode to set the value for.
* Supported values are: 'night' and 'car'
* @param {string} value The actual mode value to set.
* Supported value for different UI modes are:
* - night: yes|no|auto|custom_schedule|custom_bedtime
* - car: yes|no
* @returns {Promise<void>}
*/
export async function mobileSetUiMode(opts) {
const {mode, value} = requireArgs(['mode', 'value'], opts);
export async function mobileSetUiMode(mode, value) {
await this.adb.shell(['cmd', 'uimode', mode, value]);
}

Expand All @@ -20,12 +22,12 @@ export async function mobileSetUiMode(opts) {
*
* @since Android 10
* @this {import('../driver').AndroidDriver}
* @property {import('./types').GetUiModeOpts}
* @param {string} mode The UI mode to set the value for.
* Supported values are: 'night' and 'car'
* @returns {Promise<string>} The actual state for the queried UI mode,
* for example 'yes' or 'no'
*/
export async function mobileGetUiMode(opts) {
const {mode} = requireArgs(['mode'], opts);
export async function mobileGetUiMode(mode) {
const response = await this.adb.shell(['cmd', 'uimode', mode]);
// response looks like 'Night mode: no'
const match = RESPONSE_PATTERN.exec(response);
Expand Down
5 changes: 2 additions & 3 deletions lib/commands/bluetooth.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ const SUPPORTED_ACTIONS = /** @type {const} */ ({
* Performs the requested action on the default bluetooth adapter
*
* @this {AndroidDriver}
* @param {import('./types').BluetoothOptions} opts
* @param {'enable' | 'disable' | 'unpairAll'} action
* @returns {Promise<void>}
* @throws {Error} if the device under test has no default bluetooth adapter
* or there was a failure while performing the action.
*/
export async function mobileBluetooth(opts) {
const {action} = opts;
export async function mobileBluetooth(action) {
switch (action) {
case SUPPORTED_ACTIONS.ENABLE:
await this.settingsApp.setBluetoothState(true);
Expand Down
6 changes: 3 additions & 3 deletions lib/commands/context/exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,16 @@ export async function setContext(name) {

/**
* @this {AndroidDriver}
* @param {any} [opts={}]
* @param {number} [waitForWebviewMs]
* @returns {Promise<import('../types').WebviewsMapping[]>}
*/
export async function mobileGetContexts(opts = {}) {
export async function mobileGetContexts(waitForWebviewMs) {
const _opts = {
androidDeviceSocket: this.opts.androidDeviceSocket,
ensureWebviewsHavePages: true,
webviewDevtoolsPort: this.opts.webviewDevtoolsPort,
enableWebviewDetailsCollection: true,
waitForWebviewMs: opts.waitForWebviewMs || 0,
waitForWebviewMs: waitForWebviewMs || 0,
};
return await getWebViewsMapping.bind(this)(_opts);
}
Expand Down
Loading

0 comments on commit b68f3fa

Please sign in to comment.