appium-uiautomator2-driver 2.29.11 → 2.31.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.
- package/CHANGELOG.md +14 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +8 -15
- package/build/index.js.map +1 -0
- package/build/lib/commands/actions.d.ts +2 -0
- package/build/lib/commands/actions.d.ts.map +1 -0
- package/build/lib/commands/actions.js +67 -62
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts +2 -0
- package/build/lib/commands/alert.d.ts.map +1 -0
- package/build/lib/commands/alert.js +28 -26
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-strings.d.ts +3 -0
- package/build/lib/commands/app-strings.d.ts.map +1 -0
- package/build/lib/commands/app-strings.js +86 -57
- package/build/lib/commands/app-strings.js.map +1 -1
- package/build/lib/commands/battery.d.ts +2 -0
- package/build/lib/commands/battery.d.ts.map +1 -0
- package/build/lib/commands/battery.js +26 -16
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/element.d.ts +2 -0
- package/build/lib/commands/element.d.ts.map +1 -0
- package/build/lib/commands/element.js +140 -159
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/find.d.ts +2 -0
- package/build/lib/commands/find.d.ts.map +1 -0
- package/build/lib/commands/find.js +39 -25
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +4 -0
- package/build/lib/commands/general.d.ts.map +1 -0
- package/build/lib/commands/general.js +209 -215
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/gestures.d.ts +2 -0
- package/build/lib/commands/gestures.d.ts.map +1 -0
- package/build/lib/commands/gestures.js +206 -193
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/index.d.ts +2 -0
- package/build/lib/commands/index.d.ts.map +1 -0
- package/build/lib/commands/index.js +13 -22
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/mixins.d.ts +87 -0
- package/build/lib/commands/mixins.d.ts.map +1 -0
- package/build/lib/commands/mixins.js +26 -0
- package/build/lib/commands/mixins.js.map +1 -0
- package/build/lib/commands/screenshot.d.ts +2 -0
- package/build/lib/commands/screenshot.d.ts.map +1 -0
- package/build/lib/commands/screenshot.js +77 -62
- package/build/lib/commands/screenshot.js.map +1 -1
- package/build/lib/commands/touch.d.ts +2 -0
- package/build/lib/commands/touch.d.ts.map +1 -0
- package/build/lib/commands/touch.js +48 -38
- package/build/lib/commands/touch.js.map +1 -1
- package/build/lib/commands/types.d.ts +452 -0
- package/build/lib/commands/types.d.ts.map +1 -0
- package/build/lib/commands/types.js +3 -0
- package/build/lib/commands/types.js.map +1 -0
- package/build/lib/commands/viewport.d.ts +2 -0
- package/build/lib/commands/viewport.d.ts.map +1 -0
- package/build/lib/commands/viewport.js +37 -35
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/lib/constraints.d.ts +325 -0
- package/build/lib/constraints.d.ts.map +1 -0
- package/build/lib/constraints.js +51 -0
- package/build/lib/constraints.js.map +1 -0
- package/build/lib/css-converter.d.ts +45 -0
- package/build/lib/css-converter.d.ts.map +1 -0
- package/build/lib/css-converter.js +272 -175
- package/build/lib/css-converter.js.map +1 -1
- package/build/lib/driver.d.ts +904 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +726 -485
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts +477 -0
- package/build/lib/execute-method-map.d.ts.map +1 -0
- package/build/lib/execute-method-map.js +542 -0
- package/build/lib/execute-method-map.js.map +1 -0
- package/build/lib/extensions.d.ts +3 -0
- package/build/lib/extensions.d.ts.map +1 -0
- package/build/lib/extensions.js +7 -9
- package/build/lib/extensions.js.map +1 -1
- package/build/lib/helpers.d.ts +7 -0
- package/build/lib/helpers.d.ts.map +1 -0
- package/build/lib/helpers.js +36 -29
- package/build/lib/helpers.js.map +1 -1
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -10
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.d.ts +389 -0
- package/build/lib/method-map.d.ts.map +1 -0
- package/build/lib/method-map.js +11 -17
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/types.d.ts +44 -0
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/types.js +3 -0
- package/build/lib/types.js.map +1 -0
- package/build/lib/uiautomator2.d.ts +45 -0
- package/build/lib/uiautomator2.d.ts.map +1 -0
- package/build/lib/uiautomator2.js +340 -299
- package/build/lib/uiautomator2.js.map +1 -1
- package/build/lib/utils.d.ts +10 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +23 -16
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -0
- package/index.js +5 -3
- package/lib/commands/actions.js +115 -101
- package/lib/commands/alert.js +36 -44
- package/lib/commands/app-strings.js +79 -58
- package/lib/commands/battery.js +27 -28
- package/lib/commands/element.js +231 -134
- package/lib/commands/find.js +40 -21
- package/lib/commands/general.js +262 -336
- package/lib/commands/gestures.js +252 -366
- package/lib/commands/index.js +11 -31
- package/lib/commands/mixins.ts +169 -0
- package/lib/commands/screenshot.js +80 -76
- package/lib/commands/touch.js +64 -31
- package/lib/commands/types.ts +473 -0
- package/lib/commands/viewport.js +43 -31
- package/lib/constraints.ts +53 -0
- package/lib/css-converter.js +9 -1
- package/lib/{driver.js → driver.ts} +374 -239
- package/lib/execute-method-map.ts +573 -0
- package/lib/method-map.ts +11 -0
- package/lib/types.ts +57 -0
- package/lib/uiautomator2.js +21 -2
- package/lib/utils.js +2 -2
- package/npm-shrinkwrap.json +395 -528
- package/package.json +96 -70
- package/build/lib/desired-caps.js +0 -71
- package/build/lib/desired-caps.js.map +0 -1
- package/lib/desired-caps.js +0 -70
- package/lib/method-map.js +0 -11
package/lib/commands/index.js
CHANGED
|
@@ -1,31 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
let commands = {};
|
|
14
|
-
Object.assign(
|
|
15
|
-
commands,
|
|
16
|
-
alertCmds,
|
|
17
|
-
findCmds,
|
|
18
|
-
generalCmds,
|
|
19
|
-
touchCmds,
|
|
20
|
-
actionsCmds,
|
|
21
|
-
elementCmds,
|
|
22
|
-
viewportCmds,
|
|
23
|
-
screenshotCmds,
|
|
24
|
-
batteryCmds,
|
|
25
|
-
gesturesCmds,
|
|
26
|
-
appStringsCmds,
|
|
27
|
-
// add other command types here
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
export default commands;
|
|
31
|
-
|
|
1
|
+
import './alert';
|
|
2
|
+
import './find';
|
|
3
|
+
import './general';
|
|
4
|
+
import './touch';
|
|
5
|
+
import './element';
|
|
6
|
+
import './actions';
|
|
7
|
+
import './viewport';
|
|
8
|
+
import './screenshot';
|
|
9
|
+
import './battery';
|
|
10
|
+
import './gestures';
|
|
11
|
+
import './app-strings';
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* @privateRemarks These mixins are kind of a mishmash of stuff from `appium-android-driver`,
|
|
4
|
+
* @privateRemarks unique things, and stuff from `ExternalDriver`. Ideally, we should be pulling the method
|
|
5
|
+
* @privateRemarks definitions right out of `ExternalDriver` whenever possible. Also note that the mixins
|
|
6
|
+
* @privateRemarks contain _more stuff than just commands or execute methods_.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {Element, ExternalDriver, StringRecord} from '@appium/types';
|
|
10
|
+
import type {
|
|
11
|
+
ActionsMixin,
|
|
12
|
+
AlertMixin,
|
|
13
|
+
ElementMixin,
|
|
14
|
+
ExecuteMixin,
|
|
15
|
+
FindMixin,
|
|
16
|
+
GeneralMixin,
|
|
17
|
+
NetworkMixin,
|
|
18
|
+
TouchMixin,
|
|
19
|
+
} from 'appium-android-driver';
|
|
20
|
+
import type {EmptyObject} from 'type-fest';
|
|
21
|
+
import {AndroidUiautomator2Driver} from '../driver';
|
|
22
|
+
import type * as types from './types';
|
|
23
|
+
|
|
24
|
+
type UIA2Mixin<T = EmptyObject> = ThisType<import('../driver').AndroidUiautomator2Driver> & T;
|
|
25
|
+
|
|
26
|
+
export type UIA2ActionsMixin = UIA2Mixin<
|
|
27
|
+
Pick<
|
|
28
|
+
ActionsMixin,
|
|
29
|
+
'pressKeyCode' | 'longPressKeyCode' | 'doSwipe' | 'doDrag' | 'getOrientation' | 'setOrientation'
|
|
30
|
+
>
|
|
31
|
+
> & {
|
|
32
|
+
mobilePressKey(opts: types.PressKeyOptions): Promise<void>;
|
|
33
|
+
mobileScheduleAction(opts?: StringRecord): Promise<unknown>;
|
|
34
|
+
mobileGetActionHistory(opts?: types.ActionArgs): Promise<types.ActionResult>;
|
|
35
|
+
mobileUnscheduleAction(opts?: types.ActionArgs): Promise<unknown>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type UIA2AlertMixin = UIA2Mixin<
|
|
39
|
+
Pick<AlertMixin, 'getAlertText' | 'postAcceptAlert' | 'postDismissAlert'>
|
|
40
|
+
> & {
|
|
41
|
+
mobileAcceptAlert(opts?: types.AcceptAlertOptions): Promise<void>;
|
|
42
|
+
mobileDismissAlert(opts?: types.DismissAlertOptions): Promise<void>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type UIA2AppStringsMixin = UIA2Mixin<Pick<GeneralMixin, 'getStrings'>> & {
|
|
46
|
+
mobileGetAppStrings(opts?: types.GetAppStringsOptions): Promise<StringRecord>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type UIA2BatteryMixin = UIA2Mixin & {
|
|
50
|
+
mobileGetBatteryInfo(): Promise<types.BatteryInfo>;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type UIA2ElementMixin = UIA2Mixin<
|
|
54
|
+
Pick<
|
|
55
|
+
ElementMixin,
|
|
56
|
+
| 'getAttribute'
|
|
57
|
+
| 'elementDisplayed'
|
|
58
|
+
| 'elementEnabled'
|
|
59
|
+
| 'elementSelected'
|
|
60
|
+
| 'getName'
|
|
61
|
+
| 'getLocation'
|
|
62
|
+
| 'getSize'
|
|
63
|
+
| 'touchLongClick'
|
|
64
|
+
| 'touchDown'
|
|
65
|
+
| 'touchUp'
|
|
66
|
+
| 'touchMove'
|
|
67
|
+
| 'doSetElementValue'
|
|
68
|
+
| 'setValueImmediate'
|
|
69
|
+
| 'getText'
|
|
70
|
+
| 'click'
|
|
71
|
+
| 'tap'
|
|
72
|
+
| 'clear'
|
|
73
|
+
| 'getElementRect'
|
|
74
|
+
>
|
|
75
|
+
> & {
|
|
76
|
+
active(): Promise<Element>;
|
|
77
|
+
mobileReplaceElementValue(opts: types.ReplaceValueOptions): Promise<void>;
|
|
78
|
+
getElementScreenshot(elementId: string): Promise<string>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type UIA2FindMixin = UIA2Mixin<Pick<FindMixin, 'doFindElementOrEls'>>;
|
|
82
|
+
|
|
83
|
+
export type UIA2GeneralMixin = UIA2Mixin<
|
|
84
|
+
Pick<
|
|
85
|
+
GeneralMixin & NetworkMixin & ActionsMixin & ExecuteMixin,
|
|
86
|
+
| 'getPageSource'
|
|
87
|
+
| 'doSendKeys'
|
|
88
|
+
| 'back'
|
|
89
|
+
| 'getDisplayDensity'
|
|
90
|
+
| 'getWindowSize'
|
|
91
|
+
| 'getWindowRect'
|
|
92
|
+
| 'setUrl'
|
|
93
|
+
| 'keyevent'
|
|
94
|
+
| 'execute'
|
|
95
|
+
| 'executeMobile'
|
|
96
|
+
>
|
|
97
|
+
> & {
|
|
98
|
+
getClipboard(): Promise<string>;
|
|
99
|
+
mobileViewportScreenshot(): Promise<string>;
|
|
100
|
+
mobileViewPortRect(): Promise<types.RelativeRect>;
|
|
101
|
+
mobileDeepLink(opts: types.DeepLinkOpts): Promise<void>;
|
|
102
|
+
openNotifications(): Promise<void>;
|
|
103
|
+
suspendChromedriverProxy(): void;
|
|
104
|
+
mobileGetDeviceInfo(): Promise<StringRecord>;
|
|
105
|
+
mobileType(opts: types.TypingOptions): Promise<boolean>;
|
|
106
|
+
mobileInstallMultipleApks(opts: types.InstallMultipleApksOptions): Promise<void>;
|
|
107
|
+
mobileBackgroundApp(opts?: types.BackgroundAppOptions): Promise<void>;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type UIA2ViewportMixin = UIA2Mixin & {
|
|
111
|
+
getStatusBarHeight(): Promise<number>;
|
|
112
|
+
getDevicePixelRatio(): Promise<string>;
|
|
113
|
+
getViewportScreenshot(): Promise<string>;
|
|
114
|
+
getViewPortRect(): Promise<types.RelativeRect>;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export type UIA2GesturesMixin = UIA2Mixin & {
|
|
118
|
+
mobileClickGesture(opts?: types.ClickOptions): Promise<void>;
|
|
119
|
+
mobileDoubleClickGesture(opts?: types.ClickOptions): Promise<void>;
|
|
120
|
+
mobileDragGesture(opts: types.DragOptions): Promise<void>;
|
|
121
|
+
mobileFlingGesture(opts: types.FlingOptions): Promise<boolean>;
|
|
122
|
+
mobilePinchCloseGesture(opts: types.PinchOptions): Promise<void>;
|
|
123
|
+
mobilePinchOpenGesture(opts: types.PinchOptions): Promise<void>;
|
|
124
|
+
mobileSwipeGesture(opts: types.SwipeOptions): Promise<void>;
|
|
125
|
+
mobileScrollGesture(opts: types.ScrollGestureOptions): Promise<boolean>;
|
|
126
|
+
mobileScrollBackTo(opts: types.ScrollElementToElementOpts): Promise<void>;
|
|
127
|
+
mobileScroll(opts: types.ScrollOptions): Promise<void>;
|
|
128
|
+
mobileLongClickGesture(opts: types.LongClickOptions): Promise<void>;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export type UIA2ScreenshotMixin = UIA2Mixin<Pick<ActionsMixin, 'getScreenshot'>> & {
|
|
132
|
+
mobileScreenshots(opts: types.ScreenshotsOpts): Promise<StringRecord<types.Screenshot>>;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export type UIA2TouchMixin = UIA2Mixin<
|
|
136
|
+
// Required needed because ExternalDriver's methods are all optional
|
|
137
|
+
Required<
|
|
138
|
+
Pick<ExternalDriver & TouchMixin, 'performActions' | 'releaseActions' | 'doPerformMultiAction'>
|
|
139
|
+
>
|
|
140
|
+
>;
|
|
141
|
+
|
|
142
|
+
declare module '../driver' {
|
|
143
|
+
interface AndroidUiautomator2Driver
|
|
144
|
+
extends UIA2ActionsMixin,
|
|
145
|
+
UIA2AlertMixin,
|
|
146
|
+
UIA2AppStringsMixin,
|
|
147
|
+
UIA2BatteryMixin,
|
|
148
|
+
UIA2ElementMixin,
|
|
149
|
+
UIA2FindMixin,
|
|
150
|
+
UIA2GeneralMixin,
|
|
151
|
+
UIA2GesturesMixin,
|
|
152
|
+
UIA2ScreenshotMixin,
|
|
153
|
+
UIA2TouchMixin,
|
|
154
|
+
UIA2ViewportMixin {}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* This function assigns a mixin `T` to the `AndroidUiautomator2Driver` class' prototype.
|
|
159
|
+
*
|
|
160
|
+
* While each mixin has its own interface which is (in isolation) unrelated to
|
|
161
|
+
* `AndroidUiautomator2Driver`, the constraint on this generic type `T` is that it must be a
|
|
162
|
+
* partial of `AndroidUiautomator2Driver`'s interface. This enforces that it does not
|
|
163
|
+
* conflict with the existing interface of `AndroidUiautomator2Driver`. In that way, you
|
|
164
|
+
* can think of it as a type guard.
|
|
165
|
+
* @param mixin Mixin implementation
|
|
166
|
+
*/
|
|
167
|
+
export function mixin<T extends Partial<AndroidUiautomator2Driver>>(mixin: T): void {
|
|
168
|
+
Object.assign(AndroidUiautomator2Driver.prototype, mixin);
|
|
169
|
+
}
|
|
@@ -1,91 +1,95 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {mixin} from './mixins';
|
|
1
4
|
import _ from 'lodash';
|
|
2
5
|
import B from 'bluebird';
|
|
3
6
|
|
|
4
|
-
const commands = {};
|
|
5
|
-
|
|
6
7
|
// Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0"
|
|
7
8
|
const DISPLAY_PATTERN = /^Display\s+(\d+)\s+\(.+display\s+(\d+)\).+displayName="([^"]*)/gm;
|
|
8
9
|
|
|
9
|
-
commands.getScreenshot = async function () {
|
|
10
|
-
if (this.mjpegStream) {
|
|
11
|
-
const data = await this.mjpegStream.lastChunkPNGBase64();
|
|
12
|
-
if (data) {
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
this.log.warn('Tried to get screenshot from active MJPEG stream, but there ' +
|
|
16
|
-
'was no data yet. Falling back to regular screenshot methods.');
|
|
17
|
-
}
|
|
18
|
-
return await this.uiautomator2.jwproxy.command('/screenshot', 'GET');
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @typedef {Object} ScreenshotsInfo
|
|
23
|
-
*
|
|
24
|
-
* A dictionary where each key contains a unique display identifier
|
|
25
|
-
* and values are dictionaries with following items:
|
|
26
|
-
* - id: Display identifier
|
|
27
|
-
* - name: Display name, could be empty
|
|
28
|
-
* - isDefault: Whether this display is the default one
|
|
29
|
-
* - payload: The actual PNG screenshot data encoded to base64 string
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @typedef {Object} ScreenshotsOpts
|
|
34
|
-
* @property {number|string?} displayId Android display identifier to take a screenshot for.
|
|
35
|
-
* If not provided then screenshots of all displays are going to be returned.
|
|
36
|
-
* If no matches were found then an error is thrown.
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
10
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @param {ScreenshotsOpts} opts
|
|
44
|
-
* @returns {Promise<ScreenshotsInfo>}
|
|
11
|
+
* @type {import('./mixins').UIA2ScreenshotMixin}
|
|
12
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
45
13
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return String(
|
|
27
|
+
await /** @type {import('../uiautomator2').UiAutomator2Server} */ (
|
|
28
|
+
this.uiautomator2
|
|
29
|
+
).jwproxy.command('/screenshot', 'GET')
|
|
30
|
+
);
|
|
31
|
+
},
|
|
62
32
|
|
|
63
|
-
|
|
64
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves screenshots of each display available to Android.
|
|
35
|
+
* This functionality is only supported since Android 10.
|
|
36
|
+
*/
|
|
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)}`);
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`Only the following displays have been detected: ${JSON.stringify(infos)}`
|
|
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'
|
|
73
65
|
);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
);
|
|
79
75
|
}
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
return {
|
|
77
|
+
[displayIdStr]: {
|
|
78
|
+
...infos[displayIdStr],
|
|
79
|
+
payload: await toB64Screenshot(displayIdStr),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
+
},
|
|
89
93
|
};
|
|
90
94
|
|
|
91
|
-
|
|
95
|
+
mixin(ScreenshotMixin);
|
package/lib/commands/touch.js
CHANGED
|
@@ -1,38 +1,71 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
let opts;
|
|
5
|
-
if (elementId) {
|
|
6
|
-
opts = {
|
|
7
|
-
elementId,
|
|
8
|
-
actions: states
|
|
9
|
-
};
|
|
3
|
+
import {mixin} from './mixins';
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @type {import('./mixins').UIA2TouchMixin}
|
|
7
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
8
|
+
*/
|
|
9
|
+
const TouchMixin = {
|
|
10
|
+
async doPerformMultiAction(elementId, states) {
|
|
11
|
+
let opts;
|
|
12
|
+
if (elementId) {
|
|
13
|
+
opts = {
|
|
14
|
+
elementId,
|
|
15
|
+
actions: states,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
19
|
+
'/touch/multi/perform',
|
|
20
|
+
'POST',
|
|
21
|
+
opts
|
|
22
|
+
);
|
|
23
|
+
} else {
|
|
24
|
+
opts = {
|
|
25
|
+
actions: states,
|
|
26
|
+
};
|
|
27
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
28
|
+
'/touch/multi/perform',
|
|
29
|
+
'POST',
|
|
30
|
+
opts
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
19
34
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
+
)
|
|
50
|
+
);
|
|
51
|
+
this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
|
|
52
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
53
|
+
'/actions',
|
|
54
|
+
'POST',
|
|
55
|
+
{
|
|
56
|
+
actions: preprocessedActions,
|
|
27
57
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return await this.uiautomator2.jwproxy.command('/actions', 'POST', {actions: preprocessedActions});
|
|
31
|
-
};
|
|
58
|
+
);
|
|
59
|
+
},
|
|
32
60
|
|
|
33
|
-
// eslint-disable-next-line require-await
|
|
34
|
-
|
|
35
|
-
|
|
61
|
+
// eslint-disable-next-line require-await
|
|
62
|
+
async releaseActions() {
|
|
63
|
+
this.log.info('On this platform, releaseActions is a no-op');
|
|
64
|
+
},
|
|
36
65
|
};
|
|
37
66
|
|
|
38
|
-
|
|
67
|
+
mixin(TouchMixin);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {import('../uiautomator2').UiAutomator2Server} UiAutomator2Server
|
|
71
|
+
*/
|