appium-espresso-driver 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/commands/general.js +9 -15
- package/build/lib/driver.js +80 -46
- package/build/lib/espresso-runner.js +41 -66
- package/build/lib/server-builder.js +12 -21
- package/espresso-server/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk +0 -0
- package/espresso-server/app/build.gradle.kts +12 -10
- package/espresso-server/build.gradle.kts +9 -8
- package/lib/commands/general.js +6 -9
- package/lib/driver.js +96 -36
- package/lib/espresso-runner.js +40 -39
- package/lib/server-builder.js +12 -13
- package/npm-shrinkwrap.json +1221 -1533
- package/package.json +2 -2
|
@@ -84,6 +84,9 @@ android {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
val kotlinVersion = rootProject.extra["appiumKotlin"]
|
|
88
|
+
val composeVersion = getStringProperty("appiumComposeVersion", Version.compose)
|
|
89
|
+
|
|
87
90
|
dependencies {
|
|
88
91
|
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
|
89
92
|
// additionalAppDependencies placeholder (don't change or delete this line)
|
|
@@ -105,11 +108,11 @@ dependencies {
|
|
|
105
108
|
testImplementation("org.mockito:mockito-core:${Version.mockito}")
|
|
106
109
|
testImplementation("org.nanohttpd:nanohttpd-webserver:${Version.nanohttpd}")
|
|
107
110
|
testImplementation("org.robolectric:robolectric:${Version.robolectric}")
|
|
108
|
-
testImplementation("org.jetbrains.kotlin:kotlin-test:${
|
|
109
|
-
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$
|
|
110
|
-
testImplementation("org.jetbrains.kotlin:kotlin-reflect:${
|
|
111
|
-
testImplementation("androidx.compose.ui:ui-test:${
|
|
112
|
-
testImplementation("androidx.compose.ui:ui-test-junit4:${
|
|
111
|
+
testImplementation("org.jetbrains.kotlin:kotlin-test:${kotlinVersion}")
|
|
112
|
+
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion")
|
|
113
|
+
testImplementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
|
114
|
+
testImplementation("androidx.compose.ui:ui-test:${composeVersion}")
|
|
115
|
+
testImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}")
|
|
113
116
|
|
|
114
117
|
androidTestImplementation("androidx.annotation:annotation:${Version.annotation}")
|
|
115
118
|
androidTestImplementation("androidx.test.espresso:espresso-contrib:${Version.espresso}") {
|
|
@@ -124,10 +127,10 @@ dependencies {
|
|
|
124
127
|
androidTestImplementation("androidx.test:rules:${Version.testlib}")
|
|
125
128
|
androidTestImplementation("com.google.code.gson:gson:${Version.gson}")
|
|
126
129
|
androidTestImplementation("org.nanohttpd:nanohttpd-webserver:${Version.nanohttpd}")
|
|
127
|
-
androidTestImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${
|
|
128
|
-
androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:${
|
|
129
|
-
androidTestImplementation("androidx.compose.ui:ui-test:${
|
|
130
|
-
androidTestImplementation("androidx.compose.ui:ui-test-junit4:${
|
|
130
|
+
androidTestImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
|
|
131
|
+
androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
|
132
|
+
androidTestImplementation("androidx.compose.ui:ui-test:${composeVersion}")
|
|
133
|
+
androidTestImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}"){
|
|
131
134
|
isTransitive = false
|
|
132
135
|
}
|
|
133
136
|
|
|
@@ -139,7 +142,6 @@ tasks.withType<Test> {
|
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
object Version {
|
|
142
|
-
const val kotlin = "1.5.10"
|
|
143
145
|
const val espresso = "3.4.0"
|
|
144
146
|
const val testlib = "1.4.0"
|
|
145
147
|
const val mocklib = "2.0.9"
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
2
2
|
|
|
3
3
|
buildscript {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
extra.apply {
|
|
5
|
+
set("appiumKotlin", properties.getOrDefault("appiumKotlin", "1.5.10"))
|
|
6
|
+
set(
|
|
7
|
+
"appiumAndroidGradlePlugin",
|
|
8
|
+
properties.getOrDefault("appiumAndroidGradlePlugin", "7.0.3")
|
|
9
|
+
)
|
|
10
|
+
}
|
|
10
11
|
|
|
11
12
|
repositories {
|
|
12
13
|
google()
|
|
13
14
|
mavenCentral()
|
|
14
15
|
}
|
|
15
16
|
dependencies {
|
|
16
|
-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$appiumKotlin")
|
|
17
|
-
classpath("com.android.tools.build:gradle:$appiumAndroidGradlePlugin")
|
|
17
|
+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["appiumKotlin"]}")
|
|
18
|
+
classpath("com.android.tools.build:gradle:${rootProject.extra["appiumAndroidGradlePlugin"]}")
|
|
18
19
|
|
|
19
20
|
// NOTE: Do not place your application dependencies here; they belong
|
|
20
21
|
// in the individual module build.gradle.kts files
|
package/lib/commands/general.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import { util } from '@appium/support';
|
|
3
|
-
import logger from '../logger';
|
|
4
3
|
import validate from 'validate.js';
|
|
5
4
|
import { errors } from '@appium/base-driver';
|
|
6
5
|
import { qualifyActivityName } from '../utils';
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
const commands = {}, helpers = {}, extensions = {};
|
|
9
8
|
|
|
10
9
|
function assertRequiredOptions (options, requiredOptionNames) {
|
|
11
10
|
if (!_.isArray(requiredOptionNames)) {
|
|
@@ -62,7 +61,7 @@ commands.mobileGetDeviceInfo = async function mobileGetDeviceInfo () {
|
|
|
62
61
|
commands.mobileIsToastVisible = async function mobileIsToastVisible (opts = {}) {
|
|
63
62
|
const {text, isRegexp} = opts;
|
|
64
63
|
if (!util.hasValue(text)) {
|
|
65
|
-
|
|
64
|
+
throw new errors.InvalidArgumentError(`'text' argument is mandatory`);
|
|
66
65
|
}
|
|
67
66
|
return await this.espresso.jwproxy.command('/appium/execute_mobile/is_toast_displayed', 'POST', {
|
|
68
67
|
text,
|
|
@@ -110,8 +109,7 @@ commands.mobileNavigateTo = async function mobileNavigateTo (opts = {}) {
|
|
|
110
109
|
|
|
111
110
|
let menuItemIdAsNumber = parseInt(menuItemId, 10);
|
|
112
111
|
if (_.isNaN(menuItemIdAsNumber) || menuItemIdAsNumber < 0) {
|
|
113
|
-
|
|
114
|
-
menuItemId = menuItemIdAsNumber;
|
|
112
|
+
throw new errors.InvalidArgumentError(`'menuItemId' must be a non-negative number. Found ${menuItemId}`);
|
|
115
113
|
}
|
|
116
114
|
|
|
117
115
|
return await this.espresso.jwproxy.command(`/appium/execute_mobile/${util.unwrapElement(element)}/navigate_to`, 'POST', {
|
|
@@ -163,15 +161,14 @@ commands.mobileScrollToPage = async function mobileScrollToPage (opts = {}) {
|
|
|
163
161
|
},
|
|
164
162
|
},
|
|
165
163
|
});
|
|
166
|
-
|
|
167
164
|
if (util.hasValue(res)) {
|
|
168
|
-
|
|
165
|
+
throw new errors.InvalidArgumentError(`Invalid scrollTo parameters: ${JSON.stringify(res)}`);
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
const {element, scrollTo, scrollToPage, smoothScroll} = opts;
|
|
172
169
|
|
|
173
170
|
if (util.hasValue(scrollTo) && util.hasValue(scrollToPage)) {
|
|
174
|
-
|
|
171
|
+
this.log.warn(`'scrollTo' and 'scrollToPage' where both provided. Defaulting to 'scrollTo'`);
|
|
175
172
|
}
|
|
176
173
|
|
|
177
174
|
return await this.espresso.jwproxy.command(`/appium/execute_mobile/${util.unwrapElement(element)}/scroll_to_page`, 'POST', {
|
|
@@ -307,7 +304,7 @@ commands.startActivity = async function startActivity (appPackage, appActivity,
|
|
|
307
304
|
appWaitPackage = appWaitPackage || appPackage;
|
|
308
305
|
appActivity = qualifyActivityName(appActivity, appPackage);
|
|
309
306
|
appWaitActivity = qualifyActivityName(appWaitActivity || appActivity, appWaitPackage);
|
|
310
|
-
|
|
307
|
+
this.log.debug(`Starting activity '${appActivity}' for package '${appPackage}'`);
|
|
311
308
|
await this.espresso.jwproxy.command(`/appium/device/start_activity`, 'POST', {
|
|
312
309
|
appPackage,
|
|
313
310
|
appActivity,
|
package/lib/driver.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
import { BaseDriver, errors, isErrorType, DeviceSettings} from '@appium/base-driver';
|
|
3
4
|
import { EspressoRunner, TEST_APK_PKG } from './espresso-runner';
|
|
4
|
-
import { fs } from '@appium/support';
|
|
5
|
-
import logger from './logger';
|
|
5
|
+
import { fs, tempDir, zip } from '@appium/support';
|
|
6
6
|
import commands from './commands';
|
|
7
7
|
import { DEFAULT_ADB_PORT } from 'appium-adb';
|
|
8
8
|
import { androidHelpers, androidCommands, SETTINGS_HELPER_PKG_ID } from 'appium-android-driver';
|
|
@@ -120,6 +120,10 @@ const CHROME_NO_PROXY = [
|
|
|
120
120
|
];
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
const APK_EXT = '.apk';
|
|
124
|
+
const AAB_EXT = '.aab';
|
|
125
|
+
const SUPPORTED_EXTENSIONS = [APK_EXT, AAB_EXT];
|
|
126
|
+
|
|
123
127
|
class EspressoDriver extends BaseDriver {
|
|
124
128
|
constructor (opts = {}, shouldValidateCaps = true) {
|
|
125
129
|
// `shell` overwrites adb.shell, so remove
|
|
@@ -175,11 +179,11 @@ class EspressoDriver extends BaseDriver {
|
|
|
175
179
|
|
|
176
180
|
if (this.isChromeSession) {
|
|
177
181
|
if (this.opts.app) {
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
this.log.warn(`'browserName' capability will be ignored`);
|
|
183
|
+
this.log.warn(`Chrome browser cannot be run in Espresso sessions because Espresso automation doesn't ` +
|
|
180
184
|
`have permission to access Chrome`);
|
|
181
185
|
} else {
|
|
182
|
-
|
|
186
|
+
this.log.errorAndThrow(`Chrome browser sessions cannot be run in Espresso because Espresso ` +
|
|
183
187
|
`automation doesn't have permission to access Chrome`);
|
|
184
188
|
}
|
|
185
189
|
}
|
|
@@ -204,15 +208,15 @@ class EspressoDriver extends BaseDriver {
|
|
|
204
208
|
// find and copy, or download and unzip an app url or path
|
|
205
209
|
this.opts.app = await this.helpers.configureApp(this.opts.app, {
|
|
206
210
|
onPostProcess: this.onPostConfigureApp.bind(this),
|
|
207
|
-
supportedExtensions:
|
|
211
|
+
supportedExtensions: SUPPORTED_EXTENSIONS
|
|
208
212
|
});
|
|
209
213
|
} else if (this.appOnDevice) {
|
|
210
214
|
// the app isn't an actual app file but rather something we want to
|
|
211
215
|
// assume is on the device and just launch via the appPackage
|
|
212
|
-
|
|
216
|
+
this.log.info(`App file was not listed, instead we're going to run ` +
|
|
213
217
|
`${this.opts.appPackage} directly on the device`);
|
|
214
218
|
if (!await this.adb.isAppInstalled(this.opts.appPackage)) {
|
|
215
|
-
|
|
219
|
+
this.log.errorAndThrow(`Could not find the package '${this.opts.appPackage}' ` +
|
|
216
220
|
`installed on the device`);
|
|
217
221
|
}
|
|
218
222
|
}
|
|
@@ -233,10 +237,40 @@ class EspressoDriver extends BaseDriver {
|
|
|
233
237
|
}
|
|
234
238
|
}
|
|
235
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Unzip the given app path and return the first package that has SUPPORTED_EXTENSIONS
|
|
242
|
+
* in the archived file.
|
|
243
|
+
*
|
|
244
|
+
* @param {string} appPath The path to app file.
|
|
245
|
+
* @returns {string} Retuns the path to an unzipped app file path.
|
|
246
|
+
* @throws Raise an exception if the zip did not have any SUPPORTED_EXTENSIONS packages.
|
|
247
|
+
*/
|
|
248
|
+
async unzipApp (appPath) {
|
|
249
|
+
const useSystemUnzipEnv = process.env.APPIUM_PREFER_SYSTEM_UNZIP;
|
|
250
|
+
const useSystemUnzip = _.isEmpty(useSystemUnzipEnv)
|
|
251
|
+
|| !['0', 'false'].includes(_.toLower(useSystemUnzipEnv));
|
|
252
|
+
const tmpRoot = await tempDir.openDir();
|
|
253
|
+
await zip.extractAllTo(appPath, tmpRoot, {useSystemUnzip});
|
|
254
|
+
|
|
255
|
+
const globPattern = `**/*.+(${SUPPORTED_EXTENSIONS.map((ext) => ext.replace(/^\./, '')).join('|')})`;
|
|
256
|
+
const sortedBundleItems = (await fs.glob(globPattern, {
|
|
257
|
+
cwd: tmpRoot,
|
|
258
|
+
strict: false,
|
|
259
|
+
})).sort((a, b) => a.split(path.sep).length - b.split(path.sep).length);
|
|
260
|
+
if (sortedBundleItems.length === 0) {
|
|
261
|
+
// no expected packages in the zip
|
|
262
|
+
this.log.errorAndThrow(`${this.opts.app} did not have any of '${SUPPORTED_EXTENSIONS.join(', ')}' ` +
|
|
263
|
+
`extension packages. Please make sure the provided .zip archive contains at least one valid application package.`);
|
|
264
|
+
}
|
|
265
|
+
const unzippedAppPath = path.join(tmpRoot, _.first(sortedBundleItems));
|
|
266
|
+
this.log.debug(`'${unzippedAppPath}' is the unzipped file from '${appPath}'`);
|
|
267
|
+
return unzippedAppPath;
|
|
268
|
+
}
|
|
269
|
+
|
|
236
270
|
async onPostConfigureApp ({cachedAppInfo, isUrl, appPath}) {
|
|
237
271
|
const presignApp = async (appLocation) => {
|
|
238
272
|
if (this.opts.noSign) {
|
|
239
|
-
|
|
273
|
+
this.log.info('Skipping application signing because noSign capability is set to true. ' +
|
|
240
274
|
'Having the application under test with improper signature/non-signed will cause ' +
|
|
241
275
|
'Espresso automation startup failure.');
|
|
242
276
|
} else if (!await this.adb.checkApkCert(appLocation, this.opts.appPackage)) {
|
|
@@ -244,25 +278,51 @@ class EspressoDriver extends BaseDriver {
|
|
|
244
278
|
}
|
|
245
279
|
};
|
|
246
280
|
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
const
|
|
281
|
+
const hasApkExt = (appPath) => _.endsWith(_.toLower(appPath), APK_EXT);
|
|
282
|
+
const hasAabExt = (appPath) => _.endsWith(_.toLower(appPath), AAB_EXT);
|
|
283
|
+
const extractUniversalApk = async (shouldExtract, appPath) =>
|
|
284
|
+
shouldExtract ? appPath : await this.adb.extractUniversalApk(appPath);
|
|
285
|
+
|
|
250
286
|
let pathInCache = null;
|
|
251
287
|
let isResultAppPathAlreadyCached = false;
|
|
252
288
|
if (_.isPlainObject(cachedAppInfo)) {
|
|
253
289
|
const packageHash = await fs.hash(appPath);
|
|
254
290
|
if (packageHash === cachedAppInfo.packageHash && await fs.exists(cachedAppInfo.fullPath)) {
|
|
291
|
+
this.log.info(`Using '${cachedAppInfo.fullPath}' which is cached from '${appPath}'`);
|
|
255
292
|
isResultAppPathAlreadyCached = true;
|
|
256
293
|
pathInCache = cachedAppInfo.fullPath;
|
|
257
294
|
}
|
|
258
295
|
}
|
|
296
|
+
|
|
297
|
+
// appPath can be .zip, .apk or .aab
|
|
298
|
+
const isApk = hasApkExt(appPath);
|
|
299
|
+
// Only local .apk files that are available in-place should not be cached
|
|
300
|
+
const shouldResultAppPathBeCached = !isApk || (isApk && isUrl);
|
|
301
|
+
|
|
259
302
|
if (!isResultAppPathAlreadyCached) {
|
|
260
303
|
if (shouldResultAppPathBeCached) {
|
|
261
|
-
|
|
304
|
+
// .zip, .aab or downloaded .apk
|
|
305
|
+
|
|
306
|
+
let unzippedAppPath;
|
|
307
|
+
let isUnzippedApk = false;
|
|
308
|
+
if (!(hasApkExt(appPath) || hasAabExt(appPath))) {
|
|
309
|
+
unzippedAppPath = await this.unzipApp(appPath);
|
|
310
|
+
isUnzippedApk = hasApkExt(unzippedAppPath);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// unzippedAppPath or appPath has SUPPORTED_EXTENSIONS.
|
|
314
|
+
pathInCache = unzippedAppPath
|
|
315
|
+
? await extractUniversalApk(isUnzippedApk, unzippedAppPath)
|
|
316
|
+
: await extractUniversalApk(isApk, appPath);
|
|
317
|
+
|
|
262
318
|
if (!isApk && isUrl) {
|
|
263
|
-
// Clean up the temporarily downloaded .aab package
|
|
319
|
+
// Clean up the temporarily downloaded .aab or .zip package
|
|
264
320
|
await fs.rimraf(appPath);
|
|
265
321
|
}
|
|
322
|
+
if (hasAabExt(unzippedAppPath)) {
|
|
323
|
+
// Cleanup the local unzipped .aab file
|
|
324
|
+
await fs.rimraf(unzippedAppPath);
|
|
325
|
+
}
|
|
266
326
|
await presignApp(pathInCache);
|
|
267
327
|
} else if (isApk) {
|
|
268
328
|
// It is probably not the best idea to modify the provided app in-place,
|
|
@@ -285,13 +345,13 @@ class EspressoDriver extends BaseDriver {
|
|
|
285
345
|
// TODO this method is duplicated from uiautomator2-driver; consolidate
|
|
286
346
|
setAvdFromCapabilities (caps) {
|
|
287
347
|
if (this.opts.avd) {
|
|
288
|
-
|
|
348
|
+
this.log.info('avd name defined, ignoring device name and platform version');
|
|
289
349
|
} else {
|
|
290
350
|
if (!caps.deviceName) {
|
|
291
|
-
|
|
351
|
+
this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
|
|
292
352
|
}
|
|
293
353
|
if (!caps.platformVersion) {
|
|
294
|
-
|
|
354
|
+
this.log.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
|
|
295
355
|
}
|
|
296
356
|
let avdDevice = caps.deviceName.replace(/[^a-zA-Z0-9_.]/g, '-');
|
|
297
357
|
this.opts.avd = `${avdDevice}__${caps.platformVersion}`;
|
|
@@ -309,11 +369,11 @@ class EspressoDriver extends BaseDriver {
|
|
|
309
369
|
|
|
310
370
|
// TODO much of this logic is duplicated from uiautomator2
|
|
311
371
|
async startEspressoSession () {
|
|
312
|
-
|
|
372
|
+
this.log.info(`EspressoDriver version: ${version}`);
|
|
313
373
|
|
|
314
374
|
// Read https://github.com/appium/appium-android-driver/pull/461 what happens if ther is no setHiddenApiPolicy for Android P+
|
|
315
375
|
if (await this.adb.getApiLevel() >= 28) { // Android P
|
|
316
|
-
|
|
376
|
+
this.log.warn('Relaxing hidden api policy');
|
|
317
377
|
await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
|
|
318
378
|
}
|
|
319
379
|
|
|
@@ -335,7 +395,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
335
395
|
await this.adb.setAnimationState(false);
|
|
336
396
|
this.wasAnimationEnabled = true;
|
|
337
397
|
} catch (err) {
|
|
338
|
-
|
|
398
|
+
this.log.warn(`Unable to turn off animations: ${err.message}`);
|
|
339
399
|
}
|
|
340
400
|
}
|
|
341
401
|
|
|
@@ -346,14 +406,14 @@ class EspressoDriver extends BaseDriver {
|
|
|
346
406
|
// set up the modified espresso server etc
|
|
347
407
|
this.initEspressoServer();
|
|
348
408
|
// Further prepare the device by forwarding the espresso port
|
|
349
|
-
|
|
409
|
+
this.log.debug(`Forwarding Espresso Server port ${DEVICE_PORT} to ${this.opts.systemPort}`);
|
|
350
410
|
await this.adb.forwardPort(this.opts.systemPort, DEVICE_PORT);
|
|
351
411
|
|
|
352
412
|
if (!this.opts.skipUnlock) {
|
|
353
413
|
// unlock the device to prepare it for testing
|
|
354
414
|
await helpers.unlock(this, this.adb, this.caps);
|
|
355
415
|
} else {
|
|
356
|
-
|
|
416
|
+
this.log.debug(`'skipUnlock' capability set, so skipping device unlock`);
|
|
357
417
|
}
|
|
358
418
|
|
|
359
419
|
// set up app under test
|
|
@@ -382,7 +442,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
382
442
|
// launch espresso and wait till its online and we have a session
|
|
383
443
|
await this.espresso.startSession(this.caps);
|
|
384
444
|
if (this.caps.autoLaunch === false) {
|
|
385
|
-
|
|
445
|
+
this.log.info(`Not waiting for the application activity to start because 'autoLaunch' is disabled`);
|
|
386
446
|
} else {
|
|
387
447
|
await this.adb.waitForActivity(this.caps.appWaitPackage, this.caps.appWaitActivity, this.opts.appWaitDuration);
|
|
388
448
|
}
|
|
@@ -402,7 +462,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
402
462
|
async initWebview () {
|
|
403
463
|
const viewName = androidCommands.defaultWebviewName.call(this);
|
|
404
464
|
const timeout = this.opts.autoWebviewTimeout || 2000;
|
|
405
|
-
|
|
465
|
+
this.log.info(`Setting webview to context '${viewName}' with timeout ${timeout}ms`);
|
|
406
466
|
await retryInterval(timeout / 500, 500, this.setContext.bind(this), viewName);
|
|
407
467
|
}
|
|
408
468
|
|
|
@@ -426,7 +486,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
426
486
|
initEspressoServer () {
|
|
427
487
|
// now that we have package and activity, we can create an instance of
|
|
428
488
|
// espresso with the appropriate data
|
|
429
|
-
this.espresso = new EspressoRunner({
|
|
489
|
+
this.espresso = new EspressoRunner(this.log, {
|
|
430
490
|
host: this.opts.remoteAdbHost || this.opts.host || '127.0.0.1',
|
|
431
491
|
systemPort: this.opts.systemPort,
|
|
432
492
|
devicePort: DEVICE_PORT,
|
|
@@ -471,9 +531,9 @@ class EspressoDriver extends BaseDriver {
|
|
|
471
531
|
|
|
472
532
|
if (!this.opts.app) {
|
|
473
533
|
if (this.opts.fullReset) {
|
|
474
|
-
|
|
534
|
+
this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
|
|
475
535
|
}
|
|
476
|
-
|
|
536
|
+
this.log.debug('No app capability. Assuming it is already on the device');
|
|
477
537
|
if (this.opts.fastReset) {
|
|
478
538
|
await helpers.resetApp(this.adb, this.opts);
|
|
479
539
|
}
|
|
@@ -486,20 +546,20 @@ class EspressoDriver extends BaseDriver {
|
|
|
486
546
|
await helpers.installApk(this.adb, this.opts);
|
|
487
547
|
}
|
|
488
548
|
if (this.opts.skipServerInstallation) {
|
|
489
|
-
|
|
549
|
+
this.log.debug('skipServerInstallation capability is set. Not installig espresso-server ');
|
|
490
550
|
} else {
|
|
491
551
|
await this.espresso.installTestApk();
|
|
492
552
|
try {
|
|
493
553
|
await this.adb.addToDeviceIdleWhitelist(SETTINGS_HELPER_PKG_ID, TEST_APK_PKG);
|
|
494
554
|
} catch (e) {
|
|
495
|
-
|
|
555
|
+
this.log.warn(`Cannot add server packages to the Doze whitelist. Original error: ` +
|
|
496
556
|
(e.stderr || e.message));
|
|
497
557
|
}
|
|
498
558
|
}
|
|
499
559
|
}
|
|
500
560
|
|
|
501
561
|
async deleteSession () {
|
|
502
|
-
|
|
562
|
+
this.log.debug('Deleting espresso session');
|
|
503
563
|
|
|
504
564
|
try {
|
|
505
565
|
if (!_.isEmpty(this._screenRecordingProperties)) {
|
|
@@ -525,29 +585,29 @@ class EspressoDriver extends BaseDriver {
|
|
|
525
585
|
try {
|
|
526
586
|
await this.adb.setAnimationState(true);
|
|
527
587
|
} catch (err) {
|
|
528
|
-
|
|
588
|
+
this.log.warn(`Unable to reset animation: ${err.message}`);
|
|
529
589
|
}
|
|
530
590
|
}
|
|
531
591
|
if (this.opts.unicodeKeyboard && this.opts.resetKeyboard &&
|
|
532
592
|
this.defaultIME) {
|
|
533
|
-
|
|
593
|
+
this.log.debug(`Resetting IME to '${this.defaultIME}'`);
|
|
534
594
|
await this.adb.setIME(this.defaultIME);
|
|
535
595
|
}
|
|
536
596
|
if (!this.isChromeSession && this.opts.appPackage && !this.opts.dontStopAppOnReset) {
|
|
537
597
|
await this.adb.forceStop(this.opts.appPackage);
|
|
538
598
|
}
|
|
539
599
|
if (this.opts.fullReset && !this.opts.skipUninstall && !this.appOnDevice) {
|
|
540
|
-
|
|
600
|
+
this.log.debug(`FULL_RESET set to 'true', Uninstalling '${this.opts.appPackage}'`);
|
|
541
601
|
await this.adb.uninstallApk(this.opts.appPackage);
|
|
542
602
|
}
|
|
543
603
|
await this.adb.stopLogcat();
|
|
544
604
|
if (this.opts.reboot) {
|
|
545
605
|
let avdName = this.opts.avd.replace('@', '');
|
|
546
|
-
|
|
606
|
+
this.log.debug(`closing emulator '${avdName}'`);
|
|
547
607
|
await this.adb.killEmulator(avdName);
|
|
548
608
|
}
|
|
549
609
|
if (await this.adb.getApiLevel() >= 28) { // Android P
|
|
550
|
-
|
|
610
|
+
this.log.info('Restoring hidden api policy to the device default configuration');
|
|
551
611
|
await this.adb.setDefaultHiddenApiPolicy(!!this.opts.ignoreHiddenApiPolicyError);
|
|
552
612
|
}
|
|
553
613
|
}
|
|
@@ -556,7 +616,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
556
616
|
try {
|
|
557
617
|
await this.adb.removePortForward(this.opts.systemPort);
|
|
558
618
|
} catch (error) {
|
|
559
|
-
|
|
619
|
+
this.log.warn(`Unable to remove port forward '${error.message}'`);
|
|
560
620
|
//Ignore, this block will also be called when we fall in catch block
|
|
561
621
|
// and before even port forward.
|
|
562
622
|
}
|