Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: appium v2 support #3622

Merged
merged 13 commits into from
May 28, 2023
51 changes: 49 additions & 2 deletions docs/mobile.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,69 @@ To install Appium use npm:
npm i -g appium
```

To use Appium 2.x:
```sh
npm i -g appium@next
```
Appium 2x (still beta) reenvisions Appium as a platform where “drivers” and “plugins” can be easily created and shared independently.
Install an Appium driver and its dependencies
To install the Appium driver and its dependencies, we'll be using the uiautomator2 (Android), XCUITest (iOS) drivers.

```
appium driver install xcuitest
appium driver install uiautomator2
```
To make sure that all the drivers are installed successfully, run the following command:

```
appium driver list

tth~$appium driver list
✔ Listing available drivers
- [email protected] [installed (NPM)]
- [email protected] [installed (NPM)]
- [email protected] [installed (NPM)]
- mac2 [not installed]
- safari [not installed]
- gecko [not installed]
- chromium [not installed]
```

Then you need to prepare application for execution.
It should be packed into apk (for Android) or .ipa (for iOS) or zip.

Next, is to launch the emulator or connect physical device.
Next, is to launch the emulator or connect a physical device.
Once they are prepared, launch Appium:

```sh
appium
```

To use Appium 2.x:
```sh
tth~$npx appium --base-path=/wd/hub
[Appium] Welcome to Appium v2.0.0-beta.57 (REV 3e675c32ae71dc0b00749d5d29213e2ea5b53c5b)
[Appium] Non-default server args:
[Appium] {
[Appium] basePath: '/wd/hub'
[Appium] }
[Appium] Attempting to load driver espresso...
[debug] [Appium] Requiring driver at /Users/trung-thanh/Desktop/thanh-nguyen/task2/node_modules/appium-espresso-driver
[Appium] Attempting to load driver uiautomator2...
[debug] [Appium] Requiring driver at /Users/trung-thanh/Desktop/thanh-nguyen/task2/node_modules/appium-uiautomator2-driver
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
[Appium] Available drivers:
[Appium] - [email protected] (automationName 'Espresso')
[Appium] - [email protected] (automationName 'UiAutomator2')
[Appium] No plugins have been installed. Use the "appium plugin" command to install the one(s) you want to use.
```

To run mobile test you need either an device emulator (available with Android SDK or iOS), real device connected for mobile testing. Alternatively, you may execute Appium with device emulator inside Docker container.

CodeceptJS should be installed with webdriverio support:

```bash
npm install codeceptjs webdriverio --save
npm install codeceptjs webdriverio@8.6.3 --save
```

## Configuring
Expand Down
41 changes: 35 additions & 6 deletions lib/helper/Appium.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class Appium extends Webdriver {
super(config);

this.isRunning = false;
if (config.appiumV2 === true) {
this.appiumV2 = true;
}
this.axios = axios.create();

webdriverio = require('webdriverio');
Expand Down Expand Up @@ -181,14 +184,22 @@ class Appium extends Webdriver {

config.baseUrl = config.url || config.baseUrl;
if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
config.capabilities = config.desiredCapabilities;
config.capabilities = this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities;
}

if (this.appiumV2) {
config.capabilities['appium:deviceName'] = config['appium:device'] || config.capabilities['appium:deviceName'];
config.capabilities['appium:broswerName'] = config['appium:broswer'] || config.capabilities['appium:broswerName'];
config.capabilities['appium:app'] = config['appium:app'] || config.capabilities['appium:app'];
config.capabilities['appium:tunnelIdentifier'] = config['appium:tunnelIdentifier'] || config.capabilities['appium:tunnelIdentifier']; // Adding the code to connect to sauce labs via sauce tunnel
} else {
config.capabilities.deviceName = config.device || config.capabilities.deviceName;
config.capabilities.broswerName = config.broswer || config.capabilities.broswerName;
config.capabilities.app = config.app || config.capabilities.app;
config.capabilities.tunnelIdentifier = config.tunnelIdentifier || config.capabilities.tunnelIdentifier; // Adding the code to connect to sauce labs via sauce tunnel
}

config.capabilities.deviceName = config.device || config.capabilities.deviceName;
config.capabilities.browserName = config.browser || config.capabilities.browserName;
config.capabilities.app = config.app || config.capabilities.app;
config.capabilities.platformName = config.platform || config.capabilities.platformName;
config.capabilities.tunnelIdentifier = config.tunnelIdentifier || config.capabilities.tunnelIdentifier; // Adding the code to connect to sauce labs via sauce tunnel
config.waitForTimeoutInSeconds = config.waitForTimeout / 1000; // convert to seconds

// [CodeceptJS compatible] transform host to hostname
Expand All @@ -203,13 +214,25 @@ class Appium extends Webdriver {
}

this.platform = null;
if (config.capabilities['appium:platformName']) {
this.platform = config.capabilities['appium:platformName'].toLowerCase();
}

if (config.capabilities.platformName) {
this.platform = config.capabilities.platformName.toLowerCase();
}

return config;
}

_convertAppiumV2Caps(capabilities) {
const _convertedCaps = {};
for (const [key, value] of Object.entries(capabilities)) {
_convertedCaps[`appium:${key}`] = value;
}
return _convertedCaps;
}

static _config() {
return [{
name: 'app',
Expand All @@ -229,6 +252,11 @@ class Appium extends Webdriver {
}

async _startBrowser() {
if (this.appiumV2 === true) {
this.options.capabilities = this._convertAppiumV2Caps(this.options.capabilities);
this.options.desiredCapabilities = this._convertAppiumV2Caps(this.options.desiredCapabilities);
}

try {
if (this.options.multiremote) {
this.browser = await webdriverio.multiremote(this.options.multiremote);
Expand Down Expand Up @@ -445,6 +473,7 @@ class Appium extends Webdriver {
*/
async checkIfAppIsInstalled(bundleId) {
onlyForApps.call(this, supportedPlatform.android);

return this.browser.isAppInstalled(bundleId);
}

Expand Down Expand Up @@ -481,7 +510,7 @@ class Appium extends Webdriver {
async seeAppIsNotInstalled(bundleId) {
onlyForApps.call(this, supportedPlatform.android);
const res = await this.browser.isAppInstalled(bundleId);
return truth(`app ${bundleId}`, 'to be installed').negate(res);
return truth(`app ${bundleId}`, 'not to be installed').negate(res);
}

/**
Expand Down