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.
@@ -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:${Version.kotlin}")
109
- testImplementation("org.jetbrains.kotlin:kotlin-test-junit:${Version.kotlin}")
110
- testImplementation("org.jetbrains.kotlin:kotlin-reflect:${Version.kotlin}")
111
- testImplementation("androidx.compose.ui:ui-test:${Version.compose}")
112
- testImplementation("androidx.compose.ui:ui-test-junit4:${Version.compose}")
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:${Version.kotlin}")
128
- androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:${Version.kotlin}")
129
- androidTestImplementation("androidx.compose.ui:ui-test:${Version.compose}")
130
- androidTestImplementation("androidx.compose.ui:ui-test-junit4:${Version.compose}"){
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
- val appiumKotlin =
6
- properties.getOrDefault("appiumKotlin", "1.5.10")
7
-
8
- val appiumAndroidGradlePlugin =
9
- properties.getOrDefault("appiumAndroidGradlePlugin", "7.0.3")
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
@@ -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
- let commands = {}, helpers = {}, extensions = {};
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
- logger.errorAndThrow(`'text' argument is mandatory`);
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
- logger.errorAndThrow(`'menuItemId' must be a non-negative number. Found ${menuItemId}`);
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
- logger.errorAndThrow(`Invalid scrollTo parameters: ${JSON.stringify(res)}`);
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
- logger.warn(`'scrollTo' and 'scrollToPage' where both provided. Defaulting to 'scrollTo'`);
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
- logger.debug(`Starting activity '${appActivity}' for package '${appPackage}'`);
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
- logger.warn(`'browserName' capability will be ignored`);
179
- logger.warn(`Chrome browser cannot be run in Espresso sessions because Espresso automation doesn't ` +
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
- logger.errorAndThrow(`Chrome browser sessions cannot be run in Espresso because Espresso ` +
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: ['.apk', '.aab']
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
- logger.info(`App file was not listed, instead we're going to run ` +
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
- logger.errorAndThrow(`Could not find the package '${this.opts.appPackage}' ` +
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
- logger.info('Skipping application signing because noSign capability is set to true. ' +
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 isApk = _.endsWith(_.toLower(appPath), '.apk');
248
- // Do not cache .apk if was already present on the local file system
249
- const shouldResultAppPathBeCached = !isApk || (isApk && isUrl);
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
- pathInCache = isApk ? appPath : await this.adb.extractUniversalApk(appPath);
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
- logger.info('avd name defined, ignoring device name and platform version');
348
+ this.log.info('avd name defined, ignoring device name and platform version');
289
349
  } else {
290
350
  if (!caps.deviceName) {
291
- logger.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
351
+ this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
292
352
  }
293
353
  if (!caps.platformVersion) {
294
- logger.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
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
- logger.info(`EspressoDriver version: ${version}`);
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
- logger.warn('Relaxing hidden api policy');
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
- logger.warn(`Unable to turn off animations: ${err.message}`);
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
- logger.debug(`Forwarding Espresso Server port ${DEVICE_PORT} to ${this.opts.systemPort}`);
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
- logger.debug(`'skipUnlock' capability set, so skipping device unlock`);
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
- logger.info(`Not waiting for the application activity to start because 'autoLaunch' is disabled`);
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
- logger.info(`Setting webview to context '${viewName}' with timeout ${timeout}ms`);
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
- logger.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
534
+ this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
475
535
  }
476
- logger.debug('No app capability. Assuming it is already on the device');
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
- logger.debug('skipServerInstallation capability is set. Not installig espresso-server ');
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
- logger.warn(`Cannot add server packages to the Doze whitelist. Original error: ` +
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
- logger.debug('Deleting espresso session');
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
- logger.warn(`Unable to reset animation: ${err.message}`);
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
- logger.debug(`Resetting IME to '${this.defaultIME}'`);
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
- logger.debug(`FULL_RESET set to 'true', Uninstalling '${this.opts.appPackage}'`);
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
- logger.debug(`closing emulator '${avdName}'`);
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
- logger.info('Restoring hidden api policy to the device default configuration');
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
- logger.warn(`Unable to remove port forward '${error.message}'`);
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
  }