io.appium.settings 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/apks/settings_apk-debug.apk +0 -0
  3. package/build/lib/client.d.ts +83 -0
  4. package/build/lib/client.d.ts.map +1 -0
  5. package/build/lib/client.js +137 -0
  6. package/build/lib/client.js.map +1 -0
  7. package/build/lib/commands/animation.d.ts +16 -0
  8. package/build/lib/commands/animation.d.ts.map +1 -0
  9. package/build/lib/commands/animation.js +29 -0
  10. package/build/lib/commands/animation.js.map +1 -0
  11. package/build/lib/commands/clipboard.d.ts +16 -0
  12. package/build/lib/commands/clipboard.d.ts.map +1 -0
  13. package/build/lib/commands/clipboard.js +51 -0
  14. package/build/lib/commands/clipboard.js.map +1 -0
  15. package/build/lib/commands/geolocation.d.ts +70 -0
  16. package/build/lib/commands/geolocation.d.ts.map +1 -0
  17. package/build/lib/commands/geolocation.js +215 -0
  18. package/build/lib/commands/geolocation.js.map +1 -0
  19. package/build/lib/commands/locale.d.ts +13 -0
  20. package/build/lib/commands/locale.d.ts.map +1 -0
  21. package/build/lib/commands/locale.js +31 -0
  22. package/build/lib/commands/locale.js.map +1 -0
  23. package/build/lib/commands/media.d.ts +11 -0
  24. package/build/lib/commands/media.d.ts.map +1 -0
  25. package/build/lib/commands/media.js +35 -0
  26. package/build/lib/commands/media.js.map +1 -0
  27. package/build/lib/commands/network.d.ts +19 -0
  28. package/build/lib/commands/network.d.ts.map +1 -0
  29. package/build/lib/commands/network.js +68 -0
  30. package/build/lib/commands/network.js.map +1 -0
  31. package/build/lib/commands/notifications.d.ts +50 -0
  32. package/build/lib/commands/notifications.d.ts.map +1 -0
  33. package/build/lib/commands/notifications.js +77 -0
  34. package/build/lib/commands/notifications.js.map +1 -0
  35. package/build/lib/commands/sms.d.ts +90 -0
  36. package/build/lib/commands/sms.d.ts.map +1 -0
  37. package/build/lib/commands/sms.js +95 -0
  38. package/build/lib/commands/sms.js.map +1 -0
  39. package/build/lib/commands/typing.d.ts +23 -0
  40. package/build/lib/commands/typing.d.ts.map +1 -0
  41. package/build/lib/commands/typing.js +51 -0
  42. package/build/lib/commands/typing.js.map +1 -0
  43. package/build/lib/commands/utf7.d.ts +26 -0
  44. package/build/lib/commands/utf7.d.ts.map +1 -0
  45. package/build/lib/commands/utf7.js +144 -0
  46. package/build/lib/commands/utf7.js.map +1 -0
  47. package/build/lib/constants.d.ts +23 -0
  48. package/build/lib/constants.d.ts.map +1 -0
  49. package/build/lib/constants.js +26 -0
  50. package/build/lib/constants.js.map +1 -0
  51. package/build/lib/logger.d.ts +3 -0
  52. package/build/lib/logger.d.ts.map +1 -0
  53. package/build/lib/logger.js +17 -0
  54. package/build/lib/logger.js.map +1 -0
  55. package/index.js +6 -2
  56. package/lib/client.js +155 -0
  57. package/lib/commands/animation.js +24 -0
  58. package/lib/commands/clipboard.js +47 -0
  59. package/lib/commands/geolocation.js +214 -0
  60. package/lib/commands/locale.js +28 -0
  61. package/lib/commands/media.js +27 -0
  62. package/lib/commands/network.js +73 -0
  63. package/lib/commands/notifications.js +71 -0
  64. package/lib/commands/sms.js +92 -0
  65. package/lib/commands/typing.js +46 -0
  66. package/lib/commands/utf7.js +154 -0
  67. package/lib/constants.js +31 -0
  68. package/lib/logger.js +14 -0
  69. package/package.json +44 -8
@@ -0,0 +1,92 @@
1
+ import { LOG_PREFIX } from '../logger.js';
2
+ import { SMS_LIST_RECEIVER, SMS_LIST_RETRIEVAL_ACTION } from '../constants.js';
3
+
4
+ /**
5
+ * @typedef {Object} SmsListOptions
6
+ * @property {number} [max=100] - The maximum count of recent messages
7
+ * to retrieve
8
+ */
9
+
10
+ /**
11
+ * @typedef SmsListResult
12
+ * @property {SmsListResultItem[]} items
13
+ * @property {number} total
14
+ */
15
+
16
+ /**
17
+ * @privateRemarks XXX: WAG
18
+ * @typedef SmsListResultItem
19
+ * @property {string} id
20
+ * @property {string} address
21
+ * @property {string|null} person
22
+ * @property {string} date
23
+ * @property {string} read
24
+ * @property {string} status
25
+ * @property {string} type
26
+ * @property {string|null} subject
27
+ * @property {string} body
28
+ * @property {string|null} serviceCenter
29
+ */
30
+
31
+ /**
32
+ * Retrieves the list of the most recent SMS
33
+ * properties list via Appium Settings helper.
34
+ * Messages are sorted by date in descending order.
35
+ *
36
+ * @this {import('../client').SettingsApp}
37
+ * @param {SmsListOptions} opts
38
+ * @returns {Promise<SmsListResult>} The example output is:
39
+ * ```json
40
+ * {
41
+ * "items":[
42
+ * {
43
+ * "id":"2",
44
+ * "address":"+123456789",
45
+ * "person":null,
46
+ * "date":"1581936422203",
47
+ * "read":"0",
48
+ * "status":"-1",
49
+ * "type":"1",
50
+ * "subject":null,
51
+ * "body":"\"text message2\"",
52
+ * "serviceCenter":null
53
+ * },
54
+ * {
55
+ * "id":"1",
56
+ * "address":"+123456789",
57
+ * "person":null,
58
+ * "date":"1581936382740",
59
+ * "read":"0",
60
+ * "status":"-1",
61
+ * "type":"1",
62
+ * "subject":null,
63
+ * "body":"\"text message\"",
64
+ * "serviceCenter":null
65
+ * }
66
+ * ],
67
+ * "total":2
68
+ * }
69
+ * ```
70
+ * @throws {Error} If there was an error while getting the SMS list
71
+ */
72
+ export async function getSmsList (opts = {}) {
73
+ this.log.debug(LOG_PREFIX, 'Retrieving the recent SMS messages');
74
+ await this.requireRunning({shouldRestoreCurrentApp: true});
75
+ const args = [
76
+ 'am', 'broadcast',
77
+ '-n', SMS_LIST_RECEIVER,
78
+ '-a', SMS_LIST_RETRIEVAL_ACTION,
79
+ ];
80
+ if (opts.max) {
81
+ args.push('--es', 'max', `${opts.max}`);
82
+ }
83
+ let output;
84
+ try {
85
+ output = await this.adb.shell(args);
86
+ } catch (err) {
87
+ throw new Error(`Cannot retrieve SMS list from the device. ` +
88
+ `Make sure the Appium Settings application is installed and is up to date. ` +
89
+ `Original error: ${err.message}`);
90
+ }
91
+ return this._parseJsonData(output, 'SMS list');
92
+ };
@@ -0,0 +1,46 @@
1
+ import _ from 'lodash';
2
+ import { APPIUM_IME, UNICODE_IME } from '../constants.js';
3
+ import { imap } from './utf7';
4
+ import { LOG_PREFIX } from '../logger.js';
5
+
6
+ /**
7
+ * Performs the given editor action on the focused input field.
8
+ * This method requires Appium Settings helper to be installed on the device.
9
+ * No exception is thrown if there was a failure while performing the action.
10
+ * You must investigate the logcat output if something did not work as expected.
11
+ *
12
+ * @this {import('../client').SettingsApp}
13
+ * @param {string|number} action - Either action code or name. The following action
14
+ * names are supported: `normal, unspecified, none,
15
+ * go, search, send, next, done, previous`
16
+ */
17
+ export async function performEditorAction (action) {
18
+ this.log.debug(LOG_PREFIX, `Performing editor action: ${action}`);
19
+ await this.adb.runInImeContext(APPIUM_IME,
20
+ async () => await this.adb.shell(['input', 'text', `/${action}/`]));
21
+ };
22
+
23
+ /**
24
+ * Types the given Unicode string.
25
+ * It is expected that the focus is already put
26
+ * to the destination input field before this method is called.
27
+ *
28
+ * @this {import('../client').SettingsApp}
29
+ * @param {string} text The string to type
30
+ * @returns {Promise<boolean>} `true` if the input text has been successfully sent to adb
31
+ */
32
+ export async function typeUnicode (text) {
33
+ if (_.isNil(text)) {
34
+ return false;
35
+ }
36
+
37
+ text = `${text}`;
38
+ this.log.debug(LOG_PREFIX, `Typing ${text.length} character${text.length === 1 ? '' : 's'}`);
39
+ if (!text) {
40
+ return false;
41
+ }
42
+ await this.adb.runInImeContext(
43
+ UNICODE_IME, async () => await this.adb.inputText(imap.encode(text))
44
+ );
45
+ return true;
46
+ };
@@ -0,0 +1,154 @@
1
+ /*
2
+ * The code below has been adopted from https://www.npmjs.com/package/utf7
3
+ */
4
+
5
+ /**
6
+ * @param {number} length
7
+ * @returns {Buffer}
8
+ */
9
+ function allocateAsciiBuffer(length) {
10
+ return Buffer.alloc(length, 'ascii');
11
+ }
12
+
13
+ /**
14
+ * @param {string} str
15
+ * @returns {string}
16
+ */
17
+ function _encode(str) {
18
+ const b = allocateAsciiBuffer(str.length * 2);
19
+ for (let i = 0, bi = 0; i < str.length; i++) {
20
+ // Note that we can't simply convert a UTF-8 string to Base64 because
21
+ // UTF-8 uses a different encoding. In modified UTF-7, all characters
22
+ // are represented by their two byte Unicode ID.
23
+ const c = str.charCodeAt(i);
24
+ // Upper 8 bits shifted into lower 8 bits so that they fit into 1 byte.
25
+ b[bi++] = c >> 8;
26
+ // Lower 8 bits. Cut off the upper 8 bits so that they fit into 1 byte.
27
+ b[bi++] = c & 0xFF;
28
+ }
29
+ // Modified Base64 uses , instead of / and omits trailing =.
30
+ return b.toString('base64').replace(/=+$/, '');
31
+ }
32
+
33
+ /**
34
+ * @param {string} str
35
+ * @returns {Buffer}
36
+ */
37
+ function allocateBase64Buffer(str) {
38
+ return Buffer.from(str, 'base64');
39
+ }
40
+
41
+ /**
42
+ * @param {string} str
43
+ * @returns {string}
44
+ */
45
+ function _decode(str) {
46
+ const b = allocateBase64Buffer(str);
47
+ const r = [];
48
+ for (let i = 0; i < b.length;) {
49
+ // Calculate charcode from two adjacent bytes.
50
+ r.push(String.fromCharCode(b[i++] << 8 | b[i++]));
51
+ }
52
+ return r.join('');
53
+ }
54
+
55
+ /**
56
+ * Escape RegEx from http://simonwillison.net/2006/Jan/20/escape/
57
+ *
58
+ * @param {string} chars
59
+ * @returns {string}
60
+ */
61
+ function escape(chars) {
62
+ return chars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
63
+ }
64
+
65
+ // Character classes defined by RFC 2152.
66
+ const setD = 'A-Za-z0-9' + escape(`'(),-./:?`);
67
+ const setO = escape(`!"#$%&*;<=>@[]^_'{|}`);
68
+ const setW = escape(` \r\n\t`);
69
+
70
+ // Stores compiled regexes for various replacement pattern.
71
+ /** @type {Record<string, RegExp>} */
72
+ const regexes = {};
73
+ const regexAll = new RegExp(`[^${setW}${setD}${setO}]+`, 'g');
74
+
75
+ export const imap = {};
76
+
77
+ /**
78
+ * RFC 2152 UTF-7 encoding.
79
+ *
80
+ * @param {string} str
81
+ * @param {string?} mask
82
+ * @returns {string}
83
+ */
84
+ export const encode = function encode(str, mask = null) {
85
+ // Generate a RegExp object from the string of mask characters.
86
+ if (!mask) {
87
+ mask = '';
88
+ }
89
+ if (!regexes[mask]) {
90
+ regexes[mask] = new RegExp(`[^${setD}${escape(mask)}]+`, 'g');
91
+ }
92
+
93
+ // We replace subsequent disallowed chars with their escape sequence.
94
+ return str.replace(regexes[mask], (chunk) =>
95
+ // + is represented by an empty sequence +-, otherwise call encode().
96
+ `+${chunk === '+' ? '' : _encode(chunk)}-`
97
+ );
98
+ };
99
+
100
+ /**
101
+ * RFC 2152 UTF-7 encoding with all optionals.
102
+ *
103
+ * @param {string} str
104
+ * @returns {string}
105
+ */
106
+ export function encodeAll(str) {
107
+ // We replace subsequent disallowed chars with their escape sequence.
108
+ return str.replace(regexAll, (chunk) =>
109
+ // + is represented by an empty sequence +-, otherwise call encode().
110
+ `+${chunk === '+' ? '' : _encode(chunk)}-`
111
+ );
112
+ };
113
+
114
+ /**
115
+ * RFC 3501, section 5.1.3 UTF-7 encoding.
116
+ *
117
+ * @param {string} str
118
+ * @returns {string}
119
+ */
120
+ imap.encode = function encode(str) {
121
+ // All printable ASCII chars except for & must be represented by themselves.
122
+ // We replace subsequent non-representable chars with their escape sequence.
123
+ return str.replace(/&/g, '&-').replace(/[^\x20-\x7e]+/g, (chunk) => {
124
+ // & is represented by an empty sequence &-, otherwise call encode().
125
+ chunk = (chunk === '&' ? '' : _encode(chunk)).replace(/\//g, ',');
126
+ return `&${chunk}-`;
127
+ });
128
+ };
129
+
130
+ /**
131
+ * RFC 2152 UTF-7 decoding.
132
+ *
133
+ * @param {string} str
134
+ * @returns {string}
135
+ */
136
+ export const decode = function decode(str) {
137
+ return str.replace(/\+([A-Za-z0-9/]*)-?/gi, (_, chunk) =>
138
+ // &- represents &.
139
+ chunk === '' ? '+' : _decode(chunk)
140
+ );
141
+ };
142
+
143
+ /**
144
+ * RFC 3501, section 5.1.3 UTF-7 decoding.
145
+ *
146
+ * @param {string} str
147
+ * @returns {string}
148
+ */
149
+ imap.decode = function decode(str) {
150
+ return str.replace(/&([^-]*)-/g, (_, chunk) =>
151
+ // &- represents &.
152
+ chunk === '' ? '&' : _decode(chunk.replace(/,/g, '/'))
153
+ );
154
+ };
@@ -0,0 +1,31 @@
1
+ export const SETTINGS_HELPER_ID = 'io.appium.settings';
2
+ export const SETTINGS_HELPER_MAIN_ACTIVITY = '.Settings';
3
+
4
+ export const CLIPBOARD_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.ClipboardReceiver`;
5
+ export const CLIPBOARD_RETRIEVAL_ACTION = `${SETTINGS_HELPER_ID}.clipboard.get`;
6
+
7
+ export const APPIUM_IME = `${SETTINGS_HELPER_ID}/.AppiumIME`;
8
+ export const UNICODE_IME = `${SETTINGS_HELPER_ID}/.UnicodeIME`;
9
+
10
+ export const WIFI_CONNECTION_SETTING_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.WiFiConnectionSettingReceiver`;
11
+ export const WIFI_CONNECTION_SETTING_ACTION = `${SETTINGS_HELPER_ID}.wifi`;
12
+ export const DATA_CONNECTION_SETTING_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.DataConnectionSettingReceiver`;
13
+ export const DATA_CONNECTION_SETTING_ACTION = `${SETTINGS_HELPER_ID}.data_connection`;
14
+
15
+ export const ANIMATION_SETTING_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.AnimationSettingReceiver`;
16
+ export const ANIMATION_SETTING_ACTION = `${SETTINGS_HELPER_ID}.animation`;
17
+
18
+ export const LOCALE_SETTING_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.LocaleSettingReceiver`;
19
+ export const LOCALE_SETTING_ACTION = `${SETTINGS_HELPER_ID}.locale`;
20
+
21
+ export const LOCATION_SERVICE = `${SETTINGS_HELPER_ID}/.LocationService`;
22
+ export const LOCATION_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.LocationInfoReceiver`;
23
+ export const LOCATION_RETRIEVAL_ACTION = `${SETTINGS_HELPER_ID}.location`;
24
+
25
+ export const NOTIFICATIONS_RETRIEVAL_ACTION = `${SETTINGS_HELPER_ID}.notifications`;
26
+
27
+ export const SMS_LIST_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.SmsReader`;
28
+ export const SMS_LIST_RETRIEVAL_ACTION = `${SETTINGS_HELPER_ID}.sms.read`;
29
+
30
+ export const MEDIA_SCAN_RECEIVER = `${SETTINGS_HELPER_ID}/.receivers.MediaScannerReceiver`;
31
+ export const MEDIA_SCAN_ACTION = `${SETTINGS_HELPER_ID}.scan_media`;
package/lib/logger.js ADDED
@@ -0,0 +1,14 @@
1
+ import npmlog from 'npmlog';
2
+
3
+
4
+ export const LOG_PREFIX = 'SettingsApp';
5
+
6
+ function getLogger () {
7
+ const logger = global._global_npmlog || npmlog;
8
+ if (!logger.debug) {
9
+ logger.addLevel('debug', 1000, { fg: 'blue', bg: 'black' }, 'dbug');
10
+ }
11
+ return logger;
12
+ }
13
+
14
+ export const log = getLogger();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "io.appium.settings",
3
- "version": "5.3.0",
3
+ "version": "5.4.0",
4
4
  "description": "App for dealing with Android settings",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -9,10 +9,11 @@
9
9
  "js:lint": "eslint .",
10
10
  "js:lint:fix": "npm run lint -- --fix",
11
11
  "move-apks": "rm -rf apks && mkdir -p apks && cp app/build/outputs/apk/debug/settings_apk-debug.apk apks",
12
- "build": "./gradlew clean assembleDebug && npm run move-apks",
12
+ "build": "tsc -b && ./gradlew clean assembleDebug && npm run move-apks",
13
13
  "prepare": "npm run build",
14
14
  "version": "npm run bump-gradle-version && npm run build",
15
- "clean": "rm -rf node_modules && rm -f package-lock.json && npm install"
15
+ "clean": "npm run build -- --clean",
16
+ "js:test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\""
16
17
  },
17
18
  "repository": {
18
19
  "type": "git",
@@ -29,6 +30,8 @@
29
30
  ],
30
31
  "files": [
31
32
  "index.js",
33
+ "lib",
34
+ "build/lib",
32
35
  "apks",
33
36
  "!.DS_Store",
34
37
  "NOTICE.txt",
@@ -40,14 +43,47 @@
40
43
  "url": "https://github.com/appium/io.appium.settings/issues"
41
44
  },
42
45
  "homepage": "https://github.com/appium/io.appium.settings",
46
+ "dependencies": {
47
+ "asyncbox": "^3.0.0",
48
+ "bluebird": "^3.5.1",
49
+ "lodash": "^4.2.1",
50
+ "npmlog": "^7.0.1",
51
+ "semver": "^7.5.4",
52
+ "source-map-support": "^0.x",
53
+ "teen_process": "^2.0.0"
54
+ },
43
55
  "devDependencies": {
44
- "@appium/eslint-config-appium": "^6.0.0",
45
- "eslint": "^7.32.0",
46
- "fancy-log": "^2.0.0",
47
- "@semantic-release/git": "^10.0.1",
56
+ "@appium/eslint-config-appium": "^8.0.4",
57
+ "@appium/eslint-config-appium-ts": "^0.x",
58
+ "@appium/tsconfig": "^0.x",
59
+ "@appium/types": "^0.x",
48
60
  "@semantic-release/changelog": "^6.0.1",
61
+ "@semantic-release/git": "^10.0.1",
62
+ "@types/bluebird": "^3.5.38",
63
+ "@types/chai": "^4.3.5",
64
+ "@types/chai-as-promised": "^7.1.5",
65
+ "@types/lodash": "^4.14.196",
66
+ "@types/node": "^20.4.7",
67
+ "@types/teen_process": "^2.0.2",
68
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
69
+ "@typescript-eslint/parser": "^6.9.0",
70
+ "appium-adb": "^11.0.0",
71
+ "chai": "^4.1.2",
72
+ "chai-as-promised": "^7.1.1",
49
73
  "conventional-changelog-conventionalcommits": "^7.0.1",
74
+ "eslint": "^8.46.0",
75
+ "eslint-config-prettier": "^9.0.0",
76
+ "eslint-import-resolver-typescript": "^3.5.5",
77
+ "eslint-plugin-import": "^2.28.0",
78
+ "eslint-plugin-mocha": "^10.1.0",
79
+ "eslint-plugin-promise": "^6.1.1",
80
+ "lint-staged": "^15.0.2",
81
+ "mocha": "^10.0.0",
82
+ "pre-commit": "^1.1.3",
83
+ "prettier": "^3.0.0",
50
84
  "semantic-release": "^22.0.5",
51
- "semver": "^7.3.7"
85
+ "sinon": "^17.0.0",
86
+ "ts-node": "^10.9.1",
87
+ "typescript": "^5.1.6"
52
88
  }
53
89
  }