appium-uiautomator2-driver 7.2.3 → 7.4.0

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/app-management.d.ts.map +1 -1
  3. package/build/lib/commands/app-management.js +1 -5
  4. package/build/lib/commands/app-management.js.map +1 -1
  5. package/build/lib/commands/element.d.ts.map +1 -1
  6. package/build/lib/commands/element.js +2 -6
  7. package/build/lib/commands/element.js.map +1 -1
  8. package/build/lib/commands/gestures.d.ts.map +1 -1
  9. package/build/lib/commands/gestures.js +2 -6
  10. package/build/lib/commands/gestures.js.map +1 -1
  11. package/build/lib/commands/keyboard.d.ts.map +1 -1
  12. package/build/lib/commands/keyboard.js +0 -8
  13. package/build/lib/commands/keyboard.js.map +1 -1
  14. package/build/lib/commands/screenshot.js +7 -8
  15. package/build/lib/commands/screenshot.js.map +1 -1
  16. package/build/lib/commands/types.d.ts +1 -1
  17. package/build/lib/commands/types.d.ts.map +1 -1
  18. package/build/lib/css-converter.js +9 -12
  19. package/build/lib/css-converter.js.map +1 -1
  20. package/build/lib/driver.d.ts +31 -30
  21. package/build/lib/driver.d.ts.map +1 -1
  22. package/build/lib/driver.js +72 -43
  23. package/build/lib/driver.js.map +1 -1
  24. package/build/lib/uiautomator2.d.ts.map +1 -1
  25. package/build/lib/uiautomator2.js +1 -2
  26. package/build/lib/uiautomator2.js.map +1 -1
  27. package/build/lib/{helpers.d.ts → utils/app.d.ts} +1 -1
  28. package/build/lib/utils/app.d.ts.map +1 -0
  29. package/build/lib/{helpers.js → utils/app.js} +1 -1
  30. package/build/lib/utils/app.js.map +1 -0
  31. package/build/lib/utils/index.d.ts +5 -0
  32. package/build/lib/utils/index.d.ts.map +1 -0
  33. package/build/lib/utils/index.js +21 -0
  34. package/build/lib/utils/index.js.map +1 -0
  35. package/build/lib/utils/lang.d.ts +15 -0
  36. package/build/lib/utils/lang.d.ts.map +1 -0
  37. package/build/lib/utils/lang.js +37 -0
  38. package/build/lib/utils/lang.js.map +1 -0
  39. package/build/lib/utils/memoize.d.ts +11 -0
  40. package/build/lib/utils/memoize.d.ts.map +1 -0
  41. package/build/lib/utils/memoize.js +26 -0
  42. package/build/lib/utils/memoize.js.map +1 -0
  43. package/build/lib/utils/object.d.ts +6 -0
  44. package/build/lib/utils/object.d.ts.map +1 -0
  45. package/build/lib/utils/object.js +15 -0
  46. package/build/lib/utils/object.js.map +1 -0
  47. package/lib/commands/app-management.ts +1 -2
  48. package/lib/commands/element.ts +2 -3
  49. package/lib/commands/gestures.ts +2 -3
  50. package/lib/commands/keyboard.ts +0 -5
  51. package/lib/commands/screenshot.ts +7 -7
  52. package/lib/commands/types.ts +1 -1
  53. package/lib/constraints.ts +1 -1
  54. package/lib/css-converter.ts +9 -9
  55. package/lib/driver.ts +124 -91
  56. package/lib/execute-method-map.ts +1 -1
  57. package/lib/uiautomator2.ts +5 -6
  58. package/lib/utils/index.ts +4 -0
  59. package/lib/utils/lang.ts +34 -0
  60. package/lib/utils/memoize.ts +26 -0
  61. package/lib/utils/object.ts +14 -0
  62. package/npm-shrinkwrap.json +95 -29
  63. package/package.json +7 -5
  64. package/build/lib/helpers.d.ts.map +0 -1
  65. package/build/lib/helpers.js.map +0 -1
  66. /package/lib/{helpers.ts → utils/app.ts} +0 -0
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // TODO(appium server 3.4.1+): Replace local `isEmpty` / `escapeRegExp` with imports from `appium/support`
3
+ // once this driver declares that minimum server version.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.isEmpty = isEmpty;
6
+ exports.escapeRegExp = escapeRegExp;
7
+ /**
8
+ * Returns true when the value has no elements/properties.
9
+ *
10
+ * @param value - Value to check
11
+ * @returns `true` if the value is empty
12
+ */
13
+ function isEmpty(value) {
14
+ if (value == null) {
15
+ return true;
16
+ }
17
+ if (typeof value === 'string' || Array.isArray(value) || Buffer.isBuffer(value)) {
18
+ return value.length === 0;
19
+ }
20
+ if (value instanceof Map || value instanceof Set) {
21
+ return value.size === 0;
22
+ }
23
+ if (typeof value === 'object' || typeof value === 'function') {
24
+ return Object.keys(value).length === 0;
25
+ }
26
+ return true;
27
+ }
28
+ /**
29
+ * Escapes RegExp special characters in a string.
30
+ *
31
+ * @param value - Input string
32
+ * @returns Escaped string safe for RegExp source
33
+ */
34
+ function escapeRegExp(value) {
35
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
36
+ }
37
+ //# sourceMappingURL=lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.js","sourceRoot":"","sources":["../../../lib/utils/lang.ts"],"names":[],"mappings":";AAAA,0GAA0G;AAC1G,yDAAyD;;AAQzD,0BAcC;AAQD,oCAEC;AA9BD;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,KAAc;IACpC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAChF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,KAAK,YAAY,GAAG,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Creates a memoized version of a function.
3
+ *
4
+ * @param fn - Function to memoize
5
+ * @param resolver - Optional cache key resolver. If omitted, the first argument is used as the cache key.
6
+ * @returns Memoized function with a mutable `.cache` map (compatible with lodash-style cache resets in tests).
7
+ */
8
+ export declare function memoize<Fn extends (...args: any[]) => any>(fn: Fn, resolver?: (...args: Parameters<Fn>) => unknown): Fn & {
9
+ cache: Map<unknown, ReturnType<Fn>>;
10
+ };
11
+ //# sourceMappingURL=memoize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoize.d.ts","sourceRoot":"","sources":["../../../lib/utils/memoize.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,EAAE,EACN,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,OAAO,GAC9C,EAAE,GAAG;IAAC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAA;CAAC,CAY5C"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ // TODO(appium server 3.4.1+): Replace local `memoize` with imports from `appium/support`
3
+ // once this driver declares that minimum server version.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.memoize = memoize;
6
+ /**
7
+ * Creates a memoized version of a function.
8
+ *
9
+ * @param fn - Function to memoize
10
+ * @param resolver - Optional cache key resolver. If omitted, the first argument is used as the cache key.
11
+ * @returns Memoized function with a mutable `.cache` map (compatible with lodash-style cache resets in tests).
12
+ */
13
+ function memoize(fn, resolver) {
14
+ const memoizedFn = function (...args) {
15
+ const key = resolver ? resolver.apply(this, args) : args[0];
16
+ if (memoizedFn.cache.has(key)) {
17
+ return memoizedFn.cache.get(key);
18
+ }
19
+ const result = fn.apply(this, args);
20
+ memoizedFn.cache.set(key, result);
21
+ return result;
22
+ };
23
+ memoizedFn.cache = new Map();
24
+ return memoizedFn;
25
+ }
26
+ //# sourceMappingURL=memoize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoize.js","sourceRoot":"","sources":["../../../lib/utils/memoize.ts"],"names":[],"mappings":";AAAA,yFAAyF;AACzF,yDAAyD;;AASzD,0BAeC;AAtBD;;;;;;GAMG;AACH,SAAgB,OAAO,CACrB,EAAM,EACN,QAA+C;IAE/C,MAAM,UAAU,GAAG,UAAyB,GAAG,IAAoB;QACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAmB,CAAC;QACrD,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACpC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAA0D,CAAC;IAC3D,UAAU,CAAC,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IACtD,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Assigns own enumerable properties of `source` onto `target` only where `target[key] === undefined`
3
+ * (lodash `defaults` semantics).
4
+ */
5
+ export declare function assignDefaults<T extends Record<string, unknown>>(target: T, source: Record<string, unknown>): void;
6
+ //# sourceMappingURL=object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../../lib/utils/object.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,IAAI,CAMN"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assignDefaults = assignDefaults;
4
+ /**
5
+ * Assigns own enumerable properties of `source` onto `target` only where `target[key] === undefined`
6
+ * (lodash `defaults` semantics).
7
+ */
8
+ function assignDefaults(target, source) {
9
+ for (const key of Object.keys(source)) {
10
+ if (target[key] === undefined) {
11
+ target[key] = source[key];
12
+ }
13
+ }
14
+ }
15
+ //# sourceMappingURL=object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.js","sourceRoot":"","sources":["../../../lib/utils/object.ts"],"names":[],"mappings":";;AAIA,wCASC;AAbD;;;GAGG;AACH,SAAgB,cAAc,CAC5B,MAAS,EACT,MAA+B;IAE/B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAkC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1,4 +1,3 @@
1
- import _ from 'lodash';
2
1
  import {errors} from 'appium/driver';
3
2
  import {APK_EXTENSION} from '../extensions';
4
3
  import type {AndroidUiautomator2Driver} from '../driver';
@@ -15,7 +14,7 @@ export async function mobileInstallMultipleApks(
15
14
  apks: string[],
16
15
  options?: InstallOptions,
17
16
  ): Promise<void> {
18
- if (!_.isArray(apks) || _.isEmpty(apks)) {
17
+ if (!Array.isArray(apks) || apks.length === 0) {
19
18
  throw new errors.InvalidArgumentError('No apks are given to install');
20
19
  }
21
20
  const configuredApks = await Promise.all(
@@ -1,5 +1,4 @@
1
1
  import {PROTOCOLS} from 'appium/driver';
2
- import _ from 'lodash';
3
2
  import type {DoSetElementValueOpts} from 'appium-android-driver';
4
3
  import type {Element as AppiumElement, Position, Rect, Size} from '@appium/types';
5
4
  import type {AndroidUiautomator2Driver} from '../driver';
@@ -130,7 +129,7 @@ export async function setValueImmediate(
130
129
  ): Promise<void> {
131
130
  await this.uiautomator2.jwproxy.command(`/element/${elementId}/value`, 'POST', {
132
131
  elementId,
133
- text: _.isArray(keys) ? keys.join('') : keys,
132
+ text: Array.isArray(keys) ? keys.join('') : keys,
134
133
  replace: false,
135
134
  });
136
135
  }
@@ -215,5 +214,5 @@ export async function mobileReplaceElementValue(
215
214
  }
216
215
 
217
216
  function toBool(value: any): boolean {
218
- return _.isString(value) ? value.toLowerCase() === 'true' : !!value;
217
+ return typeof value === 'string' ? value.toLowerCase() === 'true' : !!value;
219
218
  }
@@ -1,6 +1,5 @@
1
1
  import {errors} from 'appium/driver';
2
2
  import {util} from 'appium/support';
3
- import _ from 'lodash';
4
3
  import type {Element as AppiumElement, Position} from '@appium/types';
5
4
  import type {RelativeRect} from './types';
6
5
  import type {AndroidUiautomator2Driver} from '../driver';
@@ -288,7 +287,7 @@ function toOrigin(element?: AppiumElement | string): AppiumElement | undefined {
288
287
  }
289
288
 
290
289
  function toPoint(x?: number, y?: number): Partial<Position> | undefined {
291
- return _.isFinite(x) && _.isFinite(y) ? {x, y} : undefined;
290
+ return Number.isFinite(x) && Number.isFinite(y) ? {x, y} : undefined;
292
291
  }
293
292
 
294
293
  function toRect(
@@ -297,7 +296,7 @@ function toRect(
297
296
  width?: number,
298
297
  height?: number,
299
298
  ): RelativeRect | undefined {
300
- return [left, top, width, height].some((v) => !_.isFinite(v))
299
+ return [left, top, width, height].some((v) => !Number.isFinite(v))
301
300
  ? undefined
302
301
  : ({left, top, width, height} as RelativeRect);
303
302
  }
@@ -1,5 +1,3 @@
1
- import {errors} from 'appium/driver';
2
- import _ from 'lodash';
3
1
  import type {AndroidUiautomator2Driver} from '../driver';
4
2
  import type {SendKeysOpts} from 'appium-android-driver';
5
3
 
@@ -81,9 +79,6 @@ export async function mobileType(
81
79
  this: AndroidUiautomator2Driver,
82
80
  text: string | number | boolean,
83
81
  ): Promise<boolean> {
84
- if (_.isUndefined(text)) {
85
- throw new errors.InvalidArgumentError(`The 'text' argument is mandatory`);
86
- }
87
82
  return await this.settingsApp.typeUnicode(String(text));
88
83
  }
89
84
 
@@ -1,5 +1,5 @@
1
- import _ from 'lodash';
2
1
  import {imageUtil} from 'appium/support';
2
+ import {isEmpty} from '../utils';
3
3
  import type {AndroidUiautomator2Driver} from '../driver';
4
4
  import type {Screenshot} from './types';
5
5
  import type {StringRecord} from '@appium/types';
@@ -94,7 +94,7 @@ export async function mobileScreenshots(
94
94
  ): Promise<StringRecord<Screenshot>> {
95
95
  const displaysInfo = await this.adb.shell(['dumpsys', 'SurfaceFlinger', '--display-id']);
96
96
  const infos = parseSurfaceFlingerDisplays(displaysInfo);
97
- if (_.isEmpty(infos)) {
97
+ if (isEmpty(infos)) {
98
98
  this.log.debug(displaysInfo);
99
99
  throw new Error('Cannot determine the information about connected Android displays');
100
100
  }
@@ -104,7 +104,7 @@ export async function mobileScreenshots(
104
104
  (await this.adb.takeScreenshot(dispId)).toString('base64');
105
105
 
106
106
  const displayIdStr: string | null =
107
- _.isNil(displayId) || displayId === '' ? null : String(displayId);
107
+ displayId == null || displayId === '' ? null : String(displayId);
108
108
 
109
109
  if (displayIdStr) {
110
110
  if (!infos[displayIdStr]) {
@@ -121,13 +121,13 @@ export async function mobileScreenshots(
121
121
  };
122
122
  }
123
123
 
124
- const allInfos = _.values(infos).filter(
124
+ const allInfos = Object.values(infos).filter(
125
125
  (info): info is Partial<Screenshot> & {id: string} => !!info?.id,
126
126
  );
127
127
  const screenshots = await Promise.all(allInfos.map((info) => toB64Screenshot(info.id)));
128
- for (const [info, payload] of _.zip(allInfos, screenshots) as Array<
129
- [Partial<Screenshot>, string]
130
- >) {
128
+ for (let i = 0; i < allInfos.length; i++) {
129
+ const info = allInfos[i];
130
+ const payload = screenshots[i];
131
131
  if (info && payload) {
132
132
  info.payload = payload;
133
133
  }
@@ -1,4 +1,4 @@
1
- import {Rect, StringRecord} from '@appium/types';
1
+ import type {Rect, StringRecord} from '@appium/types';
2
2
 
3
3
  export type BatteryState = -1 | 1 | 2 | 3 | 4 | 5;
4
4
 
@@ -1,4 +1,4 @@
1
- import {Constraints} from '@appium/types';
1
+ import type {Constraints} from '@appium/types';
2
2
  import {commonCapConstraints} from 'appium-android-driver';
3
3
 
4
4
  const UIAUTOMATOR2_CONSTRAINTS = {
@@ -8,9 +8,9 @@ import type {
8
8
  AstSelector,
9
9
  AstTagName,
10
10
  } from 'css-selector-parser';
11
- import _ from 'lodash';
12
11
  import {errors} from 'appium/driver';
13
12
  import {log} from './logger';
13
+ import {escapeRegExp, isEmpty} from './utils';
14
14
 
15
15
  const parseCssSelector = createParser({
16
16
  syntax: {
@@ -100,7 +100,7 @@ export class CssConverter {
100
100
  private parseAttr(cssAttr: AstAttribute): string {
101
101
  const attrValueNode = cssAttr.value as {value?: string} | undefined;
102
102
  const attrValue = attrValueNode?.value;
103
- if (!_.isString(attrValue) && !_.isEmpty(attrValue)) {
103
+ if (typeof attrValue !== 'string' && !isEmpty(attrValue)) {
104
104
  throw new Error(
105
105
  `'${cssAttr.name}=${attrValue}' is an invalid attribute. Only 'string' and empty attribute types are supported. Found '${attrValue}'`,
106
106
  );
@@ -136,14 +136,14 @@ export class CssConverter {
136
136
  if (['description', 'text'].includes(attrName)) {
137
137
  return `.${methodName}Contains("${value}")`;
138
138
  }
139
- return `.${methodName}Matches("${_.escapeRegExp(value)}")`;
139
+ return `.${methodName}Matches("${escapeRegExp(value)}")`;
140
140
  case '^=':
141
141
  if (['description', 'text'].includes(attrName)) {
142
142
  return `.${methodName}StartsWith("${value}")`;
143
143
  }
144
- return `.${methodName}Matches("^${_.escapeRegExp(value)}")`;
144
+ return `.${methodName}Matches("^${escapeRegExp(value)}")`;
145
145
  case '$=':
146
- return `.${methodName}Matches("${_.escapeRegExp(value)}$")`;
146
+ return `.${methodName}Matches("${escapeRegExp(value)}$")`;
147
147
  case '~=':
148
148
  return `.${methodName}Matches("${getWordMatcherRegex(value)}")`;
149
149
  default:
@@ -155,7 +155,7 @@ export class CssConverter {
155
155
 
156
156
  private parsePseudo(cssPseudo: AstPseudoClass): string | undefined {
157
157
  const argValue = (cssPseudo.argument as {value?: string} | undefined)?.value;
158
- if (!_.isString(argValue) && !_.isEmpty(argValue)) {
158
+ if (typeof argValue !== 'string' && !isEmpty(argValue)) {
159
159
  throw new Error(
160
160
  `'${cssPseudo.name}=${argValue}'. Unsupported css pseudo class value: '${argValue}'. Only 'string' type or empty is supported.`,
161
161
  );
@@ -226,7 +226,7 @@ export class CssConverter {
226
226
  }
227
227
 
228
228
  private parseCssObject(css: AstSelector): string {
229
- if (!_.isEmpty(css.rules)) {
229
+ if (!isEmpty(css.rules)) {
230
230
  return this.parseCssRule(css.rules[0] as AstRule);
231
231
  }
232
232
 
@@ -247,7 +247,7 @@ function toSnakeCase(str?: string | null): string {
247
247
 
248
248
  function requireBoolean(css: AstAttribute | AstPseudoClass): 'true' | 'false' {
249
249
  const rawValue = (css as any).value?.value ?? (css as any).argument?.value;
250
- const value = _.toLower(rawValue ?? 'true');
250
+ const value = String(rawValue ?? 'true').toLowerCase();
251
251
  if (value === 'true') {
252
252
  return 'true';
253
253
  }
@@ -275,5 +275,5 @@ function requireEntityName(cssEntity: AstAttribute | AstPseudoClass): string {
275
275
  }
276
276
 
277
277
  function getWordMatcherRegex(word: string): string {
278
- return `\\b(\\w*${_.escapeRegExp(word)}\\w*)\\b`;
278
+ return `\\b(\\w*${escapeRegExp(word)}\\w*)\\b`;
279
279
  }