appium-uiautomator2-driver 2.29.10 → 2.30.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 -16
- 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 -65
- 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 -29
- 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 -58
- 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 -18
- 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 -162
- 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 -27
- 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 +217 -216
- 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 -194
- 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 -23
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/mixins.d.ts +84 -0
- package/build/lib/commands/mixins.d.ts.map +1 -0
- package/build/lib/commands/mixins.js +23 -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 -63
- 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 -39
- 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 -37
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/lib/constraints.d.ts +334 -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 -176
- package/build/lib/css-converter.js.map +1 -1
- package/build/lib/driver.d.ts +912 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +738 -483
- 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 +3 -7
- 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 -30
- 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 -11
- 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 -18
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/types.d.ts +45 -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 +334 -297
- 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 +271 -336
- package/lib/commands/gestures.js +252 -366
- package/lib/commands/index.js +11 -31
- package/lib/commands/mixins.ts +167 -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} +383 -225
- package/lib/execute-method-map.ts +573 -0
- package/lib/method-map.ts +11 -0
- package/lib/types.ts +59 -0
- package/lib/uiautomator2.js +21 -2
- package/lib/utils.js +2 -2
- package/npm-shrinkwrap.json +396 -528
- package/package.json +96 -70
- package/build/lib/desired-caps.js +0 -72
- 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/actions.js
CHANGED
|
@@ -1,110 +1,124 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
|
|
2
|
-
|
|
3
|
-
let commands = {}, helpers = {}, extensions = {};
|
|
4
|
-
|
|
5
|
-
commands.pressKeyCode = async function (keycode, metastate = null, flags = null) {
|
|
6
|
-
return await this.uiautomator2.jwproxy.command('/appium/device/press_keycode', 'POST', {
|
|
7
|
-
keycode,
|
|
8
|
-
metastate,
|
|
9
|
-
flags,
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
commands.longPressKeyCode = async function (keycode, metastate = null, flags = null) {
|
|
14
|
-
return await this.uiautomator2.jwproxy.command('/appium/device/long_press_keycode', 'POST', {
|
|
15
|
-
keycode,
|
|
16
|
-
metastate,
|
|
17
|
-
flags
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
commands.doSwipe = async function (swipeOpts) {
|
|
22
|
-
return await this.uiautomator2.jwproxy.command(`/touch/perform`, 'POST', swipeOpts);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
commands.doDrag = async function (dragOpts) {
|
|
26
|
-
return await this.uiautomator2.jwproxy.command(`/touch/drag`, 'POST', dragOpts);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
commands.getOrientation = async function () {
|
|
30
|
-
return await this.uiautomator2.jwproxy.command(`/orientation`, 'GET', {});
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
commands.setOrientation = async function (orientation) {
|
|
34
|
-
orientation = orientation.toUpperCase();
|
|
35
|
-
return await this.uiautomator2.jwproxy.command(`/orientation`, 'POST', {orientation});
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @typedef {Object} PressKeyOptions
|
|
40
|
-
* @property {number} keycode A valid Android key code. See https://developer.android.com/reference/android/view/KeyEvent
|
|
41
|
-
* for the list of available key codes
|
|
42
|
-
* @property {number?} metastate An integer in which each bit set to 1 represents a pressed meta key. See
|
|
43
|
-
* https://developer.android.com/reference/android/view/KeyEvent for more details.
|
|
44
|
-
* @property {string?} flags Flags for the particular key event. See
|
|
45
|
-
* https://developer.android.com/reference/android/view/KeyEvent for more details.
|
|
46
|
-
* @property {boolean} isLongPress [false] Whether to emulate long key press
|
|
47
|
-
*/
|
|
3
|
+
import {mixin} from './mixins';
|
|
48
4
|
|
|
49
5
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* @param {PressKeyOptions} opts
|
|
6
|
+
* @type {import('./mixins').UIA2ActionsMixin}
|
|
7
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
53
8
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
9
|
+
const ActionsMixin = {
|
|
10
|
+
async pressKeyCode(keycode, metastate, flags) {
|
|
11
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
12
|
+
'/appium/device/press_keycode',
|
|
13
|
+
'POST',
|
|
14
|
+
{
|
|
15
|
+
keycode,
|
|
16
|
+
metastate,
|
|
17
|
+
flags,
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async longPressKeyCode(keycode, metastate, flags) {
|
|
23
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
24
|
+
'/appium/device/long_press_keycode',
|
|
25
|
+
'POST',
|
|
26
|
+
{
|
|
27
|
+
keycode,
|
|
28
|
+
metastate,
|
|
29
|
+
flags,
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
async doSwipe(swipeOpts) {
|
|
35
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
36
|
+
`/touch/perform`,
|
|
37
|
+
'POST',
|
|
38
|
+
swipeOpts
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async doDrag(dragOpts) {
|
|
43
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
44
|
+
`/touch/drag`,
|
|
45
|
+
'POST',
|
|
46
|
+
dragOpts
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
async getOrientation() {
|
|
51
|
+
return /** @type {import('@appium/types').Orientation} */ (
|
|
52
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
53
|
+
`/orientation`,
|
|
54
|
+
'GET',
|
|
55
|
+
{}
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
async setOrientation(orientation) {
|
|
61
|
+
orientation = /** @type {import('@appium/types').Orientation} */ (orientation.toUpperCase());
|
|
62
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
63
|
+
`/orientation`,
|
|
64
|
+
'POST',
|
|
65
|
+
{orientation}
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
async mobilePressKey(opts) {
|
|
70
|
+
const {keycode, metastate, flags, isLongPress = false} = opts;
|
|
71
|
+
|
|
72
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
73
|
+
`/appium/device/${isLongPress ? 'long_' : ''}press_keycode`,
|
|
74
|
+
'POST',
|
|
75
|
+
{
|
|
76
|
+
keycode,
|
|
77
|
+
metastate,
|
|
78
|
+
flags,
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* See https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-scheduleaction
|
|
85
|
+
* @param {Record<string, any>} opts
|
|
86
|
+
*/
|
|
87
|
+
async mobileScheduleAction(opts = {}) {
|
|
88
|
+
return await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
89
|
+
'/appium/schedule_action',
|
|
90
|
+
'POST',
|
|
91
|
+
opts
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @see https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-getactionhistory
|
|
97
|
+
*/
|
|
98
|
+
async mobileGetActionHistory(opts) {
|
|
99
|
+
return /** @type {import('./types').ActionResult} */ (
|
|
100
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
101
|
+
'/appium/action_history',
|
|
102
|
+
'POST',
|
|
103
|
+
opts ?? {}
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @see https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-unscheduleaction
|
|
110
|
+
*/
|
|
111
|
+
async mobileUnscheduleAction(opts) {
|
|
112
|
+
return await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
113
|
+
'/appium/unschedule_action',
|
|
114
|
+
'POST',
|
|
115
|
+
opts ?? {}
|
|
116
|
+
);
|
|
117
|
+
},
|
|
70
118
|
};
|
|
71
119
|
|
|
72
|
-
|
|
73
|
-
* See https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-scheduleaction
|
|
74
|
-
* @param {Record<string, any>} opts
|
|
75
|
-
*/
|
|
76
|
-
commands.mobileScheduleAction = async function mobileScheduleAction (opts = {}) {
|
|
77
|
-
return await this.uiautomator2.jwproxy.command('/appium/schedule_action', 'POST', opts);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @typedef {Object} ActionResult
|
|
82
|
-
* @property {number} repeats
|
|
83
|
-
* @property {Record<string, any>[][]}
|
|
84
|
-
*/
|
|
120
|
+
mixin(ActionsMixin);
|
|
85
121
|
|
|
86
122
|
/**
|
|
87
|
-
* @typedef {
|
|
88
|
-
* @property {string} name
|
|
123
|
+
* @typedef {import('../uiautomator2').UiAutomator2Server} UiAutomator2Server
|
|
89
124
|
*/
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* See https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-getactionhistory
|
|
93
|
-
* @param {ActionArgs} opts
|
|
94
|
-
* @returns {Promise<ActionResult>}
|
|
95
|
-
*/
|
|
96
|
-
commands.mobileGetActionHistory = async function mobileGetActionHistory (opts) {
|
|
97
|
-
return await this.uiautomator2.jwproxy.command('/appium/action_history', 'POST', opts ?? {});
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* See https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/scheduled-actions.md#mobile-unscheduleaction
|
|
102
|
-
* @param {ActionArgs} opts
|
|
103
|
-
*/
|
|
104
|
-
commands.mobileUnscheduleAction = async function mobileUnscheduleAction (opts) {
|
|
105
|
-
return await this.uiautomator2.jwproxy.command('/appium/unschedule_action', 'POST', opts ?? {});
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
Object.assign(extensions, commands, helpers);
|
|
109
|
-
export { commands, helpers };
|
|
110
|
-
export default extensions;
|
package/lib/commands/alert.js
CHANGED
|
@@ -1,53 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
return await this.uiautomator2.jwproxy.command('/alert/text', 'GET', {});
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {Object} AcceptAlertOptions
|
|
9
|
-
* @property {?string} buttonLabel - The name of the button to click in order to
|
|
10
|
-
* accept the alert. If the name is not provided
|
|
11
|
-
* then the script will try to detect the button
|
|
12
|
-
* automatically.
|
|
13
|
-
*/
|
|
3
|
+
import {mixin} from './mixins';
|
|
14
4
|
|
|
15
5
|
/**
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* can be found
|
|
19
|
-
* @throws {NoAlertOpenError} If no alert is present
|
|
6
|
+
* @type {import('./mixins').UIA2AlertMixin}
|
|
7
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
20
8
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
9
|
+
const AlertMixin = {
|
|
10
|
+
async getAlertText() {
|
|
11
|
+
return String(
|
|
12
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
13
|
+
'/alert/text',
|
|
14
|
+
'GET',
|
|
15
|
+
{}
|
|
16
|
+
)
|
|
17
|
+
);
|
|
18
|
+
},
|
|
19
|
+
async mobileAcceptAlert(opts = {}) {
|
|
20
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
21
|
+
'/alert/accept',
|
|
22
|
+
'POST',
|
|
23
|
+
opts
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
async postAcceptAlert() {
|
|
27
|
+
await this.mobileAcceptAlert();
|
|
28
|
+
},
|
|
29
|
+
async mobileDismissAlert(opts = {}) {
|
|
30
|
+
await /** @type {UiAutomator2Server} */ (this.uiautomator2).jwproxy.command(
|
|
31
|
+
'/alert/dismiss',
|
|
32
|
+
'POST',
|
|
33
|
+
opts
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
async postDismissAlert() {
|
|
37
|
+
await this.mobileDismissAlert();
|
|
38
|
+
},
|
|
27
39
|
};
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
* @typedef {Object} DismissAlertOptions
|
|
31
|
-
* @property {?string} buttonLabel - The name of the button to click in order to
|
|
32
|
-
* dismiss the alert. If the name is not provided
|
|
33
|
-
* then the script will try to detect the button
|
|
34
|
-
* automatically.
|
|
35
|
-
*/
|
|
41
|
+
mixin(AlertMixin);
|
|
36
42
|
|
|
37
43
|
/**
|
|
38
|
-
* @
|
|
39
|
-
* @throws {InvalidElementStateError} If no matching button, that can dismiss the alert,
|
|
40
|
-
* can be found
|
|
41
|
-
* @throws {NoAlertOpenError} If no alert is present
|
|
44
|
+
* @typedef {import('../uiautomator2').UiAutomator2Server} UiAutomator2Server
|
|
42
45
|
*/
|
|
43
|
-
commands.mobileDismissAlert = async function (opts = {}) {
|
|
44
|
-
return await this.uiautomator2.jwproxy.command('/alert/dismiss', 'POST', opts);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
commands.postDismissAlert = async function () {
|
|
48
|
-
return await this.mobileDismissAlert();
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
Object.assign(extensions, commands, helpers);
|
|
52
|
-
export { commands, helpers };
|
|
53
|
-
export default extensions;
|
|
@@ -1,76 +1,97 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {mixin} from './mixins';
|
|
1
4
|
import _ from 'lodash';
|
|
2
|
-
import {
|
|
5
|
+
import {fs, tempDir} from 'appium/support';
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @type {import('./mixins').UIA2AppStringsMixin}
|
|
9
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
10
|
+
*/
|
|
11
|
+
const AppStringsMixin = {
|
|
12
|
+
async getStrings(language) {
|
|
13
|
+
const adb = /** @type {ADB} */ (this.adb);
|
|
14
|
+
if (!language) {
|
|
15
|
+
language = await adb.getDeviceLanguage();
|
|
16
|
+
this.log.info(`No language specified, returning strings for: ${language}`);
|
|
17
|
+
}
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Clients require the resulting mapping to have both keys
|
|
21
|
+
* and values of type string
|
|
22
|
+
* @param {StringRecord} mapping
|
|
23
|
+
*/
|
|
24
|
+
const preprocessStringsMap = function (mapping) {
|
|
25
|
+
/** @type {StringRecord} */
|
|
26
|
+
const result = {};
|
|
27
|
+
for (const [key, value] of _.toPairs(mapping)) {
|
|
28
|
+
result[key] = _.isString(value) ? value : JSON.stringify(value);
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
11
32
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const result = {};
|
|
16
|
-
for (const [key, value] of _.toPairs(mapping)) {
|
|
17
|
-
result[key] = _.isString(value) ? value : JSON.stringify(value);
|
|
33
|
+
if (this.apkStrings[language]) {
|
|
34
|
+
// Return cached strings
|
|
35
|
+
return preprocessStringsMap(this.apkStrings[language]);
|
|
18
36
|
}
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
37
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
if (!this.opts.app && !this.opts.appPackage) {
|
|
39
|
+
this.log.errorAndThrow("One of 'app' or 'appPackage' capabilities should must be specified");
|
|
40
|
+
throw new Error(); // unreachable
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let app = this.opts.app;
|
|
44
|
+
const tmpRoot = await tempDir.openDir();
|
|
45
|
+
try {
|
|
46
|
+
if (!app) {
|
|
47
|
+
try {
|
|
48
|
+
app = await adb.pullApk(/** @type {string} */ (this.opts.appPackage), tmpRoot);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
this.log.errorAndThrow(
|
|
51
|
+
`Failed to pull an apk from '${this.opts.appPackage}'. Original error: ${
|
|
52
|
+
/** @type {Error} */ (err).message
|
|
53
|
+
}`
|
|
54
|
+
);
|
|
55
|
+
throw new Error(); // unreachable
|
|
56
|
+
}
|
|
57
|
+
}
|
|
26
58
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
59
|
+
if (!(await fs.exists(app))) {
|
|
60
|
+
this.log.errorAndThrow(`The app at '${app}' does not exist`);
|
|
61
|
+
throw new Error(); // unreachable
|
|
62
|
+
}
|
|
30
63
|
|
|
31
|
-
let app = this.opts.app;
|
|
32
|
-
const tmpRoot = await tempDir.openDir();
|
|
33
|
-
try {
|
|
34
|
-
if (!app) {
|
|
35
64
|
try {
|
|
36
|
-
|
|
65
|
+
const {apkStrings} = await adb.extractStringsFromApk(app, language, tmpRoot);
|
|
66
|
+
this.apkStrings[language] = apkStrings;
|
|
67
|
+
return preprocessStringsMap(apkStrings);
|
|
37
68
|
} catch (err) {
|
|
38
|
-
this.log.errorAndThrow(
|
|
69
|
+
this.log.errorAndThrow(
|
|
70
|
+
`Cannot extract strings from '${app}'. Original error: ${
|
|
71
|
+
/** @type {Error} */ (err).message
|
|
72
|
+
}`
|
|
73
|
+
);
|
|
74
|
+
throw new Error(); // unreachable
|
|
39
75
|
}
|
|
76
|
+
} finally {
|
|
77
|
+
await fs.rimraf(tmpRoot);
|
|
40
78
|
}
|
|
79
|
+
},
|
|
41
80
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.log.errorAndThrow(`Cannot extract strings from '${app}'. Original error: ${err.message}`);
|
|
52
|
-
}
|
|
53
|
-
} finally {
|
|
54
|
-
await fs.rimraf(tmpRoot);
|
|
55
|
-
}
|
|
81
|
+
/**
|
|
82
|
+
* Retrives app strings from its resources for the given language
|
|
83
|
+
* or the default device language.
|
|
84
|
+
*
|
|
85
|
+
* @returns App strings map
|
|
86
|
+
*/
|
|
87
|
+
async mobileGetAppStrings(opts) {
|
|
88
|
+
return await this.getStrings(opts?.language);
|
|
89
|
+
},
|
|
56
90
|
};
|
|
57
91
|
|
|
58
|
-
|
|
59
|
-
* @typedef {Object} GetAppStringsOptions
|
|
60
|
-
* @property {string?} language The language abbreviation to fetch app strings mapping for. If no
|
|
61
|
-
* language is provided then strings for the default language on the device under test
|
|
62
|
-
* would be returned. Examples: en, fr
|
|
63
|
-
*/
|
|
92
|
+
mixin(AppStringsMixin);
|
|
64
93
|
|
|
65
94
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param {GetAppStringsOptions} opts
|
|
70
|
-
* @returns {Promise<object>} App strings map
|
|
95
|
+
* @typedef {import('appium-adb').ADB} ADB
|
|
96
|
+
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
71
97
|
*/
|
|
72
|
-
commands.mobileGetAppStrings = async function mobileGetAppStrings (opts = {}) {
|
|
73
|
-
return await this.getStrings(opts.language);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export default commands;
|
package/lib/commands/battery.js
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @typedef {Object} BatteryInfo
|
|
5
|
-
*
|
|
6
|
-
* @property {number} level - Battery level in range [0.0, 1.0], where
|
|
7
|
-
* 1.0 means 100% charge.
|
|
8
|
-
* -1 is returned if the actual value cannot be
|
|
9
|
-
* retrieved from the system.
|
|
10
|
-
* @property {number} state - Battery state. The following values are possible:
|
|
11
|
-
* BATTERY_STATUS_UNKNOWN = 1
|
|
12
|
-
* BATTERY_STATUS_CHARGING = 2
|
|
13
|
-
* BATTERY_STATUS_DISCHARGING = 3
|
|
14
|
-
* BATTERY_STATUS_NOT_CHARGING = 4
|
|
15
|
-
* BATTERY_STATUS_FULL = 5
|
|
16
|
-
* -1 is returned if the actual value cannot be retrieved from the system.
|
|
17
|
-
*/
|
|
3
|
+
import {mixin} from './mixins';
|
|
18
4
|
|
|
19
5
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* @returns {BatteryInfo} The actual battery info
|
|
6
|
+
* @type {import('./mixins').UIA2BatteryMixin}
|
|
7
|
+
* @satisfies {import('@appium/types').ExternalDriver}
|
|
23
8
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
9
|
+
const BatteryMixin = {
|
|
10
|
+
/**
|
|
11
|
+
* Reads the battery information from the device under test.
|
|
12
|
+
*
|
|
13
|
+
* @returns The actual battery info
|
|
14
|
+
*/
|
|
15
|
+
async mobileGetBatteryInfo() {
|
|
16
|
+
const result = /** @type {import('./types').MapKey<BatteryInfo, 'state', 'status'>} */ (
|
|
17
|
+
await /** @type {import('../uiautomator2').UiAutomator2Server} */ (
|
|
18
|
+
this.uiautomator2
|
|
19
|
+
).jwproxy.command('/appium/device/battery_info', 'GET', {})
|
|
20
|
+
);
|
|
21
|
+
const batteryInfo = /** @type {any} */ (result);
|
|
22
|
+
// Give it the same name as in iOS
|
|
23
|
+
batteryInfo.state = result.status;
|
|
24
|
+
delete batteryInfo.status;
|
|
25
|
+
return /** @type {BatteryInfo} */ (batteryInfo);
|
|
26
|
+
},
|
|
30
27
|
};
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
mixin(BatteryMixin);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {import('./types').BatteryInfo} BatteryInfo
|
|
33
|
+
*/
|