appium-xcuitest-driver 10.10.1 → 10.11.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 (75) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/lib/app-infos-cache.d.ts +29 -31
  3. package/build/lib/app-infos-cache.d.ts.map +1 -1
  4. package/build/lib/app-infos-cache.js +29 -33
  5. package/build/lib/app-infos-cache.js.map +1 -1
  6. package/build/lib/app-utils.d.ts +30 -59
  7. package/build/lib/app-utils.d.ts.map +1 -1
  8. package/build/lib/app-utils.js +158 -211
  9. package/build/lib/app-utils.js.map +1 -1
  10. package/build/lib/commands/battery.d.ts.map +1 -1
  11. package/build/lib/commands/battery.js +4 -8
  12. package/build/lib/commands/battery.js.map +1 -1
  13. package/build/lib/commands/biometric.d.ts.map +1 -1
  14. package/build/lib/commands/biometric.js +1 -5
  15. package/build/lib/commands/biometric.js.map +1 -1
  16. package/build/lib/commands/condition.js +4 -4
  17. package/build/lib/commands/condition.js.map +1 -1
  18. package/build/lib/commands/content-size.js +1 -1
  19. package/build/lib/commands/content-size.js.map +1 -1
  20. package/build/lib/commands/find.js +2 -2
  21. package/build/lib/commands/find.js.map +1 -1
  22. package/build/lib/commands/increase-contrast.js +1 -1
  23. package/build/lib/commands/increase-contrast.js.map +1 -1
  24. package/build/lib/commands/keychains.d.ts.map +1 -1
  25. package/build/lib/commands/keychains.js +1 -5
  26. package/build/lib/commands/keychains.js.map +1 -1
  27. package/build/lib/commands/localization.d.ts.map +1 -1
  28. package/build/lib/commands/localization.js +1 -5
  29. package/build/lib/commands/localization.js.map +1 -1
  30. package/build/lib/commands/pasteboard.d.ts.map +1 -1
  31. package/build/lib/commands/pasteboard.js +10 -8
  32. package/build/lib/commands/pasteboard.js.map +1 -1
  33. package/build/lib/commands/permissions.js +1 -1
  34. package/build/lib/commands/permissions.js.map +1 -1
  35. package/build/lib/css-converter.d.ts +3 -9
  36. package/build/lib/css-converter.d.ts.map +1 -1
  37. package/build/lib/css-converter.js +41 -52
  38. package/build/lib/css-converter.js.map +1 -1
  39. package/build/lib/device/real-device-management.js +14 -14
  40. package/build/lib/device/real-device-management.js.map +1 -1
  41. package/build/lib/device/simulator-management.d.ts.map +1 -1
  42. package/build/lib/device/simulator-management.js +8 -4
  43. package/build/lib/device/simulator-management.js.map +1 -1
  44. package/build/lib/driver.d.ts.map +1 -1
  45. package/build/lib/driver.js +3 -3
  46. package/build/lib/driver.js.map +1 -1
  47. package/build/lib/logger.d.ts +1 -2
  48. package/build/lib/logger.d.ts.map +1 -1
  49. package/build/lib/logger.js +2 -2
  50. package/build/lib/logger.js.map +1 -1
  51. package/build/lib/utils.d.ts +76 -134
  52. package/build/lib/utils.d.ts.map +1 -1
  53. package/build/lib/utils.js +80 -141
  54. package/build/lib/utils.js.map +1 -1
  55. package/lib/{app-infos-cache.js → app-infos-cache.ts} +44 -46
  56. package/lib/{app-utils.js → app-utils.ts} +215 -245
  57. package/lib/commands/battery.js +3 -4
  58. package/lib/commands/biometric.js +1 -2
  59. package/lib/commands/condition.js +1 -1
  60. package/lib/commands/content-size.js +1 -1
  61. package/lib/commands/find.js +1 -1
  62. package/lib/commands/increase-contrast.js +1 -1
  63. package/lib/commands/keychains.js +1 -2
  64. package/lib/commands/localization.js +1 -2
  65. package/lib/commands/pasteboard.js +9 -8
  66. package/lib/commands/permissions.js +1 -1
  67. package/lib/{css-converter.js → css-converter.ts} +75 -88
  68. package/lib/device/real-device-management.ts +1 -1
  69. package/lib/device/simulator-management.ts +9 -4
  70. package/lib/driver.ts +6 -4
  71. package/lib/logger.ts +3 -0
  72. package/lib/{utils.js → utils.ts} +102 -139
  73. package/npm-shrinkwrap.json +26 -30
  74. package/package.json +2 -2
  75. package/lib/logger.js +0 -5
@@ -1,7 +1,6 @@
1
- import _ from 'lodash';
2
1
  import {assertSimulator as _assertSimulator} from '../utils';
3
2
 
4
- const assertSimulator = _.partial(_assertSimulator, 'Biometric enrollment');
3
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Biometric enrollment');
5
4
 
6
5
  /**
7
6
  * Enrolls biometric authentication on a simulated device.
@@ -1,6 +1,6 @@
1
1
  import {INSTRUMENT_CHANNEL, services} from 'appium-ios-device';
2
2
  import _ from 'lodash';
3
- import { isIos18OrNewer } from '../utils.js';
3
+ import { isIos18OrNewer } from '../utils';
4
4
 
5
5
  /**
6
6
  * Get all available ConditionInducer configuration information, which can be used with
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import {assertSimulator as _assertSimulator} from '../utils';
3
3
  import { errors } from 'appium/driver';
4
4
 
5
- const assertSimulator = _.partial(_assertSimulator, 'Content size ui command');
5
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Content size ui command');
6
6
 
7
7
  const CONTENT_SIZE = [
8
8
  'extra-small',
@@ -1,5 +1,5 @@
1
1
  import _ from 'lodash';
2
- import CssConverter from '../css-converter';
2
+ import {CssConverter} from '../css-converter';
3
3
  import {errors} from 'appium/driver';
4
4
  import {util} from 'appium/support';
5
5
 
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import {assertSimulator as _assertSimulator} from '../utils';
3
3
  import { errors } from 'appium/driver';
4
4
 
5
- const assertSimulator = _.partial(_assertSimulator, 'Content size ui command');
5
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Content size ui command');
6
6
 
7
7
  const INCREASE_CONTRAST_CONFIG = [
8
8
  'enabled',
@@ -1,7 +1,6 @@
1
- import _ from 'lodash';
2
1
  import {assertSimulator as _assertSimulator} from '../utils';
3
2
 
4
- const assertSimulator = _.partial(_assertSimulator, 'Keychain modification');
3
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Keychain modification');
5
4
 
6
5
  /**
7
6
  * Clears keychains on a simulated device.
@@ -1,7 +1,6 @@
1
- import _ from 'lodash';
2
1
  import {assertSimulator as _assertSimulator} from '../utils';
3
2
 
4
- const assertSimulator = _.partial(_assertSimulator, 'Localization configuration');
3
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Localization configuration');
5
4
 
6
5
  /**
7
6
  * Change localization settings on the currently booted simulator
@@ -1,3 +1,6 @@
1
+ import _ from 'lodash';
2
+ import { assertSimulator } from '../utils';
3
+
1
4
  /**
2
5
  * Sets the Simulator's pasteboard content to the given value.
3
6
  *
@@ -9,10 +12,8 @@
9
12
  * @this {XCUITestDriver}
10
13
  */
11
14
  export async function mobileSetPasteboard(content, encoding = 'utf8') {
12
- if (!this.isSimulator()) {
13
- throw new Error('Setting pasteboard content is not supported on real devices');
14
- }
15
- if (!content) {
15
+ assertSimulator.call(this, 'Setting pasteboard content');
16
+ if (!_.isString(content)) {
16
17
  // can be empty string
17
18
  throw new Error('Pasteboard content is mandatory to set');
18
19
  }
@@ -31,10 +32,10 @@ export async function mobileSetPasteboard(content, encoding = 'utf8') {
31
32
  * @returns {Promise<string>} The pasteboard content string
32
33
  */
33
34
  export async function mobileGetPasteboard(encoding = 'utf8') {
34
- if (!this.isSimulator()) {
35
- throw new Error('Getting pasteboard content is not supported on real devices');
36
- }
37
- return await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).simctl.getPasteboard(encoding);
35
+ assertSimulator.call(this, 'Getting pasteboard content');
36
+ return await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).simctl.getPasteboard(
37
+ /** @type {BufferEncoding} */ (encoding)
38
+ );
38
39
  }
39
40
 
40
41
  /**
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import {PermissionService} from './enum';
3
3
  import {assertSimulator as _assertSimulator} from '../utils';
4
4
 
5
- const assertSimulator = _.partial(_assertSimulator, 'Permission-related operations');
5
+ const assertSimulator = (driver) => _assertSimulator.call(driver, 'Permission-related operations');
6
6
 
7
7
  /**
8
8
  * Resets the given permission for the active application under test.
@@ -1,9 +1,38 @@
1
1
  import {createParser} from 'css-selector-parser';
2
2
  import _ from 'lodash';
3
3
  import {errors} from 'appium/driver';
4
- import log from './logger.js';
5
-
6
- const CssConverter = {};
4
+ import {log} from './logger';
5
+ import type {
6
+ AstAttribute,
7
+ AstPseudoClass,
8
+ AstRule,
9
+ AstSelector,
10
+ AstClassName,
11
+ AstTagName,
12
+ AstId,
13
+ } from 'css-selector-parser';
14
+
15
+ export const CssConverter = {
16
+ toIosClassChainSelector(cssSelector: string): string {
17
+ let cssObj: AstSelector;
18
+ try {
19
+ cssObj = parseCssSelector(cssSelector);
20
+ } catch (e: any) {
21
+ log.debug(e.stack);
22
+ throw new errors.InvalidSelectorError(
23
+ `Invalid CSS selector '${cssSelector}'. Reason: '${e.message}'`,
24
+ );
25
+ }
26
+ try {
27
+ return parseCssObject(cssObj);
28
+ } catch (e: any) {
29
+ log.debug(e.stack);
30
+ throw new errors.InvalidSelectorError(
31
+ `Unsupported CSS selector '${cssSelector}'. Reason: '${e.message}'`,
32
+ );
33
+ }
34
+ },
35
+ };
7
36
 
8
37
  const parseCssSelector = createParser({
9
38
  syntax: {
@@ -26,18 +55,15 @@ const parseCssSelector = createParser({
26
55
  substitutes: true,
27
56
  });
28
57
 
29
- const BOOLEAN_ATTRS = ['visible', 'accessible', 'accessibility-container', 'enabled'];
58
+ const BOOLEAN_ATTRS = ['visible', 'accessible', 'accessibility-container', 'enabled'] as const;
30
59
 
31
- const NUMERIC_ATTRS = ['index'];
60
+ const NUMERIC_ATTRS = ['index'] as const;
32
61
 
33
- const STR_ATTRS = ['label', 'name', 'value', 'type'];
62
+ const STR_ATTRS = ['label', 'name', 'value', 'type'] as const;
34
63
 
35
64
  const ALL_ATTRS = [...BOOLEAN_ATTRS, ...NUMERIC_ATTRS, ...STR_ATTRS];
36
65
 
37
- /**
38
- * @type {[string, string[]][]}
39
- */
40
- const ATTRIBUTE_ALIASES = [
66
+ const ATTRIBUTE_ALIASES: [string, string[]][] = [
41
67
  ['name', ['id']],
42
68
  ['index', ['nth-child']],
43
69
  ];
@@ -45,10 +71,10 @@ const ATTRIBUTE_ALIASES = [
45
71
  /**
46
72
  * Convert hyphen separated word to camel case
47
73
  *
48
- * @param {string?} str
49
- * @returns {string} The hyphen separated word translated to camel case
74
+ * @param str
75
+ * @returns The hyphen separated word translated to camel case
50
76
  */
51
- function toCamelCase(str) {
77
+ function toCamelCase(str: string | null | undefined): string {
52
78
  if (!str) {
53
79
  return '';
54
80
  }
@@ -62,12 +88,11 @@ function toCamelCase(str) {
62
88
  /**
63
89
  * Get the boolean from a CSS object. If empty, return true. If not true/false/empty, throw exception
64
90
  *
65
- * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssAttr
66
- * @returns {string} Either 'true' or 'false'. If value is empty, return 'true'
91
+ * @param cssAttr
92
+ * @returns Either 'true' or 'false'. If value is empty, return 'true'
67
93
  */
68
- function requireBoolean(cssAttr) {
69
- // @ts-ignore We only support strings
70
- const attrValue = cssAttr.value?.value;
94
+ function requireBoolean(cssAttr: AstAttribute | AstPseudoClass): string {
95
+ const attrValue = (cssAttr as any).value?.value;
71
96
  const val = _.toLower(attrValue) || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
72
97
  switch (val) {
73
98
  case '0':
@@ -89,14 +114,14 @@ function requireBoolean(cssAttr) {
89
114
  * Converts to lowercase and if an attribute name is an alias for something else, return
90
115
  * what it is an alias for
91
116
  *
92
- * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssEntity
93
- * @returns {string} The canonical attribute name
117
+ * @param cssEntity
118
+ * @returns The canonical attribute name
94
119
  */
95
- function requireEntityName(cssEntity) {
120
+ function requireEntityName(cssEntity: AstAttribute | AstPseudoClass): string {
96
121
  const entityName = cssEntity.name.toLowerCase();
97
122
 
98
123
  // Check if it's supported and if it is, return it
99
- if (ALL_ATTRS.includes(entityName)) {
124
+ if (ALL_ATTRS.includes(entityName as any)) {
100
125
  return entityName.toLowerCase();
101
126
  }
102
127
 
@@ -115,12 +140,11 @@ function requireEntityName(cssEntity) {
115
140
  /**
116
141
  * Convert a CSS attribute into a UiSelector method call
117
142
  *
118
- * @param {import('css-selector-parser').AstAttribute} cssAttr CSS attribute object
119
- * @returns {string|{index: string|undefined}} CSS attribute parsed as UiSelector
143
+ * @param cssAttr CSS attribute object
144
+ * @returns CSS attribute parsed as UiSelector
120
145
  */
121
- function parseAttr(cssAttr) {
122
- // @ts-ignore We only care for strings
123
- const attrValue = cssAttr.value?.value;
146
+ function parseAttr(cssAttr: AstAttribute): string | {index: string | undefined} {
147
+ const attrValue = (cssAttr as any).value?.value;
124
148
  if (!_.isString(attrValue) && !_.isEmpty(attrValue)) {
125
149
  throw new TypeError(
126
150
  `'${cssAttr.name}=${attrValue}' is an invalid attribute. ` +
@@ -130,7 +154,7 @@ function parseAttr(cssAttr) {
130
154
  const attrName = toCamelCase(requireEntityName(cssAttr));
131
155
 
132
156
  // Validate that it's a supported attribute
133
- if (!STR_ATTRS.includes(attrName) && !BOOLEAN_ATTRS.includes(attrName)) {
157
+ if (!STR_ATTRS.includes(attrName as any) && !BOOLEAN_ATTRS.includes(attrName as any)) {
134
158
  throw new Error(
135
159
  `'${attrName}' is not supported. Supported attributes are ` +
136
160
  `'${[...STR_ATTRS, ...BOOLEAN_ATTRS].join(', ')}'`,
@@ -141,11 +165,11 @@ function parseAttr(cssAttr) {
141
165
  if (attrName === 'index') {
142
166
  return {index: attrValue};
143
167
  }
144
- if (BOOLEAN_ATTRS.includes(attrName)) {
168
+ if (BOOLEAN_ATTRS.includes(attrName as any)) {
145
169
  return `${attrName} == ${requireBoolean(cssAttr)}`;
146
170
  }
147
171
 
148
- let value = attrValue || '';
172
+ const value = attrValue || '';
149
173
  if (value === '') {
150
174
  return `[${attrName} LIKE ${value}]`;
151
175
  }
@@ -173,12 +197,11 @@ function parseAttr(cssAttr) {
173
197
  /**
174
198
  * Convert a CSS pseudo class to a UiSelector
175
199
  *
176
- * @param {import('css-selector-parser').AstPseudoClass} cssPseudo
177
- * @returns {string|{index: string|undefined}|undefined} Pseudo selector parsed as UiSelector
200
+ * @param cssPseudo
201
+ * @returns Pseudo selector parsed as UiSelector
178
202
  */
179
- function parsePseudo(cssPseudo) {
180
- // @ts-ignore We only care for strings
181
- const argValue = cssPseudo.argument?.value;
203
+ function parsePseudo(cssPseudo: AstPseudoClass): string | {index: string | undefined} | undefined {
204
+ const argValue = (cssPseudo as any).argument?.value;
182
205
  if (!_.isString(argValue) && !_.isEmpty(argValue)) {
183
206
  throw new TypeError(
184
207
  `'${cssPseudo.name}=${argValue}'. ` +
@@ -188,7 +211,7 @@ function parsePseudo(cssPseudo) {
188
211
 
189
212
  const pseudoName = requireEntityName(cssPseudo);
190
213
 
191
- if (BOOLEAN_ATTRS.includes(pseudoName)) {
214
+ if (BOOLEAN_ATTRS.includes(pseudoName as any)) {
192
215
  return `${toCamelCase(pseudoName)} == ${requireBoolean(cssPseudo)}`;
193
216
  }
194
217
 
@@ -199,9 +222,9 @@ function parsePseudo(cssPseudo) {
199
222
 
200
223
  /**
201
224
  * Convert a CSS rule to a UiSelector
202
- * @param {import('css-selector-parser').AstRule} cssRule CSS rule definition
225
+ * @param cssRule CSS rule definition
203
226
  */
204
- function parseCssRule(cssRule) {
227
+ function parseCssRule(cssRule: AstRule): string {
205
228
  if (cssRule.combinator && ![' ', '>'].includes(cssRule.combinator)) {
206
229
  throw new Error(
207
230
  `'${cssRule.combinator}' is not a supported combinator. ` +
@@ -210,9 +233,7 @@ function parseCssRule(cssRule) {
210
233
  }
211
234
 
212
235
  let iosClassChainSelector = '';
213
- const astClassNames = /** @type {import('css-selector-parser').AstClassName[]} */ (
214
- cssRule.items.filter(({type}) => type === 'ClassName')
215
- );
236
+ const astClassNames = cssRule.items.filter(({type}) => type === 'ClassName') as AstClassName[];
216
237
  const classNames = astClassNames.map(({name}) => name);
217
238
  if (classNames.length) {
218
239
  throw new errors.InvalidSelectorError(`'${[cssRule || '', ...classNames].join('.')}'
@@ -220,9 +241,7 @@ function parseCssRule(cssRule) {
220
241
  dots separating them`);
221
242
  }
222
243
 
223
- const astTag = /** @type {import('css-selector-parser').AstTagName|undefined} */ (
224
- cssRule.items.find(({type}) => type === 'TagName')
225
- );
244
+ const astTag = cssRule.items.find(({type}) => type === 'TagName') as AstTagName | undefined;
226
245
  let tagName = astTag?.name ?? '';
227
246
  if (tagName && tagName !== '*' && !_.startsWith(_.toLower(tagName), 'xcuielementtype')) {
228
247
  const capitalizedTagName = tagName.charAt(0).toUpperCase() + tagName.slice(1);
@@ -230,36 +249,31 @@ function parseCssRule(cssRule) {
230
249
  }
231
250
  iosClassChainSelector += tagName || '*';
232
251
 
233
- /** @type {(string|{index: string|undefined}|undefined)[]} */
234
- const attrs = [];
252
+ const attrs: (string | {index: string | undefined} | undefined)[] = [];
235
253
 
236
- const astIds = /** @type {import('css-selector-parser').AstId[]} */ (
237
- cssRule.items.filter(({type}) => type === 'Id')
238
- );
254
+ const astIds = cssRule.items.filter(({type}) => type === 'Id') as AstId[];
239
255
  const ids = astIds.map(({name}) => name);
240
256
  if (ids.length) {
241
257
  attrs.push(`name == "${ids[0]}"`);
242
258
  }
243
- const attributes = /** @type {import('css-selector-parser').AstAttribute[]} */ (
244
- cssRule.items.filter(({type}) => type === 'Attribute')
245
- );
259
+ const attributes = cssRule.items.filter(({type}) => type === 'Attribute') as AstAttribute[];
246
260
  for (const attr of attributes) {
247
261
  attrs.push(parseAttr(attr));
248
262
  }
249
- const pseudoClasses = /** @type {import('css-selector-parser').AstPseudoClass[]} */ (
250
- cssRule.items.filter(({type}) => type === 'PseudoClass')
251
- );
263
+ const pseudoClasses = cssRule.items.filter(({type}) => type === 'PseudoClass') as AstPseudoClass[];
252
264
  for (const pseudo of pseudoClasses) {
253
265
  attrs.push(parsePseudo(pseudo));
254
266
  }
255
- const nonIndexAttrs = attrs.filter((attr) => _.isString(attr));
267
+ const nonIndexAttrs = attrs.filter((attr) => _.isString(attr)) as string[];
256
268
  if (!_.isEmpty(nonIndexAttrs)) {
257
269
  iosClassChainSelector += `[\`${nonIndexAttrs.join(' AND ')}\`]`;
258
270
  }
259
271
 
260
- const indexAttr = attrs.find((attr) => _.isObject(attr) && attr.index);
272
+ const indexAttr = attrs.find(
273
+ (attr) => _.isObject(attr) && (attr as {index: string}).index
274
+ ) as {index: string} | undefined;
261
275
  if (indexAttr) {
262
- iosClassChainSelector += `[${/** @type { {index: string} } */ (indexAttr).index}]`;
276
+ iosClassChainSelector += `[${indexAttr.index}]`;
263
277
  }
264
278
 
265
279
  if (cssRule.nestedRule) {
@@ -272,40 +286,13 @@ function parseCssRule(cssRule) {
272
286
  /**
273
287
  * Convert CSS object to iOS Class Chain selector
274
288
  *
275
- * @param {import('css-selector-parser').AstSelector} css CSS object
276
- * @returns {string} The CSS object parsed as a UiSelector
289
+ * @param css CSS object
290
+ * @returns The CSS object parsed as a UiSelector
277
291
  */
278
- function parseCssObject(css) {
292
+ function parseCssObject(css: AstSelector): string {
279
293
  if (!_.isEmpty(css.rules)) {
280
294
  return parseCssRule(css.rules[0]);
281
295
  }
282
296
 
283
297
  throw new Error('No rules could be parsed out of the current selector');
284
298
  }
285
-
286
- /**
287
- * Convert a CSS selector to a iOS Class Chain selector
288
- * @param {string} cssSelector CSS Selector
289
- * @returns {string} The CSS selector converted to an iOS Class Chain
290
- */
291
- CssConverter.toIosClassChainSelector = function toIosClassChainSelector(cssSelector) {
292
- let cssObj;
293
- try {
294
- cssObj = parseCssSelector(cssSelector);
295
- } catch (e) {
296
- log.debug(e.stack);
297
- throw new errors.InvalidSelectorError(
298
- `Invalid CSS selector '${cssSelector}'. Reason: '${e.message}'`,
299
- );
300
- }
301
- try {
302
- return parseCssObject(cssObj);
303
- } catch (e) {
304
- log.debug(e.stack);
305
- throw new errors.InvalidSelectorError(
306
- `Unsupported CSS selector '${cssSelector}'. Reason: '${e.message}'`,
307
- );
308
- }
309
- };
310
-
311
- export default CssConverter;
@@ -4,7 +4,7 @@ import {fs, tempDir, mkdirp, zip, util, timing} from 'appium/support';
4
4
  import path from 'path';
5
5
  import {services, utilities, INSTRUMENT_CHANNEL} from 'appium-ios-device';
6
6
  import {buildSafariPreferences, SAFARI_BUNDLE_ID} from '../app-utils';
7
- import defaultLogger from '../logger';
7
+ import {log as defaultLogger} from '../logger';
8
8
  import { Devicectl } from 'node-devicectl';
9
9
  import type { AppiumLogger } from '@appium/types';
10
10
  import type { XCUITestDriver } from '../driver';
@@ -6,6 +6,7 @@ import {util, timing} from 'appium/support';
6
6
  import {UDID_AUTO, normalizePlatformName} from '../utils';
7
7
  import {buildSafariPreferences} from '../app-utils';
8
8
  import type { XCUITestDriver } from '../driver';
9
+ import type { DeviceInfo } from 'node-simctl';
9
10
 
10
11
  const APPIUM_SIM_PREFIX = 'appiumTest';
11
12
 
@@ -19,11 +20,15 @@ export async function createSim(this: XCUITestDriver): Promise<Simulator> {
19
20
  const platform = normalizePlatformName(this.opts.platformName);
20
21
  const simctl = new Simctl({devicesSetPath});
21
22
  if (!deviceName) {
22
- let deviceNames: string | string[] = 'none';
23
+ let deviceNames: string[] = [];
23
24
  try {
24
- deviceNames = (await simctl
25
- .getDevices(platformVersion, platform))
26
- .map(({deviceName}) => deviceName);
25
+ const devices = platformVersion
26
+ ? await simctl.getDevices(platformVersion, platform)
27
+ : await simctl.getDevices(null, platform);
28
+ const nameMapper = (device: DeviceInfo) => device.name;
29
+ deviceNames = Array.isArray(devices)
30
+ ? devices.map(nameMapper)
31
+ : _.flatMap(_.values(devices)).map(nameMapper);
27
32
  } catch {}
28
33
  throw new Error(
29
34
  `'deviceName' must be provided in order to create a new Simulator for ${platform} platform. ` +
package/lib/driver.ts CHANGED
@@ -601,7 +601,7 @@ export class XCUITestDriver
601
601
  this.opts.useNewWDA = util.hasValue(this.opts.useNewWDA) ? this.opts.useNewWDA : false;
602
602
 
603
603
  if (caps.commandTimeouts) {
604
- caps.commandTimeouts = normalizeCommandTimeouts(caps.commandTimeouts);
604
+ caps.commandTimeouts = normalizeCommandTimeouts(caps.commandTimeouts as string | Record<string, number>);
605
605
  }
606
606
 
607
607
  if (_.isString(caps.webDriverAgentUrl)) {
@@ -1547,9 +1547,11 @@ export class XCUITestDriver
1547
1547
  };
1548
1548
  }
1549
1549
 
1550
- const appBundleVersion = this.isRealDevice()
1551
- ? (await (this.device as RealDevice).fetchAppInfo(bundleId))?.CFBundleVersion
1552
- : BUNDLE_VERSION_PATTERN.exec(await (this.device as Simulator).simctl.appInfo(bundleId))?.[1];
1550
+ const appBundleVersion = (
1551
+ this.isRealDevice()
1552
+ ? (await (this.device as RealDevice).fetchAppInfo(bundleId))
1553
+ : (await (this.device as Simulator).simctl.appInfo(bundleId))
1554
+ )?.CFBundleVersion;
1553
1555
  this.log.debug(`CFBundleVersion from installed app info: ${appBundleVersion}`);
1554
1556
  if (!appBundleVersion) {
1555
1557
  return {
package/lib/logger.ts ADDED
@@ -0,0 +1,3 @@
1
+ import {logger} from 'appium/support';
2
+
3
+ export const log = logger.getLogger('XCUITest');