appium-android-driver 7.8.2 → 8.0.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 +32 -0
- package/build/lib/commands/app-management.d.ts +129 -5
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +433 -128
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/appearance.d.ts +17 -4
- package/build/lib/commands/appearance.d.ts.map +1 -1
- package/build/lib/commands/appearance.js +32 -33
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/context/cache.d.ts +19 -0
- package/build/lib/commands/context/cache.d.ts.map +1 -0
- package/build/lib/commands/context/cache.js +32 -0
- package/build/lib/commands/context/cache.js.map +1 -0
- package/build/lib/commands/context/exports.d.ts +141 -0
- package/build/lib/commands/context/exports.d.ts.map +1 -0
- package/build/lib/commands/context/exports.js +351 -0
- package/build/lib/commands/context/exports.js.map +1 -0
- package/build/lib/commands/context/helpers.d.ts +98 -0
- package/build/lib/commands/context/helpers.d.ts.map +1 -0
- package/build/lib/commands/context/helpers.js +715 -0
- package/build/lib/commands/context/helpers.js.map +1 -0
- package/build/lib/commands/device/common.d.ts +23 -0
- package/build/lib/commands/device/common.d.ts.map +1 -0
- package/build/lib/commands/device/common.js +230 -0
- package/build/lib/commands/device/common.js.map +1 -0
- package/build/lib/commands/device/emulator-actions.d.ts +114 -0
- package/build/lib/commands/device/emulator-actions.d.ts.map +1 -0
- package/build/lib/commands/device/emulator-actions.js +197 -0
- package/build/lib/commands/device/emulator-actions.js.map +1 -0
- package/build/lib/commands/device/emulator-console.d.ts +7 -0
- package/build/lib/commands/device/emulator-console.d.ts.map +1 -0
- package/build/lib/commands/device/emulator-console.js +24 -0
- package/build/lib/commands/device/emulator-console.js.map +1 -0
- package/build/lib/commands/device/utils.d.ts +50 -0
- package/build/lib/commands/device/utils.d.ts.map +1 -0
- package/build/lib/commands/device/utils.js +238 -0
- package/build/lib/commands/device/utils.js.map +1 -0
- package/build/lib/commands/deviceidle.d.ts +8 -5
- package/build/lib/commands/deviceidle.d.ts.map +1 -1
- package/build/lib/commands/deviceidle.js +31 -37
- package/build/lib/commands/deviceidle.js.map +1 -1
- package/build/lib/commands/element.d.ts +99 -5
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +152 -116
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/execute.d.ts +12 -4
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +83 -78
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-actions.d.ts +42 -5
- package/build/lib/commands/file-actions.d.ts.map +1 -1
- package/build/lib/commands/file-actions.js +230 -194
- package/build/lib/commands/file-actions.js.map +1 -1
- package/build/lib/commands/find.d.ts +5 -4
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +7 -10
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/geolocation.d.ts +45 -0
- package/build/lib/commands/geolocation.d.ts.map +1 -0
- package/build/lib/commands/geolocation.js +182 -0
- package/build/lib/commands/geolocation.js.map +1 -0
- package/build/lib/commands/ime.d.ts +25 -5
- package/build/lib/commands/ime.d.ts.map +1 -1
- package/build/lib/commands/ime.js +59 -42
- package/build/lib/commands/ime.js.map +1 -1
- package/build/lib/commands/intent.d.ts +56 -5
- package/build/lib/commands/intent.d.ts.map +1 -1
- package/build/lib/commands/intent.js +135 -83
- package/build/lib/commands/intent.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +58 -4
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +119 -17
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/lock/exports.d.ts +301 -0
- package/build/lib/commands/lock/exports.d.ts.map +1 -0
- package/build/lib/commands/lock/exports.js +121 -0
- package/build/lib/commands/lock/exports.js.map +1 -0
- package/build/lib/commands/lock/helpers.d.ts +349 -0
- package/build/lib/commands/lock/helpers.d.ts.map +1 -0
- package/build/lib/commands/lock/helpers.js +375 -0
- package/build/lib/commands/lock/helpers.js.map +1 -0
- package/build/lib/commands/log.d.ts +59 -5
- package/build/lib/commands/log.d.ts.map +1 -1
- package/build/lib/commands/log.js +150 -140
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/media-projection.d.ts +16 -5
- package/build/lib/commands/media-projection.d.ts.map +1 -1
- package/build/lib/commands/media-projection.js +69 -58
- package/build/lib/commands/media-projection.js.map +1 -1
- package/build/lib/commands/memory.d.ts +9 -5
- package/build/lib/commands/memory.d.ts.map +1 -1
- package/build/lib/commands/memory.js +19 -24
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/misc.d.ts +42 -0
- package/build/lib/commands/misc.d.ts.map +1 -0
- package/build/lib/commands/misc.js +100 -0
- package/build/lib/commands/misc.js.map +1 -0
- package/build/lib/commands/network.d.ts +61 -5
- package/build/lib/commands/network.d.ts.map +1 -1
- package/build/lib/commands/network.js +196 -189
- package/build/lib/commands/network.js.map +1 -1
- package/build/lib/commands/performance.d.ts +67 -27
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +105 -80
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +12 -6
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +65 -62
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/recordscreen.d.ts +44 -5
- package/build/lib/commands/recordscreen.d.ts.map +1 -1
- package/build/lib/commands/recordscreen.js +131 -126
- package/build/lib/commands/recordscreen.js.map +1 -1
- package/build/lib/commands/resources.d.ts +16 -0
- package/build/lib/commands/resources.d.ts.map +1 -0
- package/build/lib/commands/resources.js +91 -0
- package/build/lib/commands/resources.js.map +1 -0
- package/build/lib/commands/shell.d.ts +8 -5
- package/build/lib/commands/shell.d.ts.map +1 -1
- package/build/lib/commands/shell.js +29 -33
- package/build/lib/commands/shell.js.map +1 -1
- package/build/lib/commands/streamscreen.d.ts +34 -6
- package/build/lib/commands/streamscreen.d.ts.map +1 -1
- package/build/lib/commands/streamscreen.js +166 -162
- package/build/lib/commands/streamscreen.js.map +1 -1
- package/build/lib/commands/system-bars.d.ts +18 -13
- package/build/lib/commands/system-bars.d.ts.map +1 -1
- package/build/lib/commands/system-bars.js +68 -64
- package/build/lib/commands/system-bars.js.map +1 -1
- package/build/lib/commands/time.d.ts +14 -0
- package/build/lib/commands/time.d.ts.map +1 -0
- package/build/lib/commands/time.js +39 -0
- package/build/lib/commands/time.js.map +1 -0
- package/build/lib/commands/touch.d.ts +99 -6
- package/build/lib/commands/touch.d.ts.map +1 -1
- package/build/lib/commands/touch.js +399 -280
- package/build/lib/commands/touch.js.map +1 -1
- package/build/lib/commands/types.d.ts +115 -3
- package/build/lib/commands/types.d.ts.map +1 -1
- package/build/lib/doctor/checks.d.ts.map +1 -1
- package/build/lib/doctor/checks.js +4 -4
- package/build/lib/doctor/checks.js.map +1 -1
- package/build/lib/driver.d.ts +224 -27
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +232 -7
- package/build/lib/driver.js.map +1 -1
- package/build/lib/index.d.ts +1 -4
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +1 -13
- package/build/lib/index.js.map +1 -1
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.d.ts +0 -23
- package/build/lib/method-map.d.ts.map +1 -1
- package/build/lib/method-map.js +0 -11
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/utils.d.ts +12 -0
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +38 -2
- package/build/lib/utils.js.map +1 -1
- package/lib/commands/app-management.js +470 -145
- package/lib/commands/appearance.js +29 -36
- package/lib/commands/context/cache.js +29 -0
- package/lib/commands/context/exports.js +379 -0
- package/lib/commands/context/helpers.js +802 -0
- package/lib/commands/device/common.js +264 -0
- package/lib/commands/device/emulator-actions.js +194 -0
- package/lib/commands/device/emulator-console.js +24 -0
- package/lib/commands/device/utils.js +285 -0
- package/lib/commands/deviceidle.js +31 -44
- package/lib/commands/element.js +149 -142
- package/lib/commands/execute.js +86 -87
- package/lib/commands/file-actions.js +249 -222
- package/lib/commands/find.ts +13 -19
- package/lib/commands/geolocation.js +179 -0
- package/lib/commands/ime.js +53 -45
- package/lib/commands/intent.js +149 -91
- package/lib/commands/keyboard.js +114 -17
- package/lib/commands/lock/exports.js +139 -0
- package/lib/commands/lock/helpers.js +379 -0
- package/lib/commands/log.js +170 -166
- package/lib/commands/media-projection.js +75 -70
- package/lib/commands/memory.js +17 -29
- package/lib/commands/misc.js +94 -0
- package/lib/commands/network.js +209 -223
- package/lib/commands/performance.js +88 -73
- package/lib/commands/permissions.js +83 -84
- package/lib/commands/recordscreen.js +171 -170
- package/lib/commands/resources.js +96 -0
- package/lib/commands/shell.js +28 -42
- package/lib/commands/streamscreen.js +207 -206
- package/lib/commands/system-bars.js +76 -77
- package/lib/commands/time.js +36 -0
- package/lib/commands/touch.js +442 -346
- package/lib/commands/types.ts +142 -10
- package/lib/doctor/checks.js +24 -16
- package/lib/driver.ts +454 -12
- package/lib/index.ts +1 -13
- package/lib/logger.js +1 -1
- package/lib/method-map.js +0 -11
- package/lib/utils.js +40 -3
- package/package.json +1 -1
- package/build/lib/commands/actions.d.ts +0 -8
- package/build/lib/commands/actions.d.ts.map +0 -1
- package/build/lib/commands/actions.js +0 -207
- package/build/lib/commands/actions.js.map +0 -1
- package/build/lib/commands/alert.d.ts +0 -8
- package/build/lib/commands/alert.d.ts.map +0 -1
- package/build/lib/commands/alert.js +0 -29
- package/build/lib/commands/alert.js.map +0 -1
- package/build/lib/commands/context.d.ts +0 -10
- package/build/lib/commands/context.d.ts.map +0 -1
- package/build/lib/commands/context.js +0 -431
- package/build/lib/commands/context.js.map +0 -1
- package/build/lib/commands/emu-console.d.ts +0 -7
- package/build/lib/commands/emu-console.d.ts.map +0 -1
- package/build/lib/commands/emu-console.js +0 -27
- package/build/lib/commands/emu-console.js.map +0 -1
- package/build/lib/commands/general.d.ts +0 -9
- package/build/lib/commands/general.d.ts.map +0 -1
- package/build/lib/commands/general.js +0 -293
- package/build/lib/commands/general.js.map +0 -1
- package/build/lib/commands/index.d.ts +0 -28
- package/build/lib/commands/index.d.ts.map +0 -1
- package/build/lib/commands/index.js +0 -57
- package/build/lib/commands/index.js.map +0 -1
- package/build/lib/commands/mixins.d.ts +0 -747
- package/build/lib/commands/mixins.d.ts.map +0 -1
- package/build/lib/commands/mixins.js +0 -19
- package/build/lib/commands/mixins.js.map +0 -1
- package/build/lib/helpers/android.d.ts +0 -163
- package/build/lib/helpers/android.d.ts.map +0 -1
- package/build/lib/helpers/android.js +0 -818
- package/build/lib/helpers/android.js.map +0 -1
- package/build/lib/helpers/index.d.ts +0 -7
- package/build/lib/helpers/index.d.ts.map +0 -1
- package/build/lib/helpers/index.js +0 -29
- package/build/lib/helpers/index.js.map +0 -1
- package/build/lib/helpers/types.d.ts +0 -122
- package/build/lib/helpers/types.d.ts.map +0 -1
- package/build/lib/helpers/types.js +0 -3
- package/build/lib/helpers/types.js.map +0 -1
- package/build/lib/helpers/unlock.d.ts +0 -32
- package/build/lib/helpers/unlock.d.ts.map +0 -1
- package/build/lib/helpers/unlock.js +0 -273
- package/build/lib/helpers/unlock.js.map +0 -1
- package/build/lib/helpers/webview.d.ts +0 -74
- package/build/lib/helpers/webview.d.ts.map +0 -1
- package/build/lib/helpers/webview.js +0 -442
- package/build/lib/helpers/webview.js.map +0 -1
- package/lib/commands/actions.js +0 -244
- package/lib/commands/alert.js +0 -34
- package/lib/commands/context.js +0 -507
- package/lib/commands/emu-console.js +0 -31
- package/lib/commands/general.js +0 -343
- package/lib/commands/index.ts +0 -54
- package/lib/commands/mixins.ts +0 -976
- package/lib/helpers/android.ts +0 -1153
- package/lib/helpers/index.ts +0 -6
- package/lib/helpers/types.ts +0 -136
- package/lib/helpers/unlock.ts +0 -329
- package/lib/helpers/webview.ts +0 -604
package/lib/commands/log.js
CHANGED
|
@@ -1,14 +1,179 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
1
|
import {DEFAULT_WS_PATHNAME_PREFIX, BaseDriver} from 'appium/driver';
|
|
4
2
|
import _ from 'lodash';
|
|
5
3
|
import os from 'node:os';
|
|
6
4
|
import WebSocket from 'ws';
|
|
7
|
-
import log from '../logger';
|
|
8
|
-
import {mixin} from './mixins';
|
|
9
5
|
|
|
10
6
|
const GET_SERVER_LOGS_FEATURE = 'get_server_logs';
|
|
11
7
|
|
|
8
|
+
export const supportedLogTypes = {
|
|
9
|
+
logcat: {
|
|
10
|
+
description: 'Logs for Android applications on real device and emulators via ADB',
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {import('../driver').AndroidDriver} self
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
getter: (self) => /** @type {ADB} */ (self.adb).getLogcatLogs(),
|
|
17
|
+
},
|
|
18
|
+
bugreport: {
|
|
19
|
+
description: `'adb bugreport' output for advanced issues diagnostic`,
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param {import('../driver').AndroidDriver} self
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
getter: async (self) => {
|
|
26
|
+
const output = await /** @type {ADB} */ (self.adb).bugreport();
|
|
27
|
+
const timestamp = Date.now();
|
|
28
|
+
return output.split(os.EOL).map((x) => toLogRecord(timestamp, 'ALL', x));
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
server: {
|
|
32
|
+
description: 'Appium server logs',
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param {import('../driver').AndroidDriver} self
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
getter: (self) => {
|
|
39
|
+
self.ensureFeatureEnabled(GET_SERVER_LOGS_FEATURE);
|
|
40
|
+
const timestamp = Date.now();
|
|
41
|
+
return self.log
|
|
42
|
+
.unwrap()
|
|
43
|
+
.record.map((x) =>
|
|
44
|
+
toLogRecord(
|
|
45
|
+
timestamp,
|
|
46
|
+
'ALL',
|
|
47
|
+
_.isEmpty(x.prefix) ? x.message : `[${x.prefix}] ${x.message}`,
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Starts Android logcat broadcast websocket on the same host and port
|
|
56
|
+
* where Appium server is running at `/ws/session/:sessionId:/appium/logcat` endpoint. The method
|
|
57
|
+
* will return immediately if the web socket is already listening.
|
|
58
|
+
*
|
|
59
|
+
* Each connected websocket listener will receive logcat log lines
|
|
60
|
+
* as soon as they are visible to Appium.
|
|
61
|
+
*
|
|
62
|
+
* @this {import('../driver').AndroidDriver}
|
|
63
|
+
* @returns {Promise<void>}
|
|
64
|
+
*/
|
|
65
|
+
export async function mobileStartLogsBroadcast() {
|
|
66
|
+
const server = /** @type {import('@appium/types').AppiumServer} */ (this.server);
|
|
67
|
+
const pathname = WEBSOCKET_ENDPOINT(/** @type {string} */ (this.sessionId));
|
|
68
|
+
if (!_.isEmpty(await server.getWebSocketHandlers(pathname))) {
|
|
69
|
+
this.log.debug(`The logcat broadcasting web socket server is already listening at ${pathname}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.log.info(
|
|
74
|
+
`Starting logcat broadcasting on web socket server ` +
|
|
75
|
+
`${JSON.stringify(server.address())} to ${pathname}`,
|
|
76
|
+
);
|
|
77
|
+
// https://github.com/websockets/ws/blob/master/doc/ws.md
|
|
78
|
+
const wss = new WebSocket.Server({
|
|
79
|
+
noServer: true,
|
|
80
|
+
});
|
|
81
|
+
wss.on('connection', (ws, req) => {
|
|
82
|
+
if (req) {
|
|
83
|
+
const remoteIp = _.isEmpty(req.headers['x-forwarded-for'])
|
|
84
|
+
? req.connection?.remoteAddress
|
|
85
|
+
: req.headers['x-forwarded-for'];
|
|
86
|
+
this.log.debug(`Established a new logcat listener web socket connection from ${remoteIp}`);
|
|
87
|
+
} else {
|
|
88
|
+
this.log.debug('Established a new logcat listener web socket connection');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (_.isEmpty(this._logcatWebsocketListener)) {
|
|
92
|
+
this._logcatWebsocketListener = (logRecord) => {
|
|
93
|
+
if (ws?.readyState === WebSocket.OPEN) {
|
|
94
|
+
ws.send(logRecord.message);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
this.adb.setLogcatListener(this._logcatWebsocketListener);
|
|
99
|
+
|
|
100
|
+
ws.on('close', (code, reason) => {
|
|
101
|
+
if (!_.isEmpty(this._logcatWebsocketListener)) {
|
|
102
|
+
try {
|
|
103
|
+
this.adb.removeLogcatListener(this._logcatWebsocketListener);
|
|
104
|
+
} catch (ign) {}
|
|
105
|
+
this._logcatWebsocketListener = undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let closeMsg = 'Logcat listener web socket is closed.';
|
|
109
|
+
if (!_.isEmpty(code)) {
|
|
110
|
+
closeMsg += ` Code: ${code}.`;
|
|
111
|
+
}
|
|
112
|
+
if (!_.isEmpty(reason)) {
|
|
113
|
+
closeMsg += ` Reason: ${reason.toString()}.`;
|
|
114
|
+
}
|
|
115
|
+
this.log.debug(closeMsg);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
await server.addWebSocketHandler(pathname, /** @type {import('@appium/types').WSServer} */ (wss));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Stops the previously started logcat broadcasting wesocket server.
|
|
123
|
+
* This method will return immediately if no server is running.
|
|
124
|
+
*
|
|
125
|
+
* @this {import('../driver').AndroidDriver}
|
|
126
|
+
* @returns {Promise<void>}
|
|
127
|
+
*/
|
|
128
|
+
export async function mobileStopLogsBroadcast() {
|
|
129
|
+
const pathname = WEBSOCKET_ENDPOINT(/** @type {string} */ (this.sessionId));
|
|
130
|
+
const server = /** @type {import('@appium/types').AppiumServer} */ (this.server);
|
|
131
|
+
if (_.isEmpty(await server.getWebSocketHandlers(pathname))) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.log.debug(
|
|
136
|
+
`Stopping logcat broadcasting on web socket server ` +
|
|
137
|
+
`${JSON.stringify(server.address())} to ${pathname}`,
|
|
138
|
+
);
|
|
139
|
+
await server.removeWebSocketHandler(pathname);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @this {import('../driver').AndroidDriver}
|
|
144
|
+
* @returns {Promise<string[]>}
|
|
145
|
+
*/
|
|
146
|
+
export async function getLogTypes() {
|
|
147
|
+
// XXX why doesn't `super` work here?
|
|
148
|
+
const nativeLogTypes = await BaseDriver.prototype.getLogTypes.call(this);
|
|
149
|
+
if (this.isWebContext()) {
|
|
150
|
+
const webLogTypes = /** @type {string[]} */ (
|
|
151
|
+
await /** @type {import('appium-chromedriver').Chromedriver} */ (
|
|
152
|
+
this.chromedriver
|
|
153
|
+
).jwproxy.command('/log/types', 'GET')
|
|
154
|
+
);
|
|
155
|
+
return [...nativeLogTypes, ...webLogTypes];
|
|
156
|
+
}
|
|
157
|
+
return nativeLogTypes;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @this {import('../driver').AndroidDriver}
|
|
162
|
+
* @param {string} logType
|
|
163
|
+
* @returns {Promise<any>}
|
|
164
|
+
*/
|
|
165
|
+
export async function getLog(logType) {
|
|
166
|
+
if (this.isWebContext() && !_.keys(this.supportedLogTypes).includes(logType)) {
|
|
167
|
+
return await /** @type {import('appium-chromedriver').Chromedriver} */ (
|
|
168
|
+
this.chromedriver
|
|
169
|
+
).jwproxy.command('/log', 'POST', {type: logType});
|
|
170
|
+
}
|
|
171
|
+
// XXX why doesn't `super` work here?
|
|
172
|
+
return await BaseDriver.prototype.getLog.call(this, logType);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// #region Internal helpers
|
|
176
|
+
|
|
12
177
|
/**
|
|
13
178
|
* @param {string} sessionId
|
|
14
179
|
* @returns {string}
|
|
@@ -30,169 +195,8 @@ function toLogRecord(timestamp, level, message) {
|
|
|
30
195
|
message,
|
|
31
196
|
};
|
|
32
197
|
}
|
|
33
|
-
/**
|
|
34
|
-
* @type {import('./mixins').LogMixin & ThisType<import('../driver').AndroidDriver>}
|
|
35
|
-
* @satisfies {import('@appium/types').ExternalDriver}
|
|
36
|
-
*/
|
|
37
|
-
const LogMixin = {
|
|
38
|
-
supportedLogTypes: {
|
|
39
|
-
logcat: {
|
|
40
|
-
description: 'Logs for Android applications on real device and emulators via ADB',
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* @param {import('../driver').AndroidDriver} self
|
|
44
|
-
* @returns
|
|
45
|
-
*/
|
|
46
|
-
getter: (self) => /** @type {ADB} */ (self.adb).getLogcatLogs(),
|
|
47
|
-
},
|
|
48
|
-
bugreport: {
|
|
49
|
-
description: `'adb bugreport' output for advanced issues diagnostic`,
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
* @param {import('../driver').AndroidDriver} self
|
|
53
|
-
* @returns
|
|
54
|
-
*/
|
|
55
|
-
getter: async (self) => {
|
|
56
|
-
const output = await /** @type {ADB} */ (self.adb).bugreport();
|
|
57
|
-
const timestamp = Date.now();
|
|
58
|
-
return output.split(os.EOL).map((x) => toLogRecord(timestamp, 'ALL', x));
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
server: {
|
|
62
|
-
description: 'Appium server logs',
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* @param {import('../driver').AndroidDriver} self
|
|
66
|
-
* @returns
|
|
67
|
-
*/
|
|
68
|
-
getter: (self) => {
|
|
69
|
-
self.ensureFeatureEnabled(GET_SERVER_LOGS_FEATURE);
|
|
70
|
-
const timestamp = Date.now();
|
|
71
|
-
return log
|
|
72
|
-
.unwrap()
|
|
73
|
-
.record.map((x) =>
|
|
74
|
-
toLogRecord(
|
|
75
|
-
timestamp,
|
|
76
|
-
'ALL',
|
|
77
|
-
_.isEmpty(x.prefix) ? x.message : `[${x.prefix}] ${x.message}`
|
|
78
|
-
)
|
|
79
|
-
);
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Starts Android logcat broadcast websocket on the same host and port
|
|
86
|
-
* where Appium server is running at `/ws/session/:sessionId:/appium/logcat` endpoint. The method
|
|
87
|
-
* will return immediately if the web socket is already listening.
|
|
88
|
-
*
|
|
89
|
-
* Each connected websocket listener will receive logcat log lines
|
|
90
|
-
* as soon as they are visible to Appium.
|
|
91
|
-
*/
|
|
92
|
-
async mobileStartLogsBroadcast() {
|
|
93
|
-
const server = /** @type {import('@appium/types').AppiumServer} */ (this.server);
|
|
94
|
-
const pathname = WEBSOCKET_ENDPOINT(/** @type {string} */ (this.sessionId));
|
|
95
|
-
if (!_.isEmpty(await server.getWebSocketHandlers(pathname))) {
|
|
96
|
-
log.debug(`The logcat broadcasting web socket server is already listening at ${pathname}`);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
log.info(
|
|
101
|
-
`Starting logcat broadcasting on web socket server ` +
|
|
102
|
-
`${JSON.stringify(server.address())} to ${pathname}`
|
|
103
|
-
);
|
|
104
|
-
// https://github.com/websockets/ws/blob/master/doc/ws.md
|
|
105
|
-
const wss = new WebSocket.Server({
|
|
106
|
-
noServer: true,
|
|
107
|
-
});
|
|
108
|
-
wss.on('connection', (ws, req) => {
|
|
109
|
-
if (req) {
|
|
110
|
-
const remoteIp = _.isEmpty(req.headers['x-forwarded-for'])
|
|
111
|
-
? req.connection?.remoteAddress
|
|
112
|
-
: req.headers['x-forwarded-for'];
|
|
113
|
-
log.debug(`Established a new logcat listener web socket connection from ${remoteIp}`);
|
|
114
|
-
} else {
|
|
115
|
-
log.debug('Established a new logcat listener web socket connection');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (_.isEmpty(this._logcatWebsocketListener)) {
|
|
119
|
-
this._logcatWebsocketListener = (logRecord) => {
|
|
120
|
-
if (ws?.readyState === WebSocket.OPEN) {
|
|
121
|
-
ws.send(logRecord.message);
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
this.adb.setLogcatListener(this._logcatWebsocketListener);
|
|
126
|
-
|
|
127
|
-
ws.on('close', (code, reason) => {
|
|
128
|
-
if (!_.isEmpty(this._logcatWebsocketListener)) {
|
|
129
|
-
try {
|
|
130
|
-
this.adb.removeLogcatListener(this._logcatWebsocketListener);
|
|
131
|
-
} catch (ign) {}
|
|
132
|
-
this._logcatWebsocketListener = undefined;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let closeMsg = 'Logcat listener web socket is closed.';
|
|
136
|
-
if (!_.isEmpty(code)) {
|
|
137
|
-
closeMsg += ` Code: ${code}.`;
|
|
138
|
-
}
|
|
139
|
-
if (!_.isEmpty(reason)) {
|
|
140
|
-
closeMsg += ` Reason: ${reason.toString()}.`;
|
|
141
|
-
}
|
|
142
|
-
log.debug(closeMsg);
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
await server.addWebSocketHandler(
|
|
146
|
-
pathname,
|
|
147
|
-
/** @type {import('@appium/types').WSServer} */ (wss)
|
|
148
|
-
);
|
|
149
|
-
},
|
|
150
|
-
/**
|
|
151
|
-
* Stops the previously started logcat broadcasting wesocket server.
|
|
152
|
-
* This method will return immediately if no server is running.
|
|
153
|
-
*/
|
|
154
|
-
async mobileStopLogsBroadcast() {
|
|
155
|
-
const pathname = WEBSOCKET_ENDPOINT(/** @type {string} */ (this.sessionId));
|
|
156
|
-
const server = /** @type {import('@appium/types').AppiumServer} */ (this.server);
|
|
157
|
-
if (_.isEmpty(await server.getWebSocketHandlers(pathname))) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
log.debug(
|
|
162
|
-
`Stopping logcat broadcasting on web socket server ` +
|
|
163
|
-
`${JSON.stringify(server.address())} to ${pathname}`
|
|
164
|
-
);
|
|
165
|
-
await server.removeWebSocketHandler(pathname);
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
async getLogTypes() {
|
|
169
|
-
// XXX why doesn't `super` work here?
|
|
170
|
-
const nativeLogTypes = await BaseDriver.prototype.getLogTypes.call(this);
|
|
171
|
-
if (this.isWebContext()) {
|
|
172
|
-
const webLogTypes = /** @type {string[]} */ (
|
|
173
|
-
await /** @type {import('appium-chromedriver').Chromedriver} */ (
|
|
174
|
-
this.chromedriver
|
|
175
|
-
).jwproxy.command('/log/types', 'GET')
|
|
176
|
-
);
|
|
177
|
-
return [...nativeLogTypes, ...webLogTypes];
|
|
178
|
-
}
|
|
179
|
-
return nativeLogTypes;
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
async getLog(logType) {
|
|
183
|
-
if (this.isWebContext() && !_.keys(this.supportedLogTypes).includes(logType)) {
|
|
184
|
-
return await /** @type {import('appium-chromedriver').Chromedriver} */ (
|
|
185
|
-
this.chromedriver
|
|
186
|
-
).jwproxy.command('/log', 'POST', {type: logType});
|
|
187
|
-
}
|
|
188
|
-
// XXX why doesn't `super` work here?
|
|
189
|
-
return await BaseDriver.prototype.getLog.call(this, logType);
|
|
190
|
-
},
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
mixin(LogMixin);
|
|
194
198
|
|
|
195
|
-
|
|
199
|
+
// #endregion
|
|
196
200
|
|
|
197
201
|
/**
|
|
198
202
|
* @typedef {import('appium-adb').ADB} ADB
|
|
@@ -2,13 +2,85 @@ import {fs, net, util} from '@appium/support';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import moment from 'moment';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import {mixin} from './mixins';
|
|
6
5
|
|
|
7
6
|
// https://github.com/appium/io.appium.settings#internal-audio--video-recording
|
|
8
7
|
const DEFAULT_EXT = '.mp4';
|
|
9
8
|
const MIN_API_LEVEL = 29;
|
|
10
9
|
const DEFAULT_FILENAME_FORMAT = 'YYYY-MM-DDTHH-mm-ss';
|
|
11
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @this {import('../driver').AndroidDriver}
|
|
13
|
+
* @param {import('./types').StartMediaProjectionRecordingOpts} [options={}]
|
|
14
|
+
* @returns {Promise<boolean>}
|
|
15
|
+
*/
|
|
16
|
+
export async function mobileStartMediaProjectionRecording(options = {}) {
|
|
17
|
+
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
18
|
+
|
|
19
|
+
const {resolution, priority, maxDurationSec, filename} = options;
|
|
20
|
+
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
21
|
+
const fname = adjustMediaExtension(filename || moment().format(DEFAULT_FILENAME_FORMAT));
|
|
22
|
+
const didStart = await recorder.start({
|
|
23
|
+
resolution,
|
|
24
|
+
priority,
|
|
25
|
+
maxDurationSec,
|
|
26
|
+
filename: fname,
|
|
27
|
+
});
|
|
28
|
+
if (didStart) {
|
|
29
|
+
this.log.info(`A new media projection recording '${fname}' has been successfully started`);
|
|
30
|
+
} else {
|
|
31
|
+
this.log.info(
|
|
32
|
+
'Another media projection recording is already in progress. There is nothing to start',
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return didStart;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @this {import('../driver').AndroidDriver}
|
|
40
|
+
* @returns {Promise<boolean>}
|
|
41
|
+
*/
|
|
42
|
+
export async function mobileIsMediaProjectionRecordingRunning() {
|
|
43
|
+
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
44
|
+
|
|
45
|
+
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
46
|
+
return await recorder.isRunning();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @this {import('../driver').AndroidDriver}
|
|
51
|
+
* @param {import('./types').StopMediaProjectionRecordingOpts} [options={}]
|
|
52
|
+
* @returns {Promise<string>}
|
|
53
|
+
*/
|
|
54
|
+
export async function mobileStopMediaProjectionRecording(options = {}) {
|
|
55
|
+
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
56
|
+
|
|
57
|
+
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
58
|
+
if (await recorder.stop()) {
|
|
59
|
+
this.log.info('Successfully stopped a media projection recording. Pulling the recorded media');
|
|
60
|
+
} else {
|
|
61
|
+
this.log.info('Media projection recording is not running. There is nothing to stop');
|
|
62
|
+
}
|
|
63
|
+
const recentRecordingPath = await recorder.pullRecent();
|
|
64
|
+
if (!recentRecordingPath) {
|
|
65
|
+
throw new Error(`No recent media projection recording have been found. Did you start any?`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const {remotePath} = options;
|
|
69
|
+
if (_.isEmpty(remotePath)) {
|
|
70
|
+
const {size} = await fs.stat(recentRecordingPath);
|
|
71
|
+
this.log.debug(
|
|
72
|
+
`The size of the resulting media projection recording is ${util.toReadableSizeString(size)}`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
return await uploadRecordedMedia(recentRecordingPath, remotePath, options);
|
|
77
|
+
} finally {
|
|
78
|
+
await fs.rimraf(path.dirname(recentRecordingPath));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// #region Internal helpers
|
|
83
|
+
|
|
12
84
|
/**
|
|
13
85
|
*
|
|
14
86
|
* @param {string} localFile
|
|
@@ -65,79 +137,12 @@ async function verifyMediaProjectionRecordingIsSupported(adb) {
|
|
|
65
137
|
if (apiLevel < MIN_API_LEVEL) {
|
|
66
138
|
throw new Error(
|
|
67
139
|
`Media projection-based recording is not available on API Level ${apiLevel}. ` +
|
|
68
|
-
`Minimum required API Level is ${MIN_API_LEVEL}
|
|
140
|
+
`Minimum required API Level is ${MIN_API_LEVEL}.`,
|
|
69
141
|
);
|
|
70
142
|
}
|
|
71
143
|
}
|
|
72
144
|
|
|
73
|
-
|
|
74
|
-
* @type {import('./mixins').MediaProjectionMixin & ThisType<import('../driver').AndroidDriver>}
|
|
75
|
-
* @satisfies {import('@appium/types').ExternalDriver}
|
|
76
|
-
*/
|
|
77
|
-
const MediaProjectionMixin = {
|
|
78
|
-
async mobileStartMediaProjectionRecording(options = {}) {
|
|
79
|
-
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
80
|
-
|
|
81
|
-
const {resolution, priority, maxDurationSec, filename} = options;
|
|
82
|
-
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
83
|
-
const fname = adjustMediaExtension(filename || moment().format(DEFAULT_FILENAME_FORMAT));
|
|
84
|
-
const didStart = await recorder.start({
|
|
85
|
-
resolution,
|
|
86
|
-
priority,
|
|
87
|
-
maxDurationSec,
|
|
88
|
-
filename: fname,
|
|
89
|
-
});
|
|
90
|
-
if (didStart) {
|
|
91
|
-
this.log.info(`A new media projection recording '${fname}' has been successfully started`);
|
|
92
|
-
} else {
|
|
93
|
-
this.log.info(
|
|
94
|
-
'Another media projection recording is already in progress. There is nothing to start'
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
return didStart;
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
async mobileIsMediaProjectionRecordingRunning() {
|
|
101
|
-
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
102
|
-
|
|
103
|
-
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
104
|
-
return await recorder.isRunning();
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
async mobileStopMediaProjectionRecording(options = {}) {
|
|
108
|
-
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
109
|
-
|
|
110
|
-
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
111
|
-
if (await recorder.stop()) {
|
|
112
|
-
this.log.info(
|
|
113
|
-
'Successfully stopped a media projection recording. Pulling the recorded media'
|
|
114
|
-
);
|
|
115
|
-
} else {
|
|
116
|
-
this.log.info('Media projection recording is not running. There is nothing to stop');
|
|
117
|
-
}
|
|
118
|
-
const recentRecordingPath = await recorder.pullRecent();
|
|
119
|
-
if (!recentRecordingPath) {
|
|
120
|
-
throw new Error(`No recent media projection recording have been found. Did you start any?`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const {remotePath} = options;
|
|
124
|
-
if (_.isEmpty(remotePath)) {
|
|
125
|
-
const {size} = await fs.stat(recentRecordingPath);
|
|
126
|
-
this.log.debug(
|
|
127
|
-
`The size of the resulting media projection recording is ${util.toReadableSizeString(size)}`
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
return await uploadRecordedMedia(recentRecordingPath, remotePath, options);
|
|
132
|
-
} finally {
|
|
133
|
-
await fs.rimraf(path.dirname(recentRecordingPath));
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
mixin(MediaProjectionMixin);
|
|
139
|
-
|
|
140
|
-
export default MediaProjectionMixin;
|
|
145
|
+
// #endregion
|
|
141
146
|
|
|
142
147
|
/**
|
|
143
148
|
* @typedef {import('appium-adb').ADB} ADB
|
package/lib/commands/memory.js
CHANGED
|
@@ -1,38 +1,26 @@
|
|
|
1
1
|
import {errors} from 'appium/driver';
|
|
2
|
-
import {mixin} from './mixins';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Simulates the onTrimMemory() event for the given package.
|
|
5
|
+
* Read https://developer.android.com/topic/performance/memory
|
|
6
|
+
* for more details.
|
|
7
|
+
*
|
|
8
|
+
* @this {import('../driver').AndroidDriver}
|
|
9
|
+
* @param {import('./types').SendTrimMemoryOpts} opts
|
|
10
|
+
* @returns {Promise<void>}
|
|
7
11
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* Simulates the onTrimMemory() event for the given package.
|
|
11
|
-
* Read https://developer.android.com/topic/performance/memory
|
|
12
|
-
* for more details.
|
|
13
|
-
*
|
|
14
|
-
* @param {import('./types').SendTrimMemoryOpts} opts
|
|
15
|
-
*/
|
|
16
|
-
async mobileSendTrimMemory(opts) {
|
|
17
|
-
const {
|
|
18
|
-
pkg,
|
|
19
|
-
level,
|
|
20
|
-
} = opts;
|
|
12
|
+
export async function mobileSendTrimMemory(opts) {
|
|
13
|
+
const {pkg, level} = opts;
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
if (!pkg) {
|
|
16
|
+
throw new errors.InvalidArgumentError(`The 'pkg' argument must be provided`);
|
|
17
|
+
}
|
|
18
|
+
if (!level) {
|
|
19
|
+
throw new errors.InvalidArgumentError(`The 'level' argument must be provided`);
|
|
20
|
+
}
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
mixin(MemoryMixin);
|
|
34
|
-
|
|
35
|
-
export default MemoryMixin;
|
|
22
|
+
await this.adb.shell(['am', 'send-trim-memory', pkg, level]);
|
|
23
|
+
}
|
|
36
24
|
|
|
37
25
|
/**
|
|
38
26
|
* @typedef {import('appium-adb').ADB} ADB
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import {errors} from 'appium/driver';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @this {import('../driver').AndroidDriver}
|
|
7
|
+
* @returns {Promise<import('@appium/types').Size>}
|
|
8
|
+
*/
|
|
9
|
+
export async function getWindowSize() {
|
|
10
|
+
throw new errors.NotImplementedError('Not implemented');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @this {import('../driver').AndroidDriver}
|
|
15
|
+
* @returns {Promise<import('@appium/types').Rect>}
|
|
16
|
+
*/
|
|
17
|
+
export async function getWindowRect() {
|
|
18
|
+
const {width, height} = await this.getWindowSize();
|
|
19
|
+
return {
|
|
20
|
+
width,
|
|
21
|
+
height,
|
|
22
|
+
x: 0,
|
|
23
|
+
y: 0,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* we override setUrl to take an android URI which can be used for deep-linking
|
|
29
|
+
* inside an app, similar to starting an intent
|
|
30
|
+
*
|
|
31
|
+
* @this {import('../driver').AndroidDriver}
|
|
32
|
+
* @param {string} uri
|
|
33
|
+
* @returns {Promise<void>}
|
|
34
|
+
*/
|
|
35
|
+
export async function setUrl(uri) {
|
|
36
|
+
await this.adb.startUri(uri, /** @type {string} */ (this.opts.appPackage));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @this {import('../driver').AndroidDriver}
|
|
41
|
+
* @returns {Promise<number>}
|
|
42
|
+
*/
|
|
43
|
+
export async function getDisplayDensity() {
|
|
44
|
+
// first try the property for devices
|
|
45
|
+
let out = await this.adb.shell(['getprop', 'ro.sf.lcd_density']);
|
|
46
|
+
if (out) {
|
|
47
|
+
let val = parseInt(out, 10);
|
|
48
|
+
// if the value is NaN, try getting the emulator property
|
|
49
|
+
if (!isNaN(val)) {
|
|
50
|
+
return val;
|
|
51
|
+
}
|
|
52
|
+
this.log.debug(`Parsed density value was NaN: "${out}"`);
|
|
53
|
+
}
|
|
54
|
+
// fallback to trying property for emulators
|
|
55
|
+
out = await this.adb.shell(['getprop', 'qemu.sf.lcd_density']);
|
|
56
|
+
if (out) {
|
|
57
|
+
let val = parseInt(out, 10);
|
|
58
|
+
if (!isNaN(val)) {
|
|
59
|
+
return val;
|
|
60
|
+
}
|
|
61
|
+
this.log.debug(`Parsed density value was NaN: "${out}"`);
|
|
62
|
+
}
|
|
63
|
+
// couldn't get anything, so error out
|
|
64
|
+
throw this.log.errorAndThrow('Failed to get display density property.');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @this {import('../driver').AndroidDriver}
|
|
69
|
+
* @returns {Promise<StringRecord>}
|
|
70
|
+
*/
|
|
71
|
+
export async function mobileGetNotifications() {
|
|
72
|
+
return await this.settingsApp.getNotifications();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @this {import('../driver').AndroidDriver}
|
|
77
|
+
* @returns {Promise<import('./types').SmsListResult>}
|
|
78
|
+
*/
|
|
79
|
+
export async function mobileListSms(opts) {
|
|
80
|
+
return await this.settingsApp.getSmsList(opts);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @this {import('../driver').AndroidDriver}
|
|
85
|
+
* @returns {Promise<void>}
|
|
86
|
+
*/
|
|
87
|
+
export async function openNotifications() {
|
|
88
|
+
throw new errors.NotImplementedError('Not implemented');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @typedef {import('appium-adb').ADB} ADB
|
|
93
|
+
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
94
|
+
*/
|