appium-uiautomator2-driver 2.42.2 → 2.43.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/lib/commands/actions.d.ts +22 -1
  3. package/build/lib/commands/actions.d.ts.map +1 -1
  4. package/build/lib/commands/actions.js +30 -62
  5. package/build/lib/commands/actions.js.map +1 -1
  6. package/build/lib/commands/alert.d.ts +28 -1
  7. package/build/lib/commands/alert.d.ts.map +1 -1
  8. package/build/lib/commands/alert.js +42 -23
  9. package/build/lib/commands/alert.js.map +1 -1
  10. package/build/lib/commands/app-management.d.ts +19 -0
  11. package/build/lib/commands/app-management.d.ts.map +1 -0
  12. package/build/lib/commands/app-management.js +45 -0
  13. package/build/lib/commands/app-management.js.map +1 -0
  14. package/build/lib/commands/app-strings.d.ts +9 -0
  15. package/build/lib/commands/app-strings.d.ts.map +1 -1
  16. package/build/lib/commands/app-strings.js +11 -79
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/battery.d.ts +7 -0
  19. package/build/lib/commands/battery.d.ts.map +1 -1
  20. package/build/lib/commands/battery.js +14 -20
  21. package/build/lib/commands/battery.js.map +1 -1
  22. package/build/lib/commands/element.d.ts +100 -1
  23. package/build/lib/commands/element.d.ts.map +1 -1
  24. package/build/lib/commands/element.js +175 -125
  25. package/build/lib/commands/element.js.map +1 -1
  26. package/build/lib/commands/execute.d.ts +25 -0
  27. package/build/lib/commands/execute.d.ts.map +1 -0
  28. package/build/lib/commands/execute.js +109 -0
  29. package/build/lib/commands/execute.js.map +1 -0
  30. package/build/lib/commands/find.d.ts +10 -0
  31. package/build/lib/commands/find.d.ts.map +1 -1
  32. package/build/lib/commands/find.js +25 -27
  33. package/build/lib/commands/find.js.map +1 -1
  34. package/build/lib/commands/gestures.d.ts +103 -1
  35. package/build/lib/commands/gestures.d.ts.map +1 -1
  36. package/build/lib/commands/gestures.js +202 -173
  37. package/build/lib/commands/gestures.js.map +1 -1
  38. package/build/lib/commands/keyboard.d.ts +47 -0
  39. package/build/lib/commands/keyboard.d.ts.map +1 -0
  40. package/build/lib/commands/keyboard.js +92 -0
  41. package/build/lib/commands/keyboard.js.map +1 -0
  42. package/build/lib/commands/misc.d.ts +48 -0
  43. package/build/lib/commands/misc.d.ts.map +1 -0
  44. package/build/lib/commands/misc.js +75 -0
  45. package/build/lib/commands/misc.js.map +1 -0
  46. package/build/lib/commands/navigation.d.ts +20 -0
  47. package/build/lib/commands/navigation.d.ts.map +1 -0
  48. package/build/lib/commands/navigation.js +35 -0
  49. package/build/lib/commands/navigation.js.map +1 -0
  50. package/build/lib/commands/screenshot.d.ts +24 -1
  51. package/build/lib/commands/screenshot.d.ts.map +1 -1
  52. package/build/lib/commands/screenshot.js +87 -64
  53. package/build/lib/commands/screenshot.js.map +1 -1
  54. package/build/lib/commands/touch.d.ts +81 -0
  55. package/build/lib/commands/touch.d.ts.map +1 -1
  56. package/build/lib/commands/touch.js +158 -41
  57. package/build/lib/commands/touch.js.map +1 -1
  58. package/build/lib/commands/viewport.d.ts +37 -1
  59. package/build/lib/commands/viewport.d.ts.map +1 -1
  60. package/build/lib/commands/viewport.js +80 -36
  61. package/build/lib/commands/viewport.js.map +1 -1
  62. package/build/lib/driver.d.ts +94 -24
  63. package/build/lib/driver.d.ts.map +1 -1
  64. package/build/lib/driver.js +114 -28
  65. package/build/lib/driver.js.map +1 -1
  66. package/build/lib/helpers.d.ts +12 -6
  67. package/build/lib/helpers.d.ts.map +1 -1
  68. package/build/lib/helpers.js +18 -18
  69. package/build/lib/helpers.js.map +1 -1
  70. package/build/lib/method-map.d.ts +0 -23
  71. package/build/lib/method-map.d.ts.map +1 -1
  72. package/build/lib/uiautomator2.js +3 -3
  73. package/build/lib/uiautomator2.js.map +1 -1
  74. package/build/tsconfig.tsbuildinfo +1 -1
  75. package/lib/commands/actions.js +37 -114
  76. package/lib/commands/alert.js +51 -37
  77. package/lib/commands/app-management.js +42 -0
  78. package/lib/commands/app-strings.js +9 -89
  79. package/lib/commands/battery.js +16 -26
  80. package/lib/commands/element.js +235 -214
  81. package/lib/commands/execute.js +120 -0
  82. package/lib/commands/find.js +31 -37
  83. package/lib/commands/gestures.js +252 -234
  84. package/lib/commands/keyboard.js +103 -0
  85. package/lib/commands/misc.js +106 -0
  86. package/lib/commands/navigation.js +31 -0
  87. package/lib/commands/screenshot.js +96 -77
  88. package/lib/commands/touch.js +190 -48
  89. package/lib/commands/viewport.js +100 -50
  90. package/lib/driver.ts +225 -36
  91. package/lib/helpers.js +15 -22
  92. package/lib/uiautomator2.js +3 -3
  93. package/npm-shrinkwrap.json +34 -34
  94. package/package.json +2 -2
  95. package/build/lib/commands/general.d.ts +0 -4
  96. package/build/lib/commands/general.d.ts.map +0 -1
  97. package/build/lib/commands/general.js +0 -214
  98. package/build/lib/commands/general.js.map +0 -1
  99. package/build/lib/commands/index.d.ts +0 -2
  100. package/build/lib/commands/index.d.ts.map +0 -1
  101. package/build/lib/commands/index.js +0 -14
  102. package/build/lib/commands/index.js.map +0 -1
  103. package/build/lib/commands/mixins.d.ts +0 -87
  104. package/build/lib/commands/mixins.d.ts.map +0 -1
  105. package/build/lib/commands/mixins.js +0 -26
  106. package/build/lib/commands/mixins.js.map +0 -1
  107. package/build/lib/utils.d.ts +0 -10
  108. package/build/lib/utils.d.ts.map +0 -1
  109. package/build/lib/utils.js +0 -26
  110. package/build/lib/utils.js.map +0 -1
  111. package/lib/commands/general.js +0 -289
  112. package/lib/commands/index.js +0 -11
  113. package/lib/commands/mixins.ts +0 -169
  114. package/lib/utils.js +0 -19
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @this {AndroidUiautomator2Driver}
3
+ * @returns {Promise<string>}
4
+ */
5
+ export async function getPageSource() {
6
+ return String(
7
+ await this.uiautomator2.jwproxy.command(
8
+ '/source',
9
+ 'GET',
10
+ {}
11
+ )
12
+ );
13
+ }
14
+
15
+ /**
16
+ * @this {AndroidUiautomator2Driver}
17
+ * @returns {Promise<import('@appium/types').Orientation>}
18
+ */
19
+ export async function getOrientation() {
20
+ return /** @type {import('@appium/types').Orientation} */ (
21
+ await this.uiautomator2.jwproxy.command(
22
+ `/orientation`,
23
+ 'GET',
24
+ {}
25
+ )
26
+ );
27
+ }
28
+
29
+ /**
30
+ * @this {AndroidUiautomator2Driver}
31
+ * @param {import('@appium/types').Orientation} orientation
32
+ * @returns {Promise<void>}
33
+ */
34
+ export async function setOrientation(orientation) {
35
+ orientation = /** @type {import('@appium/types').Orientation} */ (orientation.toUpperCase());
36
+ await this.uiautomator2.jwproxy.command(
37
+ `/orientation`,
38
+ 'POST',
39
+ {orientation}
40
+ );
41
+ }
42
+
43
+ /**
44
+ * @this {AndroidUiautomator2Driver}
45
+ * @returns {Promise<string>}
46
+ */
47
+ export async function getClipboard() {
48
+ return String(
49
+ (await this.adb.getApiLevel()) < 29
50
+ ? await this.uiautomator2.jwproxy.command(
51
+ '/appium/device/get_clipboard',
52
+ 'POST',
53
+ {}
54
+ )
55
+ : await this.settingsApp.getClipboard()
56
+ );
57
+ }
58
+
59
+ /**
60
+ * @this {AndroidUiautomator2Driver}
61
+ * @returns {Promise<void>}
62
+ */
63
+ export async function openNotifications() {
64
+ await this.uiautomator2.jwproxy.command(
65
+ '/appium/device/open_notifications',
66
+ 'POST',
67
+ {}
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Stop proxying to any Chromedriver and redirect to uiautomator2
73
+ * @this {AndroidUiautomator2Driver}
74
+ * @returns {void}
75
+ */
76
+ export function suspendChromedriverProxy() {
77
+ this.chromedriver = undefined;
78
+ this.proxyReqRes = this.uiautomator2.proxyReqRes.bind(
79
+ this.uiautomator2
80
+ );
81
+ this.proxyCommand = /** @type {typeof this.proxyCommand} */ (
82
+ this.uiautomator2.proxyCommand.bind(this.uiautomator2)
83
+ );
84
+ this.jwpProxyActive = true;
85
+ }
86
+
87
+ /**
88
+ * The list of available info entries can be found at
89
+ * https://github.com/appium/appium-uiautomator2-server/blob/master/app/src/main/java/io/appium/uiautomator2/handler/GetDeviceInfo.java
90
+ * @this {AndroidUiautomator2Driver}
91
+ * @returns {Promise<StringRecord>}
92
+ */
93
+ export async function mobileGetDeviceInfo() {
94
+ return /** @type {StringRecord} */ (
95
+ await this.uiautomator2.jwproxy.command(
96
+ '/appium/device/info',
97
+ 'GET'
98
+ )
99
+ );
100
+ }
101
+
102
+ /**
103
+ * @template [T=any]
104
+ * @typedef {import('@appium/types').StringRecord<T>} StringRecord
105
+ * @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
106
+ */
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @this {AndroidUiautomator2Driver}
3
+ * @param {string} url
4
+ * @returns {Promise<void>}
5
+ */
6
+ export async function setUrl(url) {
7
+ await this.adb.startUri(url, /** @type {string} */ (this.opts.appPackage));
8
+ }
9
+
10
+ /**
11
+ * Start URL that take users directly to specific content in the app
12
+ * @this {AndroidUiautomator2Driver}
13
+ * @param {import('./types').DeepLinkOpts} opts
14
+ * @returns {Promise<void>}
15
+ */
16
+ export async function mobileDeepLink(opts) {
17
+ const {url, package: pkg, waitForLaunch} = opts;
18
+ return await this.adb.startUri(url, pkg, {waitForLaunch});
19
+ }
20
+
21
+ /**
22
+ * @this {AndroidUiautomator2Driver}
23
+ * @returns {Promise<void>}
24
+ */
25
+ export async function back() {
26
+ await this.adb.keyevent(4);
27
+ }
28
+
29
+ /**
30
+ * @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
31
+ */
@@ -1,95 +1,114 @@
1
- // @ts-check
2
-
3
- import {mixin} from './mixins';
4
1
  import _ from 'lodash';
5
2
  import B from 'bluebird';
3
+ import {imageUtil} from 'appium/support';
6
4
 
7
5
  // Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0"
8
6
  const DISPLAY_PATTERN = /^Display\s+(\d+)\s+\(.+display\s+(\d+)\).+displayName="([^"]*)/gm;
9
7
 
10
8
  /**
11
- * @type {import('./mixins').UIA2ScreenshotMixin}
12
- * @satisfies {import('@appium/types').ExternalDriver}
9
+ * @this {AndroidUiautomator2Driver}
10
+ * @returns {Promise<string>}
13
11
  */
14
- const ScreenshotMixin = {
15
- async getScreenshot() {
16
- if (this.mjpegStream) {
17
- const data = await this.mjpegStream.lastChunkPNGBase64();
18
- if (data) {
19
- return data;
20
- }
21
- this.log.warn(
22
- 'Tried to get screenshot from active MJPEG stream, but there ' +
23
- 'was no data yet. Falling back to regular screenshot methods.'
24
- );
12
+ export async function mobileViewportScreenshot() {
13
+ return await this.getViewportScreenshot();
14
+ }
15
+
16
+ /**
17
+ * @this {AndroidUiautomator2Driver}
18
+ * @returns {Promise<string>}
19
+ */
20
+ export async function getViewportScreenshot() {
21
+ const screenshot = await this.getScreenshot();
22
+ const rect = await this.getViewPortRect();
23
+ return await imageUtil.cropBase64Image(screenshot, rect);
24
+ }
25
+
26
+ /**
27
+ * @this {AndroidUiautomator2Driver}
28
+ * @returns {Promise<string>}
29
+ */
30
+ export async function getScreenshot() {
31
+ if (this.mjpegStream) {
32
+ const data = await this.mjpegStream.lastChunkPNGBase64();
33
+ if (data) {
34
+ return data;
25
35
  }
26
- return String(
27
- await /** @type {import('../uiautomator2').UiAutomator2Server} */ (
28
- this.uiautomator2
29
- ).jwproxy.command('/screenshot', 'GET')
36
+ this.log.warn(
37
+ 'Tried to get screenshot from active MJPEG stream, but there ' +
38
+ 'was no data yet. Falling back to regular screenshot methods.'
30
39
  );
31
- },
40
+ }
41
+ return String(
42
+ await /** @type {import('../uiautomator2').UiAutomator2Server} */ (
43
+ this.uiautomator2
44
+ ).jwproxy.command('/screenshot', 'GET')
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Retrieves screenshots of each display available to Android.
50
+ * This functionality is only supported since Android 10.
51
+ * @this {AndroidUiautomator2Driver}
52
+ * @param {import('./types').ScreenshotsOpts} [opts={}]
53
+ * @returns {Promise<import('@appium/types').StringRecord<import('./types').Screenshot>>}
54
+ */
55
+ export async function mobileScreenshots(opts = {}) {
56
+ const displaysInfo = await /** @type {import('appium-adb').ADB} */ (this.adb).shell([
57
+ 'dumpsys',
58
+ 'SurfaceFlinger',
59
+ '--display-id',
60
+ ]);
61
+ /** @type {import('@appium/types').StringRecord<import('./types').Screenshot>} */
62
+ const infos = {};
63
+ let match;
64
+ while ((match = DISPLAY_PATTERN.exec(displaysInfo))) {
65
+ infos[match[1]] = /** @type {any} */ ({
66
+ id: match[1],
67
+ isDefault: match[2] === '0',
68
+ name: match[3],
69
+ });
70
+ }
71
+ if (_.isEmpty(infos)) {
72
+ this.log.debug(displaysInfo);
73
+ throw new Error('Cannot determine the information about connected Android displays');
74
+ }
75
+ this.log.info(`Parsed Android display infos: ${JSON.stringify(infos)}`);
32
76
 
33
77
  /**
34
- * Retrieves screenshots of each display available to Android.
35
- * This functionality is only supported since Android 10.
78
+ * @param {string} dispId
36
79
  */
37
- async mobileScreenshots(opts = {}) {
38
- const displaysInfo = await /** @type {import('appium-adb').ADB} */ (this.adb).shell([
39
- 'dumpsys',
40
- 'SurfaceFlinger',
41
- '--display-id',
42
- ]);
43
- /** @type {import('@appium/types').StringRecord<import('./types').Screenshot>} */
44
- const infos = {};
45
- let match;
46
- while ((match = DISPLAY_PATTERN.exec(displaysInfo))) {
47
- infos[match[1]] = /** @type {any} */ ({
48
- id: match[1],
49
- isDefault: match[2] === '0',
50
- name: match[3],
51
- });
52
- }
53
- if (_.isEmpty(infos)) {
54
- this.log.debug(displaysInfo);
55
- throw new Error('Cannot determine the information about connected Android displays');
56
- }
57
- this.log.info(`Parsed Android display infos: ${JSON.stringify(infos)}`);
80
+ const toB64Screenshot = async (dispId) =>
81
+ (await /** @type {import('appium-adb').ADB} */ (this.adb).takeScreenshot(dispId)).toString(
82
+ 'base64'
83
+ );
58
84
 
59
- /**
60
- * @param {string} dispId
61
- */
62
- const toB64Screenshot = async (dispId) =>
63
- (await /** @type {import('appium-adb').ADB} */ (this.adb).takeScreenshot(dispId)).toString(
64
- 'base64'
85
+ const {displayId} = opts;
86
+ const displayIdStr = _.isNaN(displayId) ? null : `${displayId}`;
87
+ if (displayIdStr) {
88
+ if (!infos[displayIdStr]) {
89
+ throw new Error(
90
+ `The provided display identifier '${displayId}' is not known. ` +
91
+ `Only the following displays have been detected: ${JSON.stringify(infos)}`
65
92
  );
66
-
67
- const {displayId} = opts;
68
- const displayIdStr = _.isNaN(displayId) ? null : `${displayId}`;
69
- if (displayIdStr) {
70
- if (!infos[displayIdStr]) {
71
- throw new Error(
72
- `The provided display identifier '${displayId}' is not known. ` +
73
- `Only the following displays have been detected: ${JSON.stringify(infos)}`
74
- );
75
- }
76
- return {
77
- [displayIdStr]: {
78
- ...infos[displayIdStr],
79
- payload: await toB64Screenshot(displayIdStr),
80
- },
81
- };
82
93
  }
94
+ return {
95
+ [displayIdStr]: {
96
+ ...infos[displayIdStr],
97
+ payload: await toB64Screenshot(displayIdStr),
98
+ },
99
+ };
100
+ }
83
101
 
84
- const allInfos = _.values(infos);
85
- const screenshots = await B.all(allInfos.map(({id}) => toB64Screenshot(id)));
86
- for (const [info, payload] of /** @type {[import('./types').Screenshot, string][]} */ (
87
- _.zip(allInfos, screenshots)
88
- )) {
89
- info.payload = payload;
90
- }
91
- return infos;
92
- },
93
- };
102
+ const allInfos = _.values(infos);
103
+ const screenshots = await B.all(allInfos.map(({id}) => toB64Screenshot(id)));
104
+ for (const [info, payload] of /** @type {[import('./types').Screenshot, string][]} */ (
105
+ _.zip(allInfos, screenshots)
106
+ )) {
107
+ info.payload = payload;
108
+ }
109
+ return infos;
110
+ }
94
111
 
95
- mixin(ScreenshotMixin);
112
+ /**
113
+ * @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
114
+ */
@@ -1,71 +1,213 @@
1
- // @ts-check
1
+ import { util } from 'appium/support';
2
+ import { W3C_ELEMENT_KEY } from 'appium/driver';
2
3
 
3
- import {mixin} from './mixins';
4
+ /**
5
+ * @deprecated
6
+ * @this {AndroidUiautomator2Driver}
7
+ * @param {import('appium-android-driver').SwipeOpts} swipeOpts
8
+ * @returns {Promise<void>}
9
+ */
10
+ export async function doSwipe(swipeOpts) {
11
+ await this.uiautomator2.jwproxy.command(
12
+ `/touch/perform`,
13
+ 'POST',
14
+ swipeOpts
15
+ );
16
+ }
17
+
18
+ /**
19
+ * @deprecated
20
+ * @this {AndroidUiautomator2Driver}
21
+ * @param {import('appium-android-driver').DragOpts} dragOpts
22
+ * @returns {Promise<void>}
23
+ */
24
+ export async function doDrag(dragOpts) {
25
+ await this.uiautomator2.jwproxy.command(
26
+ `/touch/drag`,
27
+ 'POST',
28
+ dragOpts
29
+ );
30
+ }
31
+
32
+ /**
33
+ * @deprecated
34
+ * @this {AndroidUiautomator2Driver}
35
+ * @param {string} element
36
+ * @param {number} x
37
+ * @param {number} y
38
+ * @param {number} duration
39
+ * @returns {Promise<void>}
40
+ */
41
+ export async function touchLongClick(element, x, y, duration) {
42
+ let params = {element, x, y, duration};
43
+ await this.uiautomator2.jwproxy.command(
44
+ `/touch/longclick`,
45
+ 'POST',
46
+ {params}
47
+ );
48
+ }
49
+
50
+ /**
51
+ * @deprecated
52
+ * @this {AndroidUiautomator2Driver}
53
+ * @param {string} element
54
+ * @param {number} x
55
+ * @param {number} y
56
+ * @returns {Promise<void>}
57
+ */
58
+ export async function touchDown(element, x, y) {
59
+ let params = {element, x, y};
60
+ await this.uiautomator2.jwproxy.command(
61
+ `/touch/down`,
62
+ 'POST',
63
+ {params}
64
+ );
65
+ }
66
+
67
+ /**
68
+ * @deprecated
69
+ * @this {AndroidUiautomator2Driver}
70
+ * @param {string} element
71
+ * @param {number} x
72
+ * @param {number} y
73
+ * @returns {Promise<void>}
74
+ */
75
+ export async function touchUp(element, x, y) {
76
+ let params = {element, x, y};
77
+ await this.uiautomator2.jwproxy.command(
78
+ `/touch/up`,
79
+ 'POST',
80
+ {params}
81
+ );
82
+ }
4
83
 
5
84
  /**
6
- * @type {import('./mixins').UIA2TouchMixin}
7
- * @satisfies {import('@appium/types').ExternalDriver}
85
+ * @deprecated
86
+ * @this {AndroidUiautomator2Driver}
87
+ * @param {string} element
88
+ * @param {number} x
89
+ * @param {number} y
90
+ * @returns {Promise<void>}
8
91
  */
9
- const TouchMixin = {
10
- async doPerformMultiAction(elementId, states) {
11
- let opts;
12
- if (elementId) {
13
- opts = {
14
- elementId,
15
- actions: states,
16
- };
92
+ export async function touchMove(element, x, y) {
93
+ let params = {element, x, y};
94
+ await this.uiautomator2.jwproxy.command(
95
+ `/touch/move`,
96
+ 'POST',
97
+ {params}
98
+ );
99
+ }
17
100
 
101
+ /**
102
+ * @deprecated
103
+ * @this {AndroidUiautomator2Driver}
104
+ * @param {string?} [elementId=null]
105
+ * @param {number?} [x=null]
106
+ * @param {number?} [y=null]
107
+ * @param {number} [count=1]
108
+ * @returns {Promise<void>}
109
+ */
110
+ export async function tap(elementId = null, x = null, y = null, count = 1) {
111
+ const areCoordinatesDefined = util.hasValue(x) && util.hasValue(y);
112
+ if (!util.hasValue(elementId) && !areCoordinatesDefined) {
113
+ throw new Error(`Either element id to tap or both absolute coordinates should be defined`);
114
+ }
115
+
116
+ for (let i = 0; i < count; i++) {
117
+ if (util.hasValue(elementId) && !areCoordinatesDefined) {
118
+ // we are either tapping on the default location of the element
119
+ // or an offset from the top left corner
18
120
  await this.uiautomator2.jwproxy.command(
19
- '/touch/multi/perform',
20
- 'POST',
21
- opts
121
+ `/element/${elementId}/click`,
122
+ 'POST'
22
123
  );
23
124
  } else {
24
- opts = {
25
- actions: states,
26
- };
27
125
  await this.uiautomator2.jwproxy.command(
28
- '/touch/multi/perform',
126
+ `/appium/tap`,
29
127
  'POST',
30
- opts
128
+ {
129
+ x,
130
+ y,
131
+ [W3C_ELEMENT_KEY]: elementId,
132
+ }
31
133
  );
32
134
  }
33
- },
135
+ }
136
+ }
137
+
138
+ /**
139
+ * @deprecated
140
+ * @this {AndroidUiautomator2Driver}
141
+ * @param {string} elementId
142
+ * @param {import('appium-android-driver').TouchState[]} states
143
+ * @returns {Promise<void>}
144
+ */
145
+ export async function doPerformMultiAction(elementId, states) {
146
+ let opts;
147
+ if (elementId) {
148
+ opts = {
149
+ elementId,
150
+ actions: states,
151
+ };
34
152
 
35
- async performActions(actions) {
36
- this.log.debug(`Received the following W3C actions: ${JSON.stringify(actions, null, ' ')}`);
37
- // This is mandatory, since Selenium API uses MOUSE as the default pointer type
38
- const preprocessedActions = actions.map((action) =>
39
- Object.assign(
40
- {},
41
- action,
42
- action.type === 'pointer'
43
- ? {
44
- parameters: {
45
- pointerType: 'touch',
46
- },
47
- }
48
- : {}
49
- )
153
+ await this.uiautomator2.jwproxy.command(
154
+ '/touch/multi/perform',
155
+ 'POST',
156
+ opts
50
157
  );
51
- this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
158
+ } else {
159
+ opts = {
160
+ actions: states,
161
+ };
52
162
  await this.uiautomator2.jwproxy.command(
53
- '/actions',
163
+ '/touch/multi/perform',
54
164
  'POST',
55
- {
56
- actions: preprocessedActions,
57
- }
165
+ opts
58
166
  );
59
- },
167
+ }
168
+ }
60
169
 
61
- // eslint-disable-next-line require-await
62
- async releaseActions() {
63
- this.log.info('On this platform, releaseActions is a no-op');
64
- },
65
- };
170
+ /**
171
+ * @this {AndroidUiautomator2Driver}
172
+ * @param {import('@appium/types').StringRecord} actions
173
+ * @returns {Promise<void>}
174
+ */
175
+ export async function performActions(actions) {
176
+ this.log.debug(`Received the following W3C actions: ${JSON.stringify(actions, null, ' ')}`);
177
+ // This is mandatory, since Selenium API uses MOUSE as the default pointer type
178
+ const preprocessedActions = actions.map((action) =>
179
+ Object.assign(
180
+ {},
181
+ action,
182
+ action.type === 'pointer'
183
+ ? {
184
+ parameters: {
185
+ pointerType: 'touch',
186
+ },
187
+ }
188
+ : {}
189
+ )
190
+ );
191
+ this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
192
+ await this.uiautomator2.jwproxy.command(
193
+ '/actions',
194
+ 'POST',
195
+ {
196
+ actions: preprocessedActions,
197
+ }
198
+ );
199
+ }
66
200
 
67
- mixin(TouchMixin);
201
+ /**
202
+ * @this {AndroidUiautomator2Driver}
203
+ * @returns {Promise<void>}
204
+ */
205
+ // eslint-disable-next-line require-await
206
+ export async function releaseActions() {
207
+ this.log.info('On this platform, releaseActions is a no-op');
208
+ }
68
209
 
69
210
  /**
70
211
  * @typedef {import('../uiautomator2').UiAutomator2Server} UiAutomator2Server
212
+ * @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
71
213
  */