wdi5 v0.7.0
wdi5 
Extension to Webdriver.IO for testing a hybrid, cordova-wrapped UI5 app on iOS, Android and Electron.
Includes all capabilites of its’ lightweight sibling wdio-ui5-service for browser-scoped tests.
Table of Contents
Prerequisites
- UI5 app (built with
cordova)- iOS:
.ipa(device-type build) or.app(emulator-type build) + iOS simulator - Android:
.apk+ emulator - Electron: binary
- iOS:
- node version >=
12.x(lts/erbium) - (optional)
yarnduring development, we rely onyarn’s workspace-features - that’s why we refer toyarninstead ofnpmin the docs, even though usingnpmas an equivalent shold be fine too
Getting started
Installation
Using wdi5 is essentially configuring wdio with wdi5-specific options on top.
The recommended development approach is to first write and execute the tests in the browser-context, then run the tests on native devices/emulators or against the electron-app.
# install the node module
$> yarn add -D wdi5
# Generate a standard `wdio.conf.js` via the
# standard webdriver.io-tools:
$> npx wdio config # this will also install standard wdio-dependenciesbrowser-scope
Note that even though wdi5 includes the functionality of its’ lightweight sibling wdio-ui5-service (the Webdriver.IO-plugin) for browser-based testing, you don’t need to add ui5 to the services-section of wdio.conf.js - the browser-functionality is included when injecting wdi5 . For this, require 'wdi5/lib/service/wdi5.service' as shown below.
Enhance the wdio.conf.js-file with the recommended wdi5 settings:
const WDI5Service = require('wdi5/lib/service/wdi5.service'); // bridge to browser-scope
exports.config = {
// ...
baseUrl: "http://localhost:8080", // standard webdriver.io
// wdi5-specific
services: [
'chromedriver',
[WDI5Service]
]
wdi5: {
screenshotPath: "./test/report/screenshots", // [optional] using the project root
screenshotsDisabled: false // [optional] {Boolean}; if set to true screenshots won't be taken and not written to file system
logLevel: "verbose", // [optional] error | silent | verbose
platform: "browser", // [mandatory] android | browser | electron | ios
deviceType: "web" // [mandatory] native (ios, android) | web (browser, electron)
path: '/some/native/device/path' // [optional] path to your android or ios webapp
// if your ui5 app under test
// is served by anything other than the ui5 tooling,
// set this option explicity to false (defaults to true)
}
// ...
services: [
'chromedriver',
[WDI5Service]
]
}Then, start your local webserver (e.g. via $> soerver in the app directory),
and kick off your tests via $> npx wdio.
General (non-browser) setup
We like to always have all parts of the test-environment running in parallel:
- manually started simulator/emulator
appiume.g. viayarn _startApp:ios(orchromedriverfor electron)- test execution, e.g.
yarn _test:ios
You can combine all of the above by running yarn test:<platform> (e.g. yarn test:ios), catering towards a ci environment, at the cost of losing the flexibility of each tooling.
Also, it is recommended to split up the overall configuration in a shared- and a platform-specific part - this helps with overview and maintenance. See wdio-shared.conf.js and wdio-${platform}.conf.js in the top-level /test-folder as an example.
shared config file
Setup appium-specific and platform-independent configuration settings in a wdio-shared.conf.js :
const WDI5Service = require('wdi5')
exports.config = { // we export it as a module since this file is required in wdio-${platform}.conf.js
// 4723 is the default port for Appium
port: 4723,
maxInstances: 1,
// path to tests
specs: [path.join('test', 'ui5-app', 'webapp', 'test', 'e2e', '*.js')],
// tell wdio to use the wdi5 extenstion
services: [
[WDI5Service]
],
waitforTimeout: 60000, // well...
// syntax style for the test files
framework: 'mocha',
mochaOpts: {
timeout: 90000 // well...
},
wdi5: {
deviceType: 'native' // native | web
screenshotPath: require('path').join('test', 'report', 'screenshots'),
logLevel: 'verbose', // error | verbose | silent
// platform: '...', // browser | android | ios | electron -> set in wdio-${platform}.conf.js
}
}iOS
First, make sure all prerequisites mentioned in http://appium.io/docs/en/drivers/ios-xcuitest/index.html for XCUITest-based testing are fullfilled.
Create an iOS-specific config file (e.g. wdi5-ios.conf.js).
In there, require the shared config file and set platform-specific options:
const path = require('path');
let config = require('./wdio-shared.conf').config;
config.capabilities = [
{
automationName: 'XCUITest',
platformName: 'iOS',
// iOS version
platformVersion: '14.0',
// For iOS, this must exactly match the (simulator) device name as seen in Xcode.
deviceName: 'iPhone 11',
// Where to find the .apk or .ipa file to install on the device.
// The exact location of the file may change depending on your cordova build!
app: path.join('test', 'ui5-app', 'app', 'platforms', 'ios', 'build', 'emulator', 'UI5.app'),
// by default, appium runs tests in the native context. By setting autoWebview to
// true, it runs our tests in the Cordova context.
autoWebview: true,
// display simulator window
isHeadless: false,
// http://appium.io/docs/en/drivers/ios-xcuitest/#capabilities
// https://appiumpro.com/editions/43-setting-ios-app-permissions-automatically
// https://github.com/wix/AppleSimulatorUtils
permissions: '{"jss.wdi5.sample": {"camera": "yes","notifications": "yes"}}'
}
];
config.outputDir = path.join('test', 'report', 'logs');
// tell wdi5 we're running on iOS
config.wdi5.platform = 'ios';
exports.config = config;Refer to the xcuitest-driver capabilities documentation for a complete list of possible settings for the capabilities-section!
Start appium with your desired switches/flags (we usually just start it "plain", aka $> appium).
Then run the tests with iOS-scope à la $> npx wdio wdio-ios.conf.js
Android
First, make sure all prerequisites mentioned in http://appium.io/docs/en/drivers/android-uiautomator2/ for UiAutomator2-based testing are installed and fullfilled.
Create an Android-specific config file (e.g. wdi5-android.conf.js).
In there, require the shared config file and set platform-specific options:
const path = require('path');
let config = require('./wdio-shared.conf').config;
require('dotenv').config();
// This defines which kind of device we want to test on, as well as how it should be
// configured.
config.capabilities = [
{
automationName: 'UiAutomator2',
platformName: 'Android',
// The version of the Android system
platformVersion: '11',
// For Android, Appium uses the first device it finds using "adb devices". So, this string simply needs to be non-empty.
deviceName: 'any',
chromeOptions: {w3c: false},
// Where to find the .apk or .ipa file to install on the device. The exact location
// of the file may change depending on your Cordova version.
app: path.join(
'test',
'ui5-app',
'app',
'platforms',
'android',
'app',
'build',
'outputs',
'apk',
'debug',
'app-debug.apk'
),
// By default, Appium runs tests in the native context. By setting autoWebview to
// true, it runs our tests in the Cordova context.
autoWebview: true,
// When set to true, it will not show permission dialogs, but instead grant all
// permissions automatically.
autoGrantPermissions: true,
isHeadless: false,
// name this to the AVD emulator of your liking
avd: 'Pixel_XL_API_30'
}
];
config.wdi5.platform = 'android';
exports.config = config;Start appium with your desired switches/flags (peak at our /test/wdio-android.conf.js).
Then run the tests with Android-scope à la $> npx wdio wdio-android.conf.js
Electron
First and foremost: make sure you’re using the version of chromedriver matching the one your electron app is built with.
As with iOS and Android with electron-specific settings, e.g. in wdio-electron.conf.js - note that for the electron-scope, we’re not reusing the shared config file:
const path = require('path');
const WDI5Service = require('wdi5/lib/service/wdi5.service'); // bridge to browser-scope
// https://github.com/electron-userland/spectron/issues/74
exports.config = {
path: '/', // Path to chromedriver endpoint.
host: 'localhost', // localhost == chromedriver
port: 9515, // default chromedriver port
services: [[WDI5Service]],
chromeDriverLogs: path.join('test', 'report', 'logs'),
maxInstances: 1, // multi-instance doesn't work (yet :) )
reporters: ['spec'],
outputDir: path.join('test', 'report', 'logs'),
coloredLogs: true,
framework: 'mocha',
mochaOpts: {
timeout: 60000
},
capabilities: [
{
isHeadless: false,
browserName: 'chrome',
'goog:chromeOptions': {
w3c: false,
binary: path.join(
process.cwd(), // this is important
'test',
'ui5-app',
'app',
'platforms',
'electron',
'build',
'mac',
'UI5.app',
'Contents',
'MacOS',
'UI5'
),
args: ['remote-debugging-port=9222', 'window-size=1440,800']
}
}
],
wdi5: {
deviceType: 'web', // yep, not "native"
screenshotPath: path.join('test', 'report', 'screenshots'),
logLevel: 'verbose',
platform: 'electron',
plugins: {
'phonegap-plugin-barcodescanner': {
respObjElectron: {
text: '123-123-asd',
format: 'EAN',
cancelled: ''
},
scanCode: '123-123-asd',
format: 'EAN'
}
}
}
};To run the tests,
- start your electron’s matching
chromedriver(e.g. via$> npx chromedriver@85) - use the Webdriver.IO-CLI for test execution:
$> npx wdio wdio-electron.conf.js
Usage
Run-(Test-)Time usage of wdi5 is agnostic to its' test-scope (browser or native) and centers around the global browser-object, be it in the browser or on a real mobile device.
Test runs are always started via the regular webdriver.io-cli:
$> npx wdioPlease see the top-level README for API-methods and usage instructions.
Features specific to wdi5 (vs. wdio-ui5-service)
Cordova plugins
This framework comes with a set of plugin mocks.
List of provided plugin mocks:
- phonegap-plugin-barcodescanner
To add a new cordova plugin mock, specify a plugins object in the wdi5 object of the config file. Name it exactly as the cordova plugin is named (e.g. "phonegap-plugin-barcodescanner") and use the path property to point to your mock implementation file.
Additionally, you can define custom properties for programmatic "responses" during test execution (here: mockedPluginResponse).
plugins: {
'phonegap-plugin-barcodescanner': {
path: "./to/mock/implementation.js",
mockedPluginResponse: {
text: '123123',
format: 'EAN',
cancelled: ''
}
},
'other-cordova-plugin': {
path: "./other/mock/implementation/path.js"
}
}FAQ/hints
- performance: integration/e2e-tests are rarely fast.
wdi5tags along that line, remote-controlling a browser with code and all -> watch your timeouts and refer to thewdio-documentation on how to tweak them - Android: make sure you have the environment variable
JAVA_HOMEset in both the shell you’re running Appium and in the shell you’re running the test(s) in. - Electron: a known pitfall is the chromedriver version. Make sure you run the matching
electron-chromedriverversion to the electron version used to build the binary. Webdriver.IO's watch mode is running, but subsequentcontext.executeAsync()-calls fail - exact cause unknown, likely candidate isfibersfrom@wdio/sync- In case
... bind() returned an error, errno=0: Address already in use (48)error shows up during test execution anychromedriverservice is already running. You need to quit this process eg. by force quiting it in the activity monitor.
License
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago