Skip to content

Commit

Permalink
Merge branch 'master' into no-compose-deps
Browse files Browse the repository at this point in the history
  • Loading branch information
KazuCocoa authored Jul 7, 2024
2 parents 5ce0054 + a49d467 commit 022bb17
Show file tree
Hide file tree
Showing 33 changed files with 370 additions and 161 deletions.
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
## [2.44.1](https://github.com/appium/appium-espresso-driver/compare/v2.44.0...v2.44.1) (2024-07-04)

### Miscellaneous Chores

* Improve gradle log strings handling ([#1019](https://github.com/appium/appium-espresso-driver/issues/1019)) ([7ab3404](https://github.com/appium/appium-espresso-driver/commit/7ab3404809a4c1c4ffc4286bb318d4d3351b5365))

## [2.44.0](https://github.com/appium/appium-espresso-driver/compare/v2.43.0...v2.44.0) (2024-06-28)

### Features

* Add mobile: wrappers to clipboard APIs ([#1018](https://github.com/appium/appium-espresso-driver/issues/1018)) ([13beafb](https://github.com/appium/appium-espresso-driver/commit/13beafb705ad1056fcf3ca8f4cad89fd7af6ca3b))

## [2.43.0](https://github.com/appium/appium-espresso-driver/compare/v2.42.1...v2.43.0) (2024-06-23)

### Features

* Document injectedImageProperties capability ([#1017](https://github.com/appium/appium-espresso-driver/issues/1017)) ([fd6dc1c](https://github.com/appium/appium-espresso-driver/commit/fd6dc1c4cf9f481914701b33ad6d265888d976b7))

## [2.42.1](https://github.com/appium/appium-espresso-driver/compare/v2.42.0...v2.42.1) (2024-06-23)

### Miscellaneous Chores

* Bump chai and chai-as-promised ([#1016](https://github.com/appium/appium-espresso-driver/issues/1016)) ([f3ed4f0](https://github.com/appium/appium-espresso-driver/commit/f3ed4f0a537c352c5805ff557106e9e58b01b49d))

## [2.42.0](https://github.com/appium/appium-espresso-driver/compare/v2.41.0...v2.42.0) (2024-06-16)

### Features
Expand Down
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ appium:avdEnv | Mapping of emulator [environment variables](https://developer.an
appium:networkSpeed | Sets the desired network speed limit for the emulator. It is only applied if the emulator is not running before the test starts. See emulator [command line arguments](https://developer.android.com/studio/run/emulator-commandline) description for more details.
appium:gpsEnabled | Sets whether to enable (`true`) or disable (`false`) GPS service in the Emulator. Unset by default, which means to not change the current value
appium:isHeadless | If set to `true` then emulator starts in headless mode (e.g. no UI is shown). It is only applied if the emulator is not running before the test starts. `false` by default.
appium:injectedImageProperties | Allows adjusting of injected image properties, like size, position or rotation. The image itself is expected to be injected by [mobile: injectEmulatorCameraImage](#mobile-injectemulatorcameraimage) extension. It is also mandatory to provide this capability if you are going to use the injection feature on a newly created/resetted emulator as it __enforces emulator restart__, so it could properly reload the modified image properties. The value itself is a map, where possible keys are `size`, `position` and `rotation`. All of them are optional. If any of values is not provided then the following defaults are used: `{size: {scaleX: 1, scaleY: 1}, position: {x: 0, y: 0, z: -1.5}, rotation: {x: 0, y: 0, z: 0}}`. The `size` value contains scale multipliers for X and Y axes. The `position` contains normalized coefficients for X/Y/Z axes, where `0` means it should be centered in the viewport. Values in the `rotation` are measured in degrees respectively for X, Y and Z axis. The capability is available since the driver version 2.43.0.

### App Signing

Expand Down Expand Up @@ -1261,6 +1262,26 @@ formFields | Map<string, string> or Array<Pair> | no | Additional fo

Base64-encoded content of the recorded media file if `remotePath` argument is falsy or an empty string.

### mobile: getClipboard

Retrieves the plaintext content of the device's clipboard. Available since driver version 2.44

#### Returned Result

Base64-encoded content of the clipboard or an empty string if the clipboard is empty.

### mobile: setClipboard

Allows to set the plain text content of the device's clipboard. Available since driver version 2.44

#### Arguments

Name | Type | Required | Description | Example
--- | --- | --- | --- | ---
content | string | yes | Base64-encoded clipboard payload. | YXBwaXVt
contentType | string | no | The only supported and the default value is `plaintext` | plaintext
lable | string | no | Optinal label to identify the current clipboard payload. | yolo

### mobile: hideKeyboard

Tries to hide the on-screen keyboard. Throws an exception if the keyboard cannot be hidden.
Expand Down Expand Up @@ -1642,6 +1663,51 @@ Starts Android logcat broadcast websocket on the same host and port where Appium

Stops the previously started logcat broadcasting websocket server. This method will return immediately if no server is running. Read [Using Mobile Execution Commands to Continuously Stream Device Logs with Appium](https://appiumpro.com/editions/55-using-mobile-execution-commands-to-continuously-stream-device-logs-with-appium) for more details.

### mobile: injectEmulatorCameraImage

Simulates an image injection into the VirtualScene emulator camera background.
Calls to this extension should seamlessly change the foreground picture
in the VirtualScene emulator camera view to the supplied one.
This extension could, for example, be useful if you need to verify QR codes scanning
by the application under test.
Available since driver version 2.43.0

#### Arguments

Name | Type | Required | Description | Example
--- | --- | --- | --- | ---
payload | string | yes | A valid base64-encoded .PNG image payload. Other image formats are not supported. This image will be shown on the virtual scene foreground as soon as you open a camera client app. | iVBORw0KGgoAAAANSUh...

#### Required Preconditions

This feature only works on Android emulators.
It is mandatory to provide a value (it could also be an empty map to use defaults) to
the [appium:injectedImageProperties capability](#emulator-android-virtual-device)
in order to prepare the emulator for image injection if this extension is used
on a newly created or resetted device.

There is also a possiblity to perform a manual configuration of the necessary preconditions
if you don't want to restart the emulator on session startup. For that replace the content
of the `Toren1BD.posters` file located in `$ANDROID_HOME/emulator/resources` folder with the
following text:

```
poster wall
size 2 2
position -0.807 0.320 5.316
rotation 0 -150 0
default poster.png
poster table
size 1 1
position 0 0 -1.5
rotation 0 0 0
```

Save the changed file and re(start) the emulator to pick up the changes.
You may also customize values for different image properties under `poster table` in the above
text snippet.

## Backdoor Extension Usage

Espresso driver allows to directly invoke a method from your application under test using `mobile: backdoor` extension. If `target` is set to `application` then methods will be invoked on the application class. If target is set to `activity` then methods will be invoked on the current application activity. If target is set to `element` then methods will be invoked on the selected view element. Only 'public' methods can be invoked ('open' modifier is necessary in Kotlin). The following primitive types are supported for method arguments: "int", "boolean", "byte", "short", "long", "float", "char". Object wrappers over primitive types with fully qualified names "java.lang.*" are also supported: "java.lang.CharSequence", "java.lang.String", "java.lang.Integer", "java.lang.Float", "java.lang.Double", "java.lang.Boolean", "java.lang.Long", "java.lang.Short", "java.lang.Character", etc.
Expand Down
41 changes: 41 additions & 0 deletions lib/commands/clipboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @this {import('../driver').EspressoDriver}
* @returns {Promise<string>} Base64-encoded content of the clipboard
* or an empty string if the clipboard is empty.
*/
export async function getClipboard () {
return /** @type {string} */ ((await this.adb.getApiLevel() < 29)
? (await this.espresso.jwproxy.command('/appium/device/get_clipboard', 'POST', {}))
: (await this.settingsApp.getClipboard()));
}

/**
* @typedef {Object} SetClipboardOptions
* @property {string} content Base64-encoded clipboard payload
* @property {'plaintext'} [contentType] Only a single
* content type is supported, which is 'plaintext'
* @property {string} [label] Optinal label to identify the current
* clipboard payload
*/

/**
* @this {EspressoDriver}
* @param {SetClipboardOptions} opts
* @returns {Promise<void>}
*/
export async function mobileSetClipboard(opts) {
const {
content,
contentType,
label,
} = opts;
await this.espresso.jwproxy.command(
'/appium/device/set_clipboard',
'POST',
{content, contentType, label}
);
}

/**
* @typedef {import('../driver').EspressoDriver} EspressoDriver
*/
3 changes: 3 additions & 0 deletions lib/commands/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export function mobileCommandsMapping() {
waitForUIThread: 'mobileWaitForUIThread',

pressKey: 'mobilePressKey',

setClipboard: 'mobileSetClipboard',
getClipboard: 'mobileGetClipboard',
};
}

Expand Down
9 changes: 0 additions & 9 deletions lib/commands/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@ import { util } from 'appium/support';
import { errors } from 'appium/driver';
import { requireOptions } from '../utils';

/**
* @this {import('../driver').EspressoDriver}
*/
export async function getClipboard () {
return (await this.adb.getApiLevel() < 29)
? (await this.espresso.jwproxy.command('/appium/device/get_clipboard', 'POST', {}))
: (await this.settingsApp.getClipboard());
}

/**
* @typedef {Object} PressKeyOptions
* @property {number} [keycode] A valid Android key code. See https://developer.android.com/reference/android/view/KeyEvent
Expand Down
6 changes: 5 additions & 1 deletion lib/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import * as servicesCmds from './commands/services';
import * as screenshotCmds from './commands/screenshot';
import * as idlingResourcesCmds from './commands/idling-resources';
import * as actionsCmds from './commands/actions';
import * as clipboardCmds from './commands/clipboard';
import { DEFAULT_ADB_PORT } from 'appium-adb';
import { AndroidDriver, utils } from 'appium-android-driver';
import { SETTINGS_HELPER_ID } from 'io.appium.settings';
Expand Down Expand Up @@ -726,7 +727,6 @@ export class EspressoDriver extends AndroidDriver implements ExternalDriver<
mobileClickAction = elementCmds.mobileClickAction;
mobileDismissAutofill = elementCmds.mobileDismissAutofill;

getClipboard = miscCmds.getClipboard;
mobilePressKey = miscCmds.mobilePressKey;
mobileGetDeviceInfo = miscCmds.mobileGetDeviceInfo;
mobileIsToastVisible = miscCmds.mobileIsToastVisible;
Expand All @@ -737,6 +737,10 @@ export class EspressoDriver extends AndroidDriver implements ExternalDriver<
updateSettings = miscCmds.updateSettings;
getSettings = miscCmds.getSettings;

getClipboard = clipboardCmds.getClipboard;
mobileGetClipbard = clipboardCmds.getClipboard;
mobileSetClipbard = clipboardCmds.mobileSetClipboard;

mobileStartService = servicesCmds.mobileStartService;
mobileStopService = servicesCmds.mobileStopService;

Expand Down
26 changes: 10 additions & 16 deletions lib/server-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { updateDependencyLines } from './utils';
const GRADLE_VERSION_KEY = 'gradle';
const GRADLE_URL_PREFIX = 'distributionUrl=';
const GRADLE_URL_TEMPLATE = 'https\\://services.gradle.org/distributions/gradle-VERSION-all.zip';
const GRADLE_MAX_ERROR_LOG_LINES = 15;
const DEPENDENCY_PROP_NAMES = ['additionalAppDependencies', 'additionalAndroidTestDependencies'];

const VERSION_KEYS = [
Expand Down Expand Up @@ -175,31 +174,26 @@ class ServerBuilder {
shell: system.isWindows(),
windowsVerbatimArguments: true
});
let buildLastLines = [];
/** @type {string[]} */
let gradleError = [];

const logMsg = `Output from Gradle ${this.showGradleLog ? 'will' : 'will not'} be logged`;
this.log.debug(`${logMsg}. To change this, use 'showGradleLog' desired capability`);
gradlebuild.on('stream-line', (line) => {
if (this.showGradleLog) {
if (line.startsWith('[STDERR]')) {
this.log.warn(`[Gradle] ${line}`);
} else {
this.log.info(`[Gradle] ${line}`);
}
}
buildLastLines.push(`${EOL}${line}`);
if (buildLastLines.length > GRADLE_MAX_ERROR_LOG_LINES) {
buildLastLines = buildLastLines.slice(-GRADLE_MAX_ERROR_LOG_LINES);
}
gradlebuild.on('line-stderr', (line) => {
this.log.warn(`[Gradle] ${line}`);
gradleError.push(line);
});
gradlebuild.on('line-stdout', (line) => this.log.info(`[Gradle] ${line}`));

try {
await gradlebuild.start();
await gradlebuild.join();
} catch (err) {
let msg = `Unable to build Espresso server - ${err.message}\n` +
`Gradle error message:${EOL}${buildLastLines}`;
const msg = `Unable to build Espresso server - ${err.message}\n` +
`Gradle error message:${EOL}${gradleError.join('\n')}`;
this.log.errorAndThrow(msg);
} finally {
gradlebuild.removeAllListeners();
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"automated testing",
"android"
],
"version": "2.42.0",
"version": "2.44.1",
"author": "Appium Contributors",
"license": "Apache-2.0",
"repository": {
Expand Down Expand Up @@ -73,14 +73,14 @@
],
"dependencies": {
"appium-adb": "^12.4.0",
"appium-android-driver": "^9.6.5",
"appium-android-driver": "^9.7.0",
"asyncbox": "^3.0.0",
"bluebird": "^3.5.0",
"io.appium.settings": "^5.12.0",
"lodash": "^4.17.11",
"portscanner": "^2.1.1",
"source-map-support": "^0.x",
"teen_process": "^2.0.0"
"teen_process": "^2.2.0"
},
"scripts": {
"build": "npm run build:node && npm run build:server",
Expand Down Expand Up @@ -112,8 +112,6 @@
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@types/bluebird": "^3.5.38",
"@types/chai": "^4.3.5",
"@types/chai-as-promised": "^7.1.5",
"@types/lodash": "^4.14.196",
"@types/mocha": "^10.0.1",
"@types/node": "^20.4.7",
Expand All @@ -124,8 +122,8 @@
"android-apidemos": "^4.1.1",
"appium-chromedriver": "^5.1.4",
"async-lock": "^1.0.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chai": "^5.1.1",
"chai-as-promised": "^8.0.0",
"conventional-changelog-conventionalcommits": "^8.0.0",
"mocha": "^10.0.0",
"rimraf": "^5.0.0",
Expand Down
14 changes: 8 additions & 6 deletions test/functional/commands/attributes-e2e-specs.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { initSession, deleteSession, MOCHA_TIMEOUT } from '../helpers/session';
import { APIDEMO_CAPS } from '../desired';


chai.should();
chai.use(chaiAsPromised);

describe('element attributes', function () {
this.timeout(MOCHA_TIMEOUT);

let driver;
let chai;

before(async function () {
chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');

chai.should();
chai.use(chaiAsPromised.default);

driver = await initSession(APIDEMO_CAPS);
});
after(async function () {
Expand Down
14 changes: 8 additions & 6 deletions test/functional/commands/clipboard-e2e-specs.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { initSession, deleteSession, MOCHA_TIMEOUT } from '../helpers/session';
import { APIDEMO_CAPS } from '../desired';


chai.should();
chai.use(chaiAsPromised);


describe('clipboard', function () {
this.timeout(MOCHA_TIMEOUT);

let driver;
let chai;

before(async function () {
chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');

chai.should();
chai.use(chaiAsPromised.default);

driver = await initSession(APIDEMO_CAPS);
});
after(async function () {
Expand Down
14 changes: 8 additions & 6 deletions test/functional/commands/contexts-e2e-specs.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { initSession, deleteSession, MOCHA_TIMEOUT } from '../helpers/session';
import { APIDEMO_CAPS } from '../desired';


chai.should();
chai.use(chaiAsPromised);


describe('context', function () {
this.timeout(MOCHA_TIMEOUT);

let driver;
let chai;

before(async function () {
chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');

chai.should();
chai.use(chaiAsPromised.default);

let caps = Object.assign({
appActivity: 'io.appium.android.apis.view.WebView1',
}, APIDEMO_CAPS);
Expand Down
Loading

0 comments on commit 022bb17

Please sign in to comment.