appium-uiautomator2-driver 1.73.0 → 2.0.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/README.md +26 -5
- package/build/index.js +6 -4
- package/build/lib/commands/actions.js +1 -1
- package/build/lib/commands/alert.js +1 -1
- package/build/lib/commands/element.js +9 -9
- package/build/lib/commands/find.js +6 -12
- package/build/lib/commands/general.js +11 -10
- package/build/lib/commands/gestures.js +7 -7
- package/build/lib/commands/viewport.js +3 -3
- package/build/lib/css-converter.js +120 -113
- package/build/lib/driver.js +11 -11
- package/build/lib/extensions.js +1 -1
- package/build/lib/helpers.js +5 -5
- package/build/lib/logger.js +3 -3
- package/build/lib/server.js +5 -5
- package/build/lib/uiautomator2.js +15 -15
- package/lib/.DS_Store +0 -0
- package/lib/commands/element.js +2 -2
- package/lib/commands/find.js +5 -9
- package/lib/commands/general.js +4 -2
- package/lib/commands/gestures.js +2 -2
- package/lib/commands/viewport.js +1 -1
- package/lib/css-converter.js +178 -170
- package/lib/driver.js +2 -2
- package/lib/helpers.js +1 -1
- package/lib/logger.js +1 -1
- package/lib/server.js +1 -1
- package/lib/uiautomator2.js +4 -4
- package/package.json +21 -15
package/lib/css-converter.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { CssSelectorParser } from 'css-selector-parser';
|
|
2
2
|
import { escapeRegExp } from 'lodash';
|
|
3
|
-
import { errors } from 'appium
|
|
4
|
-
|
|
5
|
-
const CssConverter = {};
|
|
3
|
+
import { errors } from '@appium/base-driver';
|
|
6
4
|
|
|
7
5
|
const parser = new CssSelectorParser();
|
|
8
6
|
parser.registerSelectorPseudos('has');
|
|
@@ -113,16 +111,6 @@ function getWordMatcherRegex (word) {
|
|
|
113
111
|
return `\\b(\\w*${escapeRegExp(word)}\\w*)\\b`;
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
/**
|
|
117
|
-
* Add android:id/ to beginning of string if it's not there already
|
|
118
|
-
*
|
|
119
|
-
* @param {string} locator The initial locator
|
|
120
|
-
* @returns {string} String with `android:id/` prepended (if it wasn't already)
|
|
121
|
-
*/
|
|
122
|
-
function formatIdLocator (locator) {
|
|
123
|
-
return ID_LOCATOR_PATTERN.test(locator) ? locator : `android:id/${locator}`;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
114
|
/**
|
|
127
115
|
* @typedef {Object} CssAttr
|
|
128
116
|
* @property {?string} valueType Type of attribute (must be string or empty)
|
|
@@ -131,62 +119,20 @@ function formatIdLocator (locator) {
|
|
|
131
119
|
*/
|
|
132
120
|
|
|
133
121
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* @
|
|
137
|
-
* @
|
|
122
|
+
* @typedef {Object} CssRule
|
|
123
|
+
* @property {?string} nestingOperator The nesting operator (aka: combinator https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)
|
|
124
|
+
* @property {?string} tagName The tag name (aka: type selector https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
|
|
125
|
+
* @property {?string[]} classNames An array of CSS class names
|
|
126
|
+
* @property {?CssAttr[]} attrs An array of CSS attributes
|
|
127
|
+
* @property {?CssPseudo[]} attrs An array of CSS pseudos
|
|
128
|
+
* @property {?string} id CSS identifier
|
|
129
|
+
* @property {?CssRule} rule A descendant of this CSS rule
|
|
138
130
|
*/
|
|
139
|
-
function parseAttr (cssAttr) {
|
|
140
|
-
if (cssAttr.valueType && cssAttr.valueType !== 'string') {
|
|
141
|
-
throw new Error(`'${cssAttr.name}=${cssAttr.value}' is an invalid attribute. ` +
|
|
142
|
-
`Only 'string' and empty attribute types are supported. Found '${cssAttr.valueType}'`);
|
|
143
|
-
}
|
|
144
|
-
const attrName = assertGetAttrName(cssAttr);
|
|
145
|
-
const methodName = toSnakeCase(attrName);
|
|
146
|
-
|
|
147
|
-
// Validate that it's a supported attribute
|
|
148
|
-
if (!STR_ATTRS.includes(attrName) && !BOOLEAN_ATTRS.includes(attrName)) {
|
|
149
|
-
throw new Error(`'${attrName}' is not supported. Supported attributes are ` +
|
|
150
|
-
`'${[...STR_ATTRS, ...BOOLEAN_ATTRS].join(', ')}'`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Parse boolean, if it's a boolean attribute
|
|
154
|
-
if (BOOLEAN_ATTRS.includes(attrName)) {
|
|
155
|
-
return `.${methodName}(${assertGetBool(cssAttr)})`;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Otherwise parse as string
|
|
159
|
-
let value = cssAttr.value || '';
|
|
160
|
-
if (attrName === RESOURCE_ID) {
|
|
161
|
-
value = formatIdLocator(value);
|
|
162
|
-
}
|
|
163
|
-
if (value === '') {
|
|
164
|
-
return `.${methodName}Matches("")`;
|
|
165
|
-
}
|
|
166
131
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (['description', 'text'].includes(attrName)) {
|
|
172
|
-
return `.${methodName}Contains("${value}")`;
|
|
173
|
-
}
|
|
174
|
-
return `.${methodName}Matches("${escapeRegExp(value)}")`;
|
|
175
|
-
case '^=':
|
|
176
|
-
if (['description', 'text'].includes(attrName)) {
|
|
177
|
-
return `.${methodName}StartsWith("${value}")`;
|
|
178
|
-
}
|
|
179
|
-
return `.${methodName}Matches("^${escapeRegExp(value)}")`;
|
|
180
|
-
case '$=':
|
|
181
|
-
return `.${methodName}Matches("${escapeRegExp(value)}$")`;
|
|
182
|
-
case '~=':
|
|
183
|
-
return `.${methodName}Matches("${getWordMatcherRegex(value)}")`;
|
|
184
|
-
default:
|
|
185
|
-
// Unreachable, but adding error in case a new CSS attribute is added.
|
|
186
|
-
throw new Error(`Unsupported CSS attribute operator '${cssAttr.operator}'. ` +
|
|
187
|
-
` '=', '*=', '^=', '$=' and '~=' are supported.`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
132
|
+
/**
|
|
133
|
+
* @typedef {Object} CssObject
|
|
134
|
+
* @property {?string} type Type of CSS object. 'rule', 'ruleset' or 'selectors'
|
|
135
|
+
*/
|
|
190
136
|
|
|
191
137
|
/**
|
|
192
138
|
* @typedef {Object} CssPseudo
|
|
@@ -195,126 +141,188 @@ function parseAttr (cssAttr) {
|
|
|
195
141
|
* @property {?string} value The value of the pseudo selector
|
|
196
142
|
*/
|
|
197
143
|
|
|
198
|
-
|
|
199
|
-
* Convert a CSS pseudo class to a UiSelector
|
|
200
|
-
*
|
|
201
|
-
* @param {CssPseudo} cssPseudo CSS Pseudo class
|
|
202
|
-
* @returns {string} Pseudo selector parsed as UiSelector
|
|
203
|
-
*/
|
|
204
|
-
function parsePseudo (cssPseudo) {
|
|
205
|
-
if (cssPseudo.valueType && cssPseudo.valueType !== 'string') {
|
|
206
|
-
throw new Error(`'${cssPseudo.name}=${cssPseudo.value}'. ` +
|
|
207
|
-
`Unsupported css pseudo class value type: '${cssPseudo.valueType}'. Only 'string' type or empty is supported.`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const pseudoName = assertGetAttrName(cssPseudo);
|
|
144
|
+
class CssConverter {
|
|
211
145
|
|
|
212
|
-
|
|
213
|
-
|
|
146
|
+
constructor (selector, pkg) {
|
|
147
|
+
this.selector = selector;
|
|
148
|
+
this.pkg = pkg;
|
|
214
149
|
}
|
|
215
150
|
|
|
216
|
-
|
|
217
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Add `<pkgName>:id/` prefix to beginning of string if it's not there already
|
|
153
|
+
*
|
|
154
|
+
* @param {string} locator The initial locator
|
|
155
|
+
* @returns {string} String with `<pkgName>:id/` prepended (if it wasn't already)
|
|
156
|
+
*/
|
|
157
|
+
formatIdLocator (locator) {
|
|
158
|
+
return ID_LOCATOR_PATTERN.test(locator)
|
|
159
|
+
? locator
|
|
160
|
+
: `${this.pkg || 'android'}:id/${locator}`;
|
|
218
161
|
}
|
|
219
|
-
}
|
|
220
162
|
|
|
221
|
-
/**
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Convert a CSS attribute into a UiSelector method call
|
|
165
|
+
*
|
|
166
|
+
* @param {CssAttr} cssAttr CSS attribute object
|
|
167
|
+
* @returns {string} CSS attribute parsed as UiSelector
|
|
168
|
+
*/
|
|
169
|
+
parseAttr (cssAttr) {
|
|
170
|
+
if (cssAttr.valueType && cssAttr.valueType !== 'string') {
|
|
171
|
+
throw new Error(`'${cssAttr.name}=${cssAttr.value}' is an invalid attribute. ` +
|
|
172
|
+
`Only 'string' and empty attribute types are supported. Found '${cssAttr.valueType}'`);
|
|
173
|
+
}
|
|
174
|
+
const attrName = assertGetAttrName(cssAttr);
|
|
175
|
+
const methodName = toSnakeCase(attrName);
|
|
231
176
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const { nestingOperator } = cssRule;
|
|
238
|
-
if (nestingOperator && nestingOperator !== ' ') {
|
|
239
|
-
throw new Error(`'${nestingOperator}' is not a supported combinator. ` +
|
|
240
|
-
`Only child combinator (>) and descendant combinator are supported.`);
|
|
241
|
-
}
|
|
177
|
+
// Validate that it's a supported attribute
|
|
178
|
+
if (!STR_ATTRS.includes(attrName) && !BOOLEAN_ATTRS.includes(attrName)) {
|
|
179
|
+
throw new Error(`'${attrName}' is not supported. Supported attributes are ` +
|
|
180
|
+
`'${[...STR_ATTRS, ...BOOLEAN_ATTRS].join(', ')}'`);
|
|
181
|
+
}
|
|
242
182
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (cssRule.classNames) {
|
|
247
|
-
for (const cssClassNames of cssRule.classNames) {
|
|
248
|
-
androidClass.push(cssClassNames);
|
|
249
|
-
}
|
|
250
|
-
uiAutomatorSelector += `.className("${androidClass.join('.')}")`;
|
|
251
|
-
} else {
|
|
252
|
-
uiAutomatorSelector += `.classNameMatches("${cssRule.tagName}")`;
|
|
183
|
+
// Parse boolean, if it's a boolean attribute
|
|
184
|
+
if (BOOLEAN_ATTRS.includes(attrName)) {
|
|
185
|
+
return `.${methodName}(${assertGetBool(cssAttr)})`;
|
|
253
186
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
if (cssRule.attrs) {
|
|
261
|
-
for (const attr of cssRule.attrs) {
|
|
262
|
-
uiAutomatorSelector += parseAttr(attr);
|
|
187
|
+
|
|
188
|
+
// Otherwise parse as string
|
|
189
|
+
let value = cssAttr.value || '';
|
|
190
|
+
if (attrName === RESOURCE_ID) {
|
|
191
|
+
value = this.formatIdLocator(value);
|
|
263
192
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
193
|
+
if (value === '') {
|
|
194
|
+
return `.${methodName}Matches("")`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
switch (cssAttr.operator) {
|
|
198
|
+
case '=':
|
|
199
|
+
return `.${methodName}("${value}")`;
|
|
200
|
+
case '*=':
|
|
201
|
+
if (['description', 'text'].includes(attrName)) {
|
|
202
|
+
return `.${methodName}Contains("${value}")`;
|
|
203
|
+
}
|
|
204
|
+
return `.${methodName}Matches("${escapeRegExp(value)}")`;
|
|
205
|
+
case '^=':
|
|
206
|
+
if (['description', 'text'].includes(attrName)) {
|
|
207
|
+
return `.${methodName}StartsWith("${value}")`;
|
|
208
|
+
}
|
|
209
|
+
return `.${methodName}Matches("^${escapeRegExp(value)}")`;
|
|
210
|
+
case '$=':
|
|
211
|
+
return `.${methodName}Matches("${escapeRegExp(value)}$")`;
|
|
212
|
+
case '~=':
|
|
213
|
+
return `.${methodName}Matches("${getWordMatcherRegex(value)}")`;
|
|
214
|
+
default:
|
|
215
|
+
// Unreachable, but adding error in case a new CSS attribute is added.
|
|
216
|
+
throw new Error(`Unsupported CSS attribute operator '${cssAttr.operator}'. ` +
|
|
217
|
+
` '=', '*=', '^=', '$=' and '~=' are supported.`);
|
|
268
218
|
}
|
|
269
219
|
}
|
|
270
|
-
|
|
271
|
-
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Convert a CSS pseudo class to a UiSelector
|
|
223
|
+
*
|
|
224
|
+
* @param {CssPseudo} cssPseudo CSS Pseudo class
|
|
225
|
+
* @returns {string} Pseudo selector parsed as UiSelector
|
|
226
|
+
*/
|
|
227
|
+
parsePseudo (cssPseudo) {
|
|
228
|
+
if (cssPseudo.valueType && cssPseudo.valueType !== 'string') {
|
|
229
|
+
throw new Error(`'${cssPseudo.name}=${cssPseudo.value}'. ` +
|
|
230
|
+
`Unsupported css pseudo class value type: '${cssPseudo.valueType}'. Only 'string' type or empty is supported.`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const pseudoName = assertGetAttrName(cssPseudo);
|
|
234
|
+
|
|
235
|
+
if (BOOLEAN_ATTRS.includes(pseudoName)) {
|
|
236
|
+
return `.${toSnakeCase(pseudoName)}(${assertGetBool(cssPseudo)})`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (NUMERIC_ATTRS.includes(pseudoName)) {
|
|
240
|
+
return `.${pseudoName}(${cssPseudo.value})`;
|
|
241
|
+
}
|
|
272
242
|
}
|
|
273
|
-
return uiAutomatorSelector;
|
|
274
|
-
}
|
|
275
243
|
|
|
276
|
-
/**
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Convert a CSS rule to a UiSelector
|
|
246
|
+
* @param {CssRule} cssRule CSS rule definition
|
|
247
|
+
*/
|
|
248
|
+
parseCssRule (cssRule) {
|
|
249
|
+
const { nestingOperator } = cssRule;
|
|
250
|
+
if (nestingOperator && nestingOperator !== ' ') {
|
|
251
|
+
throw new Error(`'${nestingOperator}' is not a supported combinator. ` +
|
|
252
|
+
`Only child combinator (>) and descendant combinator are supported.`);
|
|
253
|
+
}
|
|
280
254
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
255
|
+
let uiAutomatorSelector = 'new UiSelector()';
|
|
256
|
+
if (cssRule.tagName && cssRule.tagName !== '*') {
|
|
257
|
+
let androidClass = [cssRule.tagName];
|
|
258
|
+
if (cssRule.classNames) {
|
|
259
|
+
for (const cssClassNames of cssRule.classNames) {
|
|
260
|
+
androidClass.push(cssClassNames);
|
|
261
|
+
}
|
|
262
|
+
uiAutomatorSelector += `.className("${androidClass.join('.')}")`;
|
|
263
|
+
} else {
|
|
264
|
+
uiAutomatorSelector += `.classNameMatches("${cssRule.tagName}")`;
|
|
265
|
+
}
|
|
266
|
+
} else if (cssRule.classNames) {
|
|
267
|
+
uiAutomatorSelector += `.classNameMatches("${cssRule.classNames.join('\\.')}")`;
|
|
268
|
+
}
|
|
269
|
+
if (cssRule.id) {
|
|
270
|
+
uiAutomatorSelector += `.resourceId("${this.formatIdLocator(cssRule.id)}")`;
|
|
271
|
+
}
|
|
272
|
+
if (cssRule.attrs) {
|
|
273
|
+
for (const attr of cssRule.attrs) {
|
|
274
|
+
uiAutomatorSelector += this.parseAttr(attr);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (cssRule.pseudos) {
|
|
278
|
+
for (const pseudo of cssRule.pseudos) {
|
|
279
|
+
uiAutomatorSelector += this.parsePseudo(pseudo);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (cssRule.rule) {
|
|
283
|
+
uiAutomatorSelector += `.childSelector(${this.parseCssRule(cssRule.rule)})`;
|
|
284
|
+
}
|
|
285
|
+
return uiAutomatorSelector;
|
|
298
286
|
}
|
|
299
|
-
}
|
|
300
287
|
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Convert CSS object to UiAutomator2 selector
|
|
290
|
+
* @param {CssObject} css CSS object
|
|
291
|
+
* @returns {string} The CSS object parsed as a UiSelector
|
|
292
|
+
*/
|
|
293
|
+
parseCssObject (css) {
|
|
294
|
+
switch (css.type) {
|
|
295
|
+
case 'rule':
|
|
296
|
+
return this.parseCssRule(css);
|
|
297
|
+
case 'ruleSet':
|
|
298
|
+
return this.parseCssObject(css.rule);
|
|
299
|
+
case 'selectors':
|
|
300
|
+
return css.selectors.map((selector) => this.parseCssObject(selector)).join('; ');
|
|
301
|
+
|
|
302
|
+
default:
|
|
303
|
+
// This is never reachable, but if it ever is do this.
|
|
304
|
+
throw new Error(`UiAutomator does not support '${css.type}' css. Only supports 'rule', 'ruleSet', 'selectors' `);
|
|
305
|
+
}
|
|
312
306
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Convert a CSS selector to a UiAutomator2 selector
|
|
310
|
+
*
|
|
311
|
+
* @returns {string} The CSS selector converted to a UiSelector
|
|
312
|
+
*/
|
|
313
|
+
toUiAutomatorSelector () {
|
|
314
|
+
let cssObj;
|
|
315
|
+
try {
|
|
316
|
+
cssObj = parser.parse(this.selector);
|
|
317
|
+
} catch (e) {
|
|
318
|
+
throw new errors.InvalidSelectorError(`Invalid CSS selector '${this.selector}'. Reason: '${e}'`);
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
return this.parseCssObject(cssObj);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
throw new errors.InvalidSelectorError(`Unsupported CSS selector '${this.selector}'. Reason: '${e}'`);
|
|
324
|
+
}
|
|
317
325
|
}
|
|
318
|
-
}
|
|
326
|
+
}
|
|
319
327
|
|
|
320
328
|
export default CssConverter;
|
package/lib/driver.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { BaseDriver, DeviceSettings } from 'appium
|
|
2
|
+
import { BaseDriver, DeviceSettings } from '@appium/base-driver';
|
|
3
3
|
import {
|
|
4
4
|
UiAutomator2Server, SERVER_PACKAGE_ID, SERVER_TEST_PACKAGE_ID
|
|
5
5
|
} from './uiautomator2';
|
|
6
|
-
import { fs, util, mjpeg } from 'appium
|
|
6
|
+
import { fs, util, mjpeg } from '@appium/support';
|
|
7
7
|
import { retryInterval } from 'asyncbox';
|
|
8
8
|
import B from 'bluebird';
|
|
9
9
|
import logger from './logger';
|
package/lib/helpers.js
CHANGED
package/lib/logger.js
CHANGED
package/lib/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import log from './logger';
|
|
2
|
-
import { server as baseServer, routeConfiguringFunction as makeRouter } from 'appium
|
|
2
|
+
import { server as baseServer, routeConfiguringFunction as makeRouter } from '@appium/base-driver';
|
|
3
3
|
import AndroidUiautomator2Driver from './driver';
|
|
4
4
|
|
|
5
5
|
|
package/lib/uiautomator2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { JWProxy, errors } from 'appium
|
|
2
|
+
import { JWProxy, errors } from '@appium/base-driver';
|
|
3
3
|
import { waitForCondition } from 'asyncbox';
|
|
4
4
|
import log from './logger';
|
|
5
5
|
import {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from 'appium-uiautomator2-server';
|
|
10
10
|
import {
|
|
11
11
|
util, logger, tempDir, fs, timing
|
|
12
|
-
} from 'appium
|
|
12
|
+
} from '@appium/support';
|
|
13
13
|
import B from 'bluebird';
|
|
14
14
|
import helpers from './helpers';
|
|
15
15
|
import axios from 'axios';
|
|
@@ -306,7 +306,7 @@ class UiAutomator2Server {
|
|
|
306
306
|
|
|
307
307
|
try {
|
|
308
308
|
const {value} = (await axios({
|
|
309
|
-
url: `http://${this.host}:${this.systemPort}/
|
|
309
|
+
url: `http://${this.host}:${this.systemPort}/sessions`,
|
|
310
310
|
timeout: 500,
|
|
311
311
|
})).data;
|
|
312
312
|
const activeSessionIds = value.map(({id}) => id).filter(Boolean);
|
|
@@ -314,7 +314,7 @@ class UiAutomator2Server {
|
|
|
314
314
|
log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
|
|
315
315
|
log.debug(`Cleaning up ${util.pluralize('obsolete session', activeSessionIds.length, true)}`);
|
|
316
316
|
await B.all(activeSessionIds
|
|
317
|
-
.map((id) => axios.delete(`http://${this.host}:${this.systemPort}/
|
|
317
|
+
.map((id) => axios.delete(`http://${this.host}:${this.systemPort}/session/${id}`))
|
|
318
318
|
);
|
|
319
319
|
// Let all sessions to be properly terminated before continuing
|
|
320
320
|
await B.delay(1000);
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"automated testing",
|
|
8
8
|
"android"
|
|
9
9
|
],
|
|
10
|
-
"version": "
|
|
10
|
+
"version": "2.0.1",
|
|
11
11
|
"author": "appium",
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"repository": {
|
|
@@ -40,20 +40,20 @@
|
|
|
40
40
|
"build/lib"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@appium/base-driver": "^8.0.0",
|
|
44
|
+
"@appium/support": "^2.55.3",
|
|
43
45
|
"@babel/runtime": "^7.0.0",
|
|
44
|
-
"appium-adb": "^
|
|
45
|
-
"appium-android-driver": "^
|
|
46
|
-
"appium-
|
|
47
|
-
"appium-
|
|
48
|
-
"appium-support": "^2.49.0",
|
|
49
|
-
"appium-uiautomator2-server": "^4.28.0",
|
|
46
|
+
"appium-adb": "^9.0.0",
|
|
47
|
+
"appium-android-driver": "^5.0.0",
|
|
48
|
+
"appium-chromedriver": "^5.0.1",
|
|
49
|
+
"appium-uiautomator2-server": "^5.1.0",
|
|
50
50
|
"asyncbox": "^2.3.1",
|
|
51
51
|
"axios": "^0.x",
|
|
52
52
|
"bluebird": "^3.5.1",
|
|
53
53
|
"css-selector-parser": "^1.4.1",
|
|
54
54
|
"lodash": "^4.17.4",
|
|
55
|
-
"portscanner": "2.2.0",
|
|
56
|
-
"source-map-support": "^0.
|
|
55
|
+
"portscanner": "^2.2.0",
|
|
56
|
+
"source-map-support": "^0.x",
|
|
57
57
|
"teen_process": "^1.3.1"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
@@ -81,13 +81,19 @@
|
|
|
81
81
|
"test"
|
|
82
82
|
],
|
|
83
83
|
"devDependencies": {
|
|
84
|
+
"@appium/gulp-plugins": "^6.0.0",
|
|
85
|
+
"@appium/eslint-config-appium": "^5.0.0",
|
|
86
|
+
"@appium/test-support": "^1.0.0",
|
|
87
|
+
"@babel/core": "^7.16.0",
|
|
88
|
+
"@babel/eslint-parser": "^7.16.3",
|
|
84
89
|
"@xmldom/xmldom": "^0.x",
|
|
85
|
-
"android-apidemos": "^
|
|
86
|
-
"appium-gulp-plugins": "^5.4.0",
|
|
87
|
-
"appium-test-support": "^1.0.0",
|
|
90
|
+
"android-apidemos": "^4.0.0",
|
|
88
91
|
"chai": "^4.1.0",
|
|
89
92
|
"chai-as-promised": "^7.1.1",
|
|
90
|
-
"eslint
|
|
93
|
+
"eslint": "^7.32.0",
|
|
94
|
+
"eslint-plugin-import": "^2.25.3",
|
|
95
|
+
"eslint-plugin-mocha": "^9.0.0",
|
|
96
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
91
97
|
"gps-demo-app": "^2.1.1",
|
|
92
98
|
"gulp": "^4.0.0",
|
|
93
99
|
"mocha": "^9.0.0",
|
|
@@ -97,8 +103,8 @@
|
|
|
97
103
|
"pre-commit": "^1.2.2",
|
|
98
104
|
"rimraf": "^3.0.0",
|
|
99
105
|
"sinon": "^12.0.0",
|
|
100
|
-
"unzipper": "^0.
|
|
101
|
-
"
|
|
106
|
+
"unzipper": "^0.x",
|
|
107
|
+
"webdriverio": "^7.0.0",
|
|
102
108
|
"xpath": "^0.x"
|
|
103
109
|
}
|
|
104
110
|
}
|