appium-espresso-driver 2.2.0 → 2.2.3
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/README.md +3 -2
- package/build/index.js +1 -1
- package/build/lib/commands/execute.js +1 -1
- package/build/lib/commands/general.js +9 -15
- package/build/lib/commands/idling-resources.js +1 -1
- package/build/lib/commands/index.js +1 -1
- package/build/lib/commands/services.js +1 -1
- package/build/lib/desired-caps.js +1 -1
- package/build/lib/driver.js +32 -47
- package/build/lib/espresso-runner.js +41 -66
- package/build/lib/logger.js +1 -1
- package/build/lib/server-builder.js +11 -20
- package/build/lib/server.js +1 -1
- package/build/lib/utils.js +1 -1
- package/espresso-server/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk +0 -0
- package/lib/commands/general.js +6 -9
- package/lib/driver.js +31 -32
- package/lib/espresso-runner.js +40 -39
- package/lib/server-builder.js +10 -12
- package/npm-shrinkwrap.json +1842 -1614
- package/package.json +3 -3
package/build/lib/server.js
CHANGED
|
@@ -36,4 +36,4 @@ var _default = startServer;
|
|
|
36
36
|
exports.default = _default;require('source-map-support').install();
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
//# sourceMappingURL=data:application/json;charset=utf8;base64,
|
|
39
|
+
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliL3NlcnZlci5qcyIsIm5hbWVzIjpbInN0YXJ0U2VydmVyIiwicG9ydCIsImhvc3QiLCJkIiwiRXNwcmVzc29Ecml2ZXIiLCJzZXJ2ZXIiLCJyb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb24iLCJob3N0bmFtZSIsImxvZyIsImluZm8iXSwic291cmNlUm9vdCI6Ii4uLy4uIiwic291cmNlcyI6WyJsaWIvc2VydmVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHsgc2VydmVyIGFzIGJhc2VTZXJ2ZXIsIHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbiB9IGZyb20gJ0BhcHBpdW0vYmFzZS1kcml2ZXInO1xuaW1wb3J0IEVzcHJlc3NvRHJpdmVyIGZyb20gJy4vZHJpdmVyJztcblxuXG5hc3luYyBmdW5jdGlvbiBzdGFydFNlcnZlciAocG9ydCwgaG9zdCkge1xuICBjb25zdCBkID0gbmV3IEVzcHJlc3NvRHJpdmVyKHtwb3J0LCBob3N0fSk7XG4gIGNvbnN0IHNlcnZlciA9IGJhc2VTZXJ2ZXIoe1xuICAgIHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbjogcm91dGVDb25maWd1cmluZ0Z1bmN0aW9uKGQpLFxuICAgIHBvcnQsXG4gICAgaG9zdG5hbWU6IGhvc3QsXG4gIH0pO1xuICBsb2cuaW5mbyhgQW5kcm9pZCBFc3ByZXNzbyBEcml2ZXIgbGlzdGVuaW5nIG9uIGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH1gKTtcbiAgcmV0dXJuIGF3YWl0IHNlcnZlcjtcbn1cblxuZXhwb3J0IHsgc3RhcnRTZXJ2ZXIgfTtcbmV4cG9ydCBkZWZhdWx0IHN0YXJ0U2VydmVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFHQSxlQUFlQSxXQUFmLENBQTRCQyxJQUE1QixFQUFrQ0MsSUFBbEMsRUFBd0M7RUFDdEMsTUFBTUMsQ0FBQyxHQUFHLElBQUlDLGVBQUosQ0FBbUI7SUFBQ0gsSUFBRDtJQUFPQztFQUFQLENBQW5CLENBQVY7RUFDQSxNQUFNRyxNQUFNLEdBQUcsd0JBQVc7SUFDeEJDLHdCQUF3QixFQUFFLDBDQUF5QkgsQ0FBekIsQ0FERjtJQUV4QkYsSUFGd0I7SUFHeEJNLFFBQVEsRUFBRUw7RUFIYyxDQUFYLENBQWY7O0VBS0FNLGdCQUFJQyxJQUFKLENBQVUsK0NBQThDUCxJQUFLLElBQUdELElBQUssRUFBckU7O0VBQ0EsT0FBTyxNQUFNSSxNQUFiO0FBQ0Q7O2VBR2NMLFcifQ==
|
package/build/lib/utils.js
CHANGED
|
@@ -82,4 +82,4 @@ function updateDependencyLines(originalContent, dependencyPlaceholder, dependenc
|
|
|
82
82
|
}require('source-map-support').install();
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
//# sourceMappingURL=data:application/json;charset=utf8;base64,
|
|
85
|
+
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliL3V0aWxzLmpzIiwibmFtZXMiOlsicXVhbGlmeUFjdGl2aXR5TmFtZSIsImFjdGl2aXR5TmFtZSIsInBhY2thZ2VOYW1lIiwic29tZSIsIm5hbWUiLCJfIiwiaW5jbHVkZXMiLCJkb3RQb3MiLCJpbmRleE9mIiwiY29weUdyYWRsZVByb2plY3RSZWN1cnNpdmVseSIsInNvdXJjZUJhc2VEaXIiLCJ0YXJnZXRCYXNlRGlyIiwiZnMiLCJ3YWxrRGlyIiwiaXRlbVBhdGgiLCJpc0RpcmVjdG9yeSIsInJlbGF0aXZlUGF0aCIsInBhdGgiLCJyZWxhdGl2ZSIsInRhcmdldFBhdGgiLCJyZXNvbHZlIiwiaXNJbkdyYWRsZUJ1aWxkRGlyIiwic2VwIiwiY29weUZpbGUiLCJyZXF1aXJlT3B0aW9ucyIsIm9wdHMiLCJyZXF1aXJlZEtleXMiLCJtaXNzaW5nS2V5cyIsImRpZmZlcmVuY2UiLCJrZXlzIiwiaXNFbXB0eSIsIkVycm9yIiwidXBkYXRlRGVwZW5kZW5jeUxpbmVzIiwib3JpZ2luYWxDb250ZW50IiwiZGVwZW5kZW5jeVBsYWNlaG9sZGVyIiwiZGVwZW5kZW5jeUxpbmVzIiwiY29uZmlndXJhdGlvbkxpbmVzIiwic3BsaXQiLCJzZWFyY2hSZSIsIlJlZ0V4cCIsImVzY2FwZVJlZ0V4cCIsInBsYWNlaG9sZGVySW5kZXgiLCJmaW5kSW5kZXgiLCJsaW5lIiwidGVzdCIsInBsYWNlaG9sZGVyTGluZSIsImluZGVudExlbiIsImxlbmd0aCIsInRyaW1TdGFydCIsInNwbGljZSIsIm1hcCIsInJlcGVhdCIsImpvaW4iXSwic291cmNlUm9vdCI6Ii4uLy4uIiwic291cmNlcyI6WyJsaWIvdXRpbHMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnMsIG1rZGlycCB9IGZyb20gJ0BhcHBpdW0vc3VwcG9ydCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5cbi8qKlxuICogaHR0cHM6Ly9hbmRyb2lkLmdvb2dsZXNvdXJjZS5jb20vcGxhdGZvcm0vZnJhbWV3b3Jrcy9iYXNlLysvbWFzdGVyL3Rvb2xzL2FhcHQvUmVzb3VyY2UuY3BwIzc1NVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpdml0eU5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYWNrYWdlTmFtZVxuICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBhY3Rpdml0eSBuYW1lXG4gKi9cbmZ1bmN0aW9uIHF1YWxpZnlBY3Rpdml0eU5hbWUgKGFjdGl2aXR5TmFtZSwgcGFja2FnZU5hbWUpIHtcbiAgLy8gaWYgZWl0aGVyIGFjdGl2aXR5IG9yIHBhY2thZ2UgbmFtZSBpcyBub3Qgc2V0XG4gIC8vIG9yIGFueSBvZiB0aGVzZSBjb250YWluIHdpbGRjYXJkcyB0aGVuIHRoZXJlIGlzXG4gIC8vIG5vIHBvaW50IGluIHF1YWxpZnlpbmcgdGhlIGFjdGl2aXR5IG5hbWVcbiAgaWYgKFthY3Rpdml0eU5hbWUsIHBhY2thZ2VOYW1lXS5zb21lKChuYW1lKSA9PiAhbmFtZSB8fCBfLmluY2x1ZGVzKG5hbWUsICcqJykpKSB7XG4gICAgcmV0dXJuIGFjdGl2aXR5TmFtZTtcbiAgfVxuXG4gIGNvbnN0IGRvdFBvcyA9IGFjdGl2aXR5TmFtZS5pbmRleE9mKCcuJyk7XG4gIGlmIChkb3RQb3MgPiAwKSB7XG4gICAgcmV0dXJuIGFjdGl2aXR5TmFtZTtcbiAgfVxuICByZXR1cm4gYCR7cGFja2FnZU5hbWV9JHtkb3RQb3MgPT09IDAgPyAnJyA6ICcuJ30ke2FjdGl2aXR5TmFtZX1gO1xufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IGNvcHkgYWxsIGZpbGVzIGV4Y2VwdCBidWlsZCBkaXJlY3RvcmllcyBjb250ZW50c1xuICogQHBhcmFtIHNvdXJjZUJhc2VEaXIge3N0cmluZ30gZGlyZWN0b3J5IHRvIGNvcHkgZmlsZXMgZnJvbVxuICogQHBhcmFtIHRhcmdldEJhc2VEaXIge3N0cmluZ30gZGlyZWN0b3J5IHRvIGNvcHkgZmlsZXMgdG9cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29weUdyYWRsZVByb2plY3RSZWN1cnNpdmVseSAoc291cmNlQmFzZURpciwgdGFyZ2V0QmFzZURpcikge1xuICBhd2FpdCBmcy53YWxrRGlyKHNvdXJjZUJhc2VEaXIsIHRydWUsIGFzeW5jIChpdGVtUGF0aCwgaXNEaXJlY3RvcnkpID0+IHtcbiAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBwYXRoLnJlbGF0aXZlKHNvdXJjZUJhc2VEaXIsIGl0ZW1QYXRoKTtcbiAgICBjb25zdCB0YXJnZXRQYXRoID0gcGF0aC5yZXNvbHZlKHRhcmdldEJhc2VEaXIsIHJlbGF0aXZlUGF0aCk7XG5cbiAgICBjb25zdCBpc0luR3JhZGxlQnVpbGREaXIgPSBgJHtwYXRoLnNlcH0ke2l0ZW1QYXRofWAuaW5jbHVkZXMoYCR7cGF0aC5zZXB9YnVpbGQke3BhdGguc2VwfWApO1xuICAgIGlmIChpc0luR3JhZGxlQnVpbGREaXIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoaXNEaXJlY3RvcnkpIHtcbiAgICAgIGF3YWl0IG1rZGlycCh0YXJnZXRQYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgZnMuY29weUZpbGUoaXRlbVBhdGgsIHRhcmdldFBhdGgpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZXF1aXJlT3B0aW9ucyAob3B0cywgcmVxdWlyZWRLZXlzID0gW10pIHtcbiAgY29uc3QgbWlzc2luZ0tleXMgPSBfLmRpZmZlcmVuY2UocmVxdWlyZWRLZXlzLCBfLmtleXMob3B0cykpO1xuICBpZiAoIV8uaXNFbXB0eShtaXNzaW5nS2V5cykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhcmUgcmVxdWlyZWQ6ICR7bWlzc2luZ0tleXN9YCk7XG4gIH1cbiAgcmV0dXJuIG9wdHM7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZURlcGVuZGVuY3lMaW5lcyAob3JpZ2luYWxDb250ZW50LCBkZXBlbmRlbmN5UGxhY2Vob2xkZXIsIGRlcGVuZGVuY3lMaW5lcykge1xuICBjb25zdCBjb25maWd1cmF0aW9uTGluZXMgPSBvcmlnaW5hbENvbnRlbnQuc3BsaXQoJ1xcbicpO1xuICBjb25zdCBzZWFyY2hSZSA9IG5ldyBSZWdFeHAoYF5cXFxccyovL1xcXFxzKlxcXFxiJHtfLmVzY2FwZVJlZ0V4cChkZXBlbmRlbmN5UGxhY2Vob2xkZXIpfVxcXFxiYCwgJ20nKTtcbiAgY29uc3QgcGxhY2Vob2xkZXJJbmRleCA9IGNvbmZpZ3VyYXRpb25MaW5lcy5maW5kSW5kZXgoKGxpbmUpID0+IHNlYXJjaFJlLnRlc3QobGluZSkpO1xuICBpZiAocGxhY2Vob2xkZXJJbmRleCA8IDApIHtcbiAgICByZXR1cm4gb3JpZ2luYWxDb250ZW50O1xuICB9XG5cbiAgY29uc3QgcGxhY2Vob2xkZXJMaW5lID0gY29uZmlndXJhdGlvbkxpbmVzW3BsYWNlaG9sZGVySW5kZXhdO1xuICBjb25zdCBpbmRlbnRMZW4gPSBwbGFjZWhvbGRlckxpbmUubGVuZ3RoIC0gXy50cmltU3RhcnQocGxhY2Vob2xkZXJMaW5lKS5sZW5ndGg7XG4gIGNvbmZpZ3VyYXRpb25MaW5lcy5zcGxpY2UocGxhY2Vob2xkZXJJbmRleCArIDEsIDAsIC4uLihkZXBlbmRlbmN5TGluZXNcbiAgICAubWFwKChsaW5lKSA9PiBgJHsnICcucmVwZWF0KGluZGVudExlbil9JHtsaW5lfWApKSk7XG4gIHJldHVybiBjb25maWd1cmF0aW9uTGluZXMuam9pbignXFxuJyk7XG59XG5cbmV4cG9ydCB7IHF1YWxpZnlBY3Rpdml0eU5hbWUsIGNvcHlHcmFkbGVQcm9qZWN0UmVjdXJzaXZlbHksIHJlcXVpcmVPcHRpb25zLCB1cGRhdGVEZXBlbmRlbmN5TGluZXMgfTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFTQSxTQUFTQSxtQkFBVCxDQUE4QkMsWUFBOUIsRUFBNENDLFdBQTVDLEVBQXlE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
|
|
Binary file
|
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
|
@@ -3,7 +3,6 @@ import path from 'path';
|
|
|
3
3
|
import { BaseDriver, errors, isErrorType, DeviceSettings} from '@appium/base-driver';
|
|
4
4
|
import { EspressoRunner, TEST_APK_PKG } from './espresso-runner';
|
|
5
5
|
import { fs, tempDir, zip } from '@appium/support';
|
|
6
|
-
import logger from './logger';
|
|
7
6
|
import commands from './commands';
|
|
8
7
|
import { DEFAULT_ADB_PORT } from 'appium-adb';
|
|
9
8
|
import { androidHelpers, androidCommands, SETTINGS_HELPER_PKG_ID } from 'appium-android-driver';
|
|
@@ -180,11 +179,11 @@ class EspressoDriver extends BaseDriver {
|
|
|
180
179
|
|
|
181
180
|
if (this.isChromeSession) {
|
|
182
181
|
if (this.opts.app) {
|
|
183
|
-
|
|
184
|
-
|
|
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 ` +
|
|
185
184
|
`have permission to access Chrome`);
|
|
186
185
|
} else {
|
|
187
|
-
|
|
186
|
+
this.log.errorAndThrow(`Chrome browser sessions cannot be run in Espresso because Espresso ` +
|
|
188
187
|
`automation doesn't have permission to access Chrome`);
|
|
189
188
|
}
|
|
190
189
|
}
|
|
@@ -214,10 +213,10 @@ class EspressoDriver extends BaseDriver {
|
|
|
214
213
|
} else if (this.appOnDevice) {
|
|
215
214
|
// the app isn't an actual app file but rather something we want to
|
|
216
215
|
// assume is on the device and just launch via the appPackage
|
|
217
|
-
|
|
216
|
+
this.log.info(`App file was not listed, instead we're going to run ` +
|
|
218
217
|
`${this.opts.appPackage} directly on the device`);
|
|
219
218
|
if (!await this.adb.isAppInstalled(this.opts.appPackage)) {
|
|
220
|
-
|
|
219
|
+
this.log.errorAndThrow(`Could not find the package '${this.opts.appPackage}' ` +
|
|
221
220
|
`installed on the device`);
|
|
222
221
|
}
|
|
223
222
|
}
|
|
@@ -260,18 +259,18 @@ class EspressoDriver extends BaseDriver {
|
|
|
260
259
|
})).sort((a, b) => a.split(path.sep).length - b.split(path.sep).length);
|
|
261
260
|
if (sortedBundleItems.length === 0) {
|
|
262
261
|
// no expected packages in the zip
|
|
263
|
-
|
|
262
|
+
this.log.errorAndThrow(`${this.opts.app} did not have any of '${SUPPORTED_EXTENSIONS.join(', ')}' ` +
|
|
264
263
|
`extension packages. Please make sure the provided .zip archive contains at least one valid application package.`);
|
|
265
264
|
}
|
|
266
265
|
const unzippedAppPath = path.join(tmpRoot, _.first(sortedBundleItems));
|
|
267
|
-
|
|
266
|
+
this.log.debug(`'${unzippedAppPath}' is the unzipped file from '${appPath}'`);
|
|
268
267
|
return unzippedAppPath;
|
|
269
268
|
}
|
|
270
269
|
|
|
271
270
|
async onPostConfigureApp ({cachedAppInfo, isUrl, appPath}) {
|
|
272
271
|
const presignApp = async (appLocation) => {
|
|
273
272
|
if (this.opts.noSign) {
|
|
274
|
-
|
|
273
|
+
this.log.info('Skipping application signing because noSign capability is set to true. ' +
|
|
275
274
|
'Having the application under test with improper signature/non-signed will cause ' +
|
|
276
275
|
'Espresso automation startup failure.');
|
|
277
276
|
} else if (!await this.adb.checkApkCert(appLocation, this.opts.appPackage)) {
|
|
@@ -289,7 +288,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
289
288
|
if (_.isPlainObject(cachedAppInfo)) {
|
|
290
289
|
const packageHash = await fs.hash(appPath);
|
|
291
290
|
if (packageHash === cachedAppInfo.packageHash && await fs.exists(cachedAppInfo.fullPath)) {
|
|
292
|
-
|
|
291
|
+
this.log.info(`Using '${cachedAppInfo.fullPath}' which is cached from '${appPath}'`);
|
|
293
292
|
isResultAppPathAlreadyCached = true;
|
|
294
293
|
pathInCache = cachedAppInfo.fullPath;
|
|
295
294
|
}
|
|
@@ -346,13 +345,13 @@ class EspressoDriver extends BaseDriver {
|
|
|
346
345
|
// TODO this method is duplicated from uiautomator2-driver; consolidate
|
|
347
346
|
setAvdFromCapabilities (caps) {
|
|
348
347
|
if (this.opts.avd) {
|
|
349
|
-
|
|
348
|
+
this.log.info('avd name defined, ignoring device name and platform version');
|
|
350
349
|
} else {
|
|
351
350
|
if (!caps.deviceName) {
|
|
352
|
-
|
|
351
|
+
this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
|
|
353
352
|
}
|
|
354
353
|
if (!caps.platformVersion) {
|
|
355
|
-
|
|
354
|
+
this.log.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
|
|
356
355
|
}
|
|
357
356
|
let avdDevice = caps.deviceName.replace(/[^a-zA-Z0-9_.]/g, '-');
|
|
358
357
|
this.opts.avd = `${avdDevice}__${caps.platformVersion}`;
|
|
@@ -370,11 +369,11 @@ class EspressoDriver extends BaseDriver {
|
|
|
370
369
|
|
|
371
370
|
// TODO much of this logic is duplicated from uiautomator2
|
|
372
371
|
async startEspressoSession () {
|
|
373
|
-
|
|
372
|
+
this.log.info(`EspressoDriver version: ${version}`);
|
|
374
373
|
|
|
375
374
|
// Read https://github.com/appium/appium-android-driver/pull/461 what happens if ther is no setHiddenApiPolicy for Android P+
|
|
376
375
|
if (await this.adb.getApiLevel() >= 28) { // Android P
|
|
377
|
-
|
|
376
|
+
this.log.warn('Relaxing hidden api policy');
|
|
378
377
|
await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
|
|
379
378
|
}
|
|
380
379
|
|
|
@@ -396,7 +395,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
396
395
|
await this.adb.setAnimationState(false);
|
|
397
396
|
this.wasAnimationEnabled = true;
|
|
398
397
|
} catch (err) {
|
|
399
|
-
|
|
398
|
+
this.log.warn(`Unable to turn off animations: ${err.message}`);
|
|
400
399
|
}
|
|
401
400
|
}
|
|
402
401
|
|
|
@@ -407,14 +406,14 @@ class EspressoDriver extends BaseDriver {
|
|
|
407
406
|
// set up the modified espresso server etc
|
|
408
407
|
this.initEspressoServer();
|
|
409
408
|
// Further prepare the device by forwarding the espresso port
|
|
410
|
-
|
|
409
|
+
this.log.debug(`Forwarding Espresso Server port ${DEVICE_PORT} to ${this.opts.systemPort}`);
|
|
411
410
|
await this.adb.forwardPort(this.opts.systemPort, DEVICE_PORT);
|
|
412
411
|
|
|
413
412
|
if (!this.opts.skipUnlock) {
|
|
414
413
|
// unlock the device to prepare it for testing
|
|
415
414
|
await helpers.unlock(this, this.adb, this.caps);
|
|
416
415
|
} else {
|
|
417
|
-
|
|
416
|
+
this.log.debug(`'skipUnlock' capability set, so skipping device unlock`);
|
|
418
417
|
}
|
|
419
418
|
|
|
420
419
|
// set up app under test
|
|
@@ -443,7 +442,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
443
442
|
// launch espresso and wait till its online and we have a session
|
|
444
443
|
await this.espresso.startSession(this.caps);
|
|
445
444
|
if (this.caps.autoLaunch === false) {
|
|
446
|
-
|
|
445
|
+
this.log.info(`Not waiting for the application activity to start because 'autoLaunch' is disabled`);
|
|
447
446
|
} else {
|
|
448
447
|
await this.adb.waitForActivity(this.caps.appWaitPackage, this.caps.appWaitActivity, this.opts.appWaitDuration);
|
|
449
448
|
}
|
|
@@ -463,7 +462,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
463
462
|
async initWebview () {
|
|
464
463
|
const viewName = androidCommands.defaultWebviewName.call(this);
|
|
465
464
|
const timeout = this.opts.autoWebviewTimeout || 2000;
|
|
466
|
-
|
|
465
|
+
this.log.info(`Setting webview to context '${viewName}' with timeout ${timeout}ms`);
|
|
467
466
|
await retryInterval(timeout / 500, 500, this.setContext.bind(this), viewName);
|
|
468
467
|
}
|
|
469
468
|
|
|
@@ -487,7 +486,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
487
486
|
initEspressoServer () {
|
|
488
487
|
// now that we have package and activity, we can create an instance of
|
|
489
488
|
// espresso with the appropriate data
|
|
490
|
-
this.espresso = new EspressoRunner({
|
|
489
|
+
this.espresso = new EspressoRunner(this.log, {
|
|
491
490
|
host: this.opts.remoteAdbHost || this.opts.host || '127.0.0.1',
|
|
492
491
|
systemPort: this.opts.systemPort,
|
|
493
492
|
devicePort: DEVICE_PORT,
|
|
@@ -532,9 +531,9 @@ class EspressoDriver extends BaseDriver {
|
|
|
532
531
|
|
|
533
532
|
if (!this.opts.app) {
|
|
534
533
|
if (this.opts.fullReset) {
|
|
535
|
-
|
|
534
|
+
this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
|
|
536
535
|
}
|
|
537
|
-
|
|
536
|
+
this.log.debug('No app capability. Assuming it is already on the device');
|
|
538
537
|
if (this.opts.fastReset) {
|
|
539
538
|
await helpers.resetApp(this.adb, this.opts);
|
|
540
539
|
}
|
|
@@ -547,20 +546,20 @@ class EspressoDriver extends BaseDriver {
|
|
|
547
546
|
await helpers.installApk(this.adb, this.opts);
|
|
548
547
|
}
|
|
549
548
|
if (this.opts.skipServerInstallation) {
|
|
550
|
-
|
|
549
|
+
this.log.debug('skipServerInstallation capability is set. Not installig espresso-server ');
|
|
551
550
|
} else {
|
|
552
551
|
await this.espresso.installTestApk();
|
|
553
552
|
try {
|
|
554
553
|
await this.adb.addToDeviceIdleWhitelist(SETTINGS_HELPER_PKG_ID, TEST_APK_PKG);
|
|
555
554
|
} catch (e) {
|
|
556
|
-
|
|
555
|
+
this.log.warn(`Cannot add server packages to the Doze whitelist. Original error: ` +
|
|
557
556
|
(e.stderr || e.message));
|
|
558
557
|
}
|
|
559
558
|
}
|
|
560
559
|
}
|
|
561
560
|
|
|
562
561
|
async deleteSession () {
|
|
563
|
-
|
|
562
|
+
this.log.debug('Deleting espresso session');
|
|
564
563
|
|
|
565
564
|
try {
|
|
566
565
|
if (!_.isEmpty(this._screenRecordingProperties)) {
|
|
@@ -586,29 +585,29 @@ class EspressoDriver extends BaseDriver {
|
|
|
586
585
|
try {
|
|
587
586
|
await this.adb.setAnimationState(true);
|
|
588
587
|
} catch (err) {
|
|
589
|
-
|
|
588
|
+
this.log.warn(`Unable to reset animation: ${err.message}`);
|
|
590
589
|
}
|
|
591
590
|
}
|
|
592
591
|
if (this.opts.unicodeKeyboard && this.opts.resetKeyboard &&
|
|
593
592
|
this.defaultIME) {
|
|
594
|
-
|
|
593
|
+
this.log.debug(`Resetting IME to '${this.defaultIME}'`);
|
|
595
594
|
await this.adb.setIME(this.defaultIME);
|
|
596
595
|
}
|
|
597
596
|
if (!this.isChromeSession && this.opts.appPackage && !this.opts.dontStopAppOnReset) {
|
|
598
597
|
await this.adb.forceStop(this.opts.appPackage);
|
|
599
598
|
}
|
|
600
599
|
if (this.opts.fullReset && !this.opts.skipUninstall && !this.appOnDevice) {
|
|
601
|
-
|
|
600
|
+
this.log.debug(`FULL_RESET set to 'true', Uninstalling '${this.opts.appPackage}'`);
|
|
602
601
|
await this.adb.uninstallApk(this.opts.appPackage);
|
|
603
602
|
}
|
|
604
603
|
await this.adb.stopLogcat();
|
|
605
604
|
if (this.opts.reboot) {
|
|
606
605
|
let avdName = this.opts.avd.replace('@', '');
|
|
607
|
-
|
|
606
|
+
this.log.debug(`closing emulator '${avdName}'`);
|
|
608
607
|
await this.adb.killEmulator(avdName);
|
|
609
608
|
}
|
|
610
609
|
if (await this.adb.getApiLevel() >= 28) { // Android P
|
|
611
|
-
|
|
610
|
+
this.log.info('Restoring hidden api policy to the device default configuration');
|
|
612
611
|
await this.adb.setDefaultHiddenApiPolicy(!!this.opts.ignoreHiddenApiPolicyError);
|
|
613
612
|
}
|
|
614
613
|
}
|
|
@@ -617,7 +616,7 @@ class EspressoDriver extends BaseDriver {
|
|
|
617
616
|
try {
|
|
618
617
|
await this.adb.removePortForward(this.opts.systemPort);
|
|
619
618
|
} catch (error) {
|
|
620
|
-
|
|
619
|
+
this.log.warn(`Unable to remove port forward '${error.message}'`);
|
|
621
620
|
//Ignore, this block will also be called when we fall in catch block
|
|
622
621
|
// and before even port forward.
|
|
623
622
|
}
|
package/lib/espresso-runner.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { JWProxy, errors } from '@appium/base-driver';
|
|
2
2
|
import { waitForCondition } from 'asyncbox';
|
|
3
|
-
import logger from './logger';
|
|
4
3
|
import { ServerBuilder, buildServerSigningConfig } from './server-builder';
|
|
5
4
|
import path from 'path';
|
|
6
5
|
import { fs, util, mkdirp, timing } from '@appium/support';
|
|
@@ -38,14 +37,16 @@ class EspressoProxy extends JWProxy {
|
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
class EspressoRunner {
|
|
41
|
-
constructor (opts = {}) {
|
|
40
|
+
constructor (log, opts = {}) {
|
|
42
41
|
for (let req of REQUIRED_PARAMS) {
|
|
43
42
|
if (!opts || !util.hasValue(opts[req])) {
|
|
44
43
|
throw new Error(`Option '${req}' is required!`);
|
|
45
44
|
}
|
|
46
45
|
this[req] = opts[req];
|
|
47
46
|
}
|
|
47
|
+
this.log = log;
|
|
48
48
|
this.jwproxy = new EspressoProxy({
|
|
49
|
+
log,
|
|
49
50
|
server: this.host,
|
|
50
51
|
port: this.systemPort,
|
|
51
52
|
base: '',
|
|
@@ -85,11 +86,11 @@ class EspressoRunner {
|
|
|
85
86
|
|
|
86
87
|
async isAppPackageChanged () {
|
|
87
88
|
if (!await this.adb.fileExists(TARGET_PACKAGE_CONTAINER)) {
|
|
88
|
-
|
|
89
|
+
this.log.debug('The previous target application package is unknown');
|
|
89
90
|
return true;
|
|
90
91
|
}
|
|
91
92
|
const previousAppPackage = (await this.adb.shell(['cat', TARGET_PACKAGE_CONTAINER])).trim();
|
|
92
|
-
|
|
93
|
+
this.log.debug(`The previous target application package was '${previousAppPackage}'. ` +
|
|
93
94
|
`The current package is '${this.appPackage}'`);
|
|
94
95
|
return previousAppPackage !== this.appPackage;
|
|
95
96
|
}
|
|
@@ -110,21 +111,21 @@ class EspressoRunner {
|
|
|
110
111
|
].includes(appState);
|
|
111
112
|
|
|
112
113
|
if (shouldUninstallApp) {
|
|
113
|
-
|
|
114
|
+
this.log.info(`Uninstalling Espresso Test Server apk from the target device (pkg: '${TEST_APK_PKG}')`);
|
|
114
115
|
try {
|
|
115
116
|
await this.adb.uninstallApk(TEST_APK_PKG);
|
|
116
117
|
} catch (err) {
|
|
117
|
-
|
|
118
|
+
this.log.warn(`Error uninstalling '${TEST_APK_PKG}': ${err.message}`);
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
if (shouldInstallApp) {
|
|
122
|
-
|
|
123
|
+
this.log.info(`Installing Espresso Test Server apk from the target device (path: '${this.modServerPath}')`);
|
|
123
124
|
try {
|
|
124
125
|
await this.adb.install(this.modServerPath, { replace: false, timeout: this.androidInstallTimeout });
|
|
125
|
-
|
|
126
|
+
this.log.info(`Installed Espresso Test Server apk '${this.modServerPath}' (pkg: '${TEST_APK_PKG}')`);
|
|
126
127
|
} catch (err) {
|
|
127
|
-
|
|
128
|
+
this.log.errorAndThrow(`Cannot install '${this.modServerPath}' because of '${err.message}'`);
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
}
|
|
@@ -132,14 +133,14 @@ class EspressoRunner {
|
|
|
132
133
|
async installTestApk () {
|
|
133
134
|
let rebuild = this.forceEspressoRebuild;
|
|
134
135
|
if (rebuild) {
|
|
135
|
-
|
|
136
|
+
this.log.debug(`'forceEspressoRebuild' capability is enabled`);
|
|
136
137
|
} else if (await this.isAppPackageChanged()) {
|
|
137
|
-
|
|
138
|
+
this.log.info(`Forcing Espresso server rebuild because of changed application package`);
|
|
138
139
|
rebuild = true;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
if (rebuild && await fs.exists(this.modServerPath)) {
|
|
142
|
-
|
|
143
|
+
this.log.debug(`Deleting the obsolete Espresso server package '${this.modServerPath}'`);
|
|
143
144
|
await fs.unlink(this.modServerPath);
|
|
144
145
|
}
|
|
145
146
|
if (!(await fs.exists(this.modServerPath))) {
|
|
@@ -150,7 +151,7 @@ class EspressoRunner {
|
|
|
150
151
|
await this.adb.sign(this.modServerPath);
|
|
151
152
|
}
|
|
152
153
|
if ((rebuild || !isSigned) && await this.adb.uninstallApk(TEST_APK_PKG)) {
|
|
153
|
-
|
|
154
|
+
this.log.info('Uninstalled the obsolete Espresso server package from the device under test');
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
await this.installServer();
|
|
@@ -161,16 +162,16 @@ class EspressoRunner {
|
|
|
161
162
|
if (this.espressoBuildConfig) {
|
|
162
163
|
let buildConfigurationStr;
|
|
163
164
|
if (await fs.exists(this.espressoBuildConfig)) {
|
|
164
|
-
|
|
165
|
+
this.log.info(`Loading the build configuration from '${this.espressoBuildConfig}'`);
|
|
165
166
|
buildConfigurationStr = await fs.readFile(this.espressoBuildConfig, 'utf8');
|
|
166
167
|
} else {
|
|
167
|
-
|
|
168
|
+
this.log.info(`Loading the build configuration from 'espressoBuildConfig' capability`);
|
|
168
169
|
buildConfigurationStr = this.espressoBuildConfig;
|
|
169
170
|
}
|
|
170
171
|
try {
|
|
171
172
|
buildConfiguration = JSON.parse(buildConfigurationStr);
|
|
172
173
|
} catch (e) {
|
|
173
|
-
|
|
174
|
+
this.log.error('Cannot parse the build configuration JSON', e);
|
|
174
175
|
throw e;
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -178,26 +179,26 @@ class EspressoRunner {
|
|
|
178
179
|
replacement: '-',
|
|
179
180
|
});
|
|
180
181
|
const serverPath = path.resolve(this.tmpDir, dirName);
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
this.log.info(`Building espresso server in '${serverPath}'`);
|
|
183
|
+
this.log.debug(`The build folder root could be customized by changing the 'tmpDir' capability`);
|
|
183
184
|
await fs.rimraf(serverPath);
|
|
184
185
|
await mkdirp(serverPath);
|
|
185
|
-
|
|
186
|
+
this.log.debug(`Copying espresso server template from ('${TEST_SERVER_ROOT}' to '${serverPath}')`);
|
|
186
187
|
await copyGradleProjectRecursively(TEST_SERVER_ROOT, serverPath);
|
|
187
|
-
|
|
188
|
-
await new ServerBuilder({
|
|
188
|
+
this.log.debug('Bulding espresso server');
|
|
189
|
+
await new ServerBuilder(this.log, {
|
|
189
190
|
serverPath, buildConfiguration,
|
|
190
191
|
showGradleLog: this.showGradleLog,
|
|
191
192
|
testAppPackage: this.appPackage,
|
|
192
193
|
signingConfig: this.signingConfig
|
|
193
194
|
}).build();
|
|
194
195
|
const apkPath = path.resolve(serverPath, 'app', 'build', 'outputs', 'apk', 'androidTest', 'debug', 'app-debug-androidTest.apk');
|
|
195
|
-
|
|
196
|
+
this.log.debug(`Copying built apk from '${apkPath}' to '${this.modServerPath}'`);
|
|
196
197
|
await fs.copyFile(apkPath, this.modServerPath);
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
async cleanupSessionLeftovers () {
|
|
200
|
-
|
|
201
|
+
this.log.debug('Performing cleanup of automation leftovers');
|
|
201
202
|
|
|
202
203
|
try {
|
|
203
204
|
const {value} = (await axios({
|
|
@@ -206,8 +207,8 @@ class EspressoRunner {
|
|
|
206
207
|
})).data;
|
|
207
208
|
const activeSessionIds = value.map((sess) => sess.id);
|
|
208
209
|
if (activeSessionIds.length) {
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
this.log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
|
|
211
|
+
this.log.debug('Cleaning up the obsolete sessions');
|
|
211
212
|
await B.all(activeSessionIds.map((id) =>
|
|
212
213
|
axios({
|
|
213
214
|
url: `http://${this.host}:${this.systemPort}/session/${id}`,
|
|
@@ -217,10 +218,10 @@ class EspressoRunner {
|
|
|
217
218
|
// Let all sessions to be properly terminated before continuing
|
|
218
219
|
await B.delay(1000);
|
|
219
220
|
} else {
|
|
220
|
-
|
|
221
|
+
this.log.debug('No obsolete sessions have been detected');
|
|
221
222
|
}
|
|
222
223
|
} catch (e) {
|
|
223
|
-
|
|
224
|
+
this.log.debug(`No obsolete sessions have been detected (${e.message})`);
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
227
|
|
|
@@ -241,7 +242,7 @@ class EspressoRunner {
|
|
|
241
242
|
|
|
242
243
|
cmd.push(`${TEST_APK_PKG}/androidx.test.runner.AndroidJUnitRunner`);
|
|
243
244
|
|
|
244
|
-
|
|
245
|
+
this.log.info(`Starting Espresso Server v${version} with cmd: adb ${cmd.join(' ')}`);
|
|
245
246
|
|
|
246
247
|
let hasSocketError = false;
|
|
247
248
|
// start the instrumentation process
|
|
@@ -251,7 +252,7 @@ class EspressoRunner {
|
|
|
251
252
|
};
|
|
252
253
|
this.instProcess = this.adb.createSubProcess(cmd);
|
|
253
254
|
this.instProcess.on('exit', (code, signal) => {
|
|
254
|
-
|
|
255
|
+
this.log.info(`Instrumentation process exited with code ${code} from signal ${signal}`);
|
|
255
256
|
this.jwproxy.instrumentationState.exited = true;
|
|
256
257
|
});
|
|
257
258
|
this.instProcess.on('output', (stdout, stderr) => {
|
|
@@ -261,7 +262,7 @@ class EspressoRunner {
|
|
|
261
262
|
return;
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
|
|
265
|
+
this.log.debug(`[Instrumentation] ${line.trim()}`);
|
|
265
266
|
// A 'SocketException' indicates that we couldn't connect to the Espresso server,
|
|
266
267
|
// because the INTERNET permission is not set
|
|
267
268
|
if (line.toLowerCase().includes('java.net.socketexception')) {
|
|
@@ -273,15 +274,15 @@ class EspressoRunner {
|
|
|
273
274
|
|
|
274
275
|
const timer = new timing.Timer().start();
|
|
275
276
|
await this.instProcess.start(0);
|
|
276
|
-
|
|
277
|
+
this.log.info(`Waiting up to ${this.serverLaunchTimeout}ms for Espresso server to be online`);
|
|
277
278
|
try {
|
|
278
279
|
await waitForCondition(async () => {
|
|
279
280
|
if (hasSocketError) {
|
|
280
|
-
|
|
281
|
+
this.log.errorAndThrow(`Espresso server has failed to start due to an unexpected exception. ` +
|
|
281
282
|
`Make sure the 'INTERNET' permission is requested in the Android manifest of your ` +
|
|
282
283
|
`application under test (<uses-permission android:name="android.permission.INTERNET" />)`);
|
|
283
284
|
} else if (this.jwproxy.instrumentationState.exited) {
|
|
284
|
-
|
|
285
|
+
this.log.errorAndThrow(`Espresso server process has been unexpectedly terminated. ` +
|
|
285
286
|
`Check the Appium server log and the logcat output for more details`);
|
|
286
287
|
}
|
|
287
288
|
try {
|
|
@@ -296,15 +297,15 @@ class EspressoRunner {
|
|
|
296
297
|
});
|
|
297
298
|
} catch (e) {
|
|
298
299
|
if (/Condition unmet/.test(e.message)) {
|
|
299
|
-
|
|
300
|
+
this.log.errorAndThrow(`Timed out waiting for Espresso server to be ` +
|
|
300
301
|
`online within ${this.serverLaunchTimeout}ms. The timeout value could be ` +
|
|
301
302
|
`customized using 'espressoServerLaunchTimeout' capability`);
|
|
302
303
|
}
|
|
303
304
|
throw e;
|
|
304
305
|
}
|
|
305
|
-
|
|
306
|
+
this.log.info(`Espresso server is online. ` +
|
|
306
307
|
`The initialization process took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
307
|
-
|
|
308
|
+
this.log.info('Starting the session');
|
|
308
309
|
|
|
309
310
|
await this.jwproxy.command('/session', 'POST', {
|
|
310
311
|
capabilities: {
|
|
@@ -317,17 +318,17 @@ class EspressoRunner {
|
|
|
317
318
|
|
|
318
319
|
async recordTargetAppPackage () {
|
|
319
320
|
await this.adb.shell([`echo "${this.appPackage}" > "${TARGET_PACKAGE_CONTAINER}"`]);
|
|
320
|
-
|
|
321
|
+
this.log.info(`Recorded the target application package '${this.appPackage}' to ${TARGET_PACKAGE_CONTAINER}`);
|
|
321
322
|
}
|
|
322
323
|
|
|
323
324
|
async deleteSession () {
|
|
324
|
-
|
|
325
|
+
this.log.debug('Deleting Espresso server session');
|
|
325
326
|
// rely on jwproxy's intelligence to know what we're talking about and
|
|
326
327
|
// delete the current session
|
|
327
328
|
try {
|
|
328
329
|
await this.jwproxy.command('/', 'DELETE');
|
|
329
330
|
} catch (err) {
|
|
330
|
-
|
|
331
|
+
this.log.warn(`Did not get confirmation Espresso deleteSession worked; ` +
|
|
331
332
|
`Error was: ${err}`);
|
|
332
333
|
}
|
|
333
334
|
|