appium-xcuitest-driver 4.32.3 → 4.32.4

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 CHANGED
@@ -1,3 +1,10 @@
1
+ ## [4.32.4](https://github.com/appium/appium-xcuitest-driver/compare/v4.32.3...v4.32.4) (2023-06-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **deps:** update dependency css-selector-parser to v2 ([#1759](https://github.com/appium/appium-xcuitest-driver/issues/1759)) ([0426349](https://github.com/appium/appium-xcuitest-driver/commit/0426349da313127111c19d4de44151ab45ecb64f))
7
+
1
8
  ## [4.32.3](https://github.com/appium/appium-xcuitest-driver/compare/v4.32.2...v4.32.3) (2023-06-16)
2
9
 
3
10
 
@@ -1,79 +1,4 @@
1
1
  export default CssConverter;
2
- export type CssNameValueObject = {
3
- /**
4
- * The name of the CSS object
5
- */
6
- name?: string | undefined;
7
- /**
8
- * The value of the CSS object
9
- */
10
- value?: string | undefined;
11
- };
12
- export type CssAttr = {
13
- name?: string | undefined;
14
- /**
15
- * Type of attribute (must be string or empty)
16
- */
17
- valueType?: string | undefined;
18
- /**
19
- * Value of the attribute
20
- */
21
- value?: string | undefined;
22
- /**
23
- * The operator between value and value type (=, *=, , ^=, $=)
24
- */
25
- operator?: string | undefined;
26
- };
27
- export type CssPseudo = {
28
- /**
29
- * The type of CSS pseudo selector (https://www.npmjs.com/package/css-selector-parser for reference)
30
- */
31
- valueType?: string | undefined;
32
- /**
33
- * The name of the pseudo selector
34
- */
35
- name?: string | undefined;
36
- /**
37
- * The value of the pseudo selector
38
- */
39
- value?: string | undefined;
40
- };
41
- export type CssRule = {
42
- /**
43
- * The nesting operator (aka: combinator https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)
44
- */
45
- nestingOperator?: string | undefined;
46
- /**
47
- * The tag name (aka: type selector https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
48
- */
49
- tagName?: string | undefined;
50
- /**
51
- * An array of CSS class names
52
- */
53
- classNames?: string[] | undefined;
54
- /**
55
- * An array of CSS attributes
56
- */
57
- attrs?: CssAttr[] | undefined;
58
- /**
59
- * An array of CSS pseudos
60
- */
61
- pseudos?: CssPseudo[] | undefined;
62
- /**
63
- * CSS identifier
64
- */
65
- id?: string | undefined;
66
- /**
67
- * A descendant of this CSS rule
68
- */
69
- rule?: CssRule | undefined;
70
- };
71
- export type CssObject = {
72
- /**
73
- * Type of CSS object. 'rule', 'ruleset' or 'selectors'
74
- */
75
- type?: string | undefined;
76
- };
77
2
  declare namespace CssConverter {
78
3
  /**
79
4
  * Convert a CSS selector to a iOS Class Chain selector
@@ -1 +1 @@
1
- {"version":3,"file":"css-converter.d.ts","sourceRoot":"","sources":["../../lib/css-converter.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmSA;;;;OAIG;IACH,8DAYC"}
1
+ {"version":3,"file":"css-converter.d.ts","sourceRoot":"","sources":["../../lib/css-converter.js"],"names":[],"mappings":";;IAoQA;;;;OAIG;IACH,8DAcC"}
@@ -6,12 +6,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const css_selector_parser_1 = require("css-selector-parser");
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
8
  const driver_1 = require("appium/driver");
9
+ const logger_js_1 = __importDefault(require("./logger.js"));
9
10
  const CssConverter = {};
10
- const parser = new css_selector_parser_1.CssSelectorParser();
11
- parser.registerSelectorPseudos('has');
12
- parser.registerNestingOperators('>', '+', '~');
13
- parser.registerAttrEqualityMods('^', '$', '*', '~');
14
- parser.enableSubstitutes();
11
+ const parseCssSelector = (0, css_selector_parser_1.createParser)({
12
+ syntax: {
13
+ pseudoClasses: {
14
+ unknown: 'accept',
15
+ definitions: {
16
+ Selector: ['has'],
17
+ }
18
+ },
19
+ combinators: ['>', '+', '~'],
20
+ attributes: {
21
+ operators: ['^=', '$=', '*=', '~=', '=']
22
+ },
23
+ ids: true,
24
+ classNames: true,
25
+ tag: {
26
+ wildcard: true
27
+ },
28
+ },
29
+ substitutes: true
30
+ });
15
31
  const BOOLEAN_ATTRS = [
16
32
  'visible', 'accessible', 'accessibility-container', 'enabled',
17
33
  ];
@@ -36,7 +52,7 @@ const ATTRIBUTE_ALIASES = [
36
52
  /**
37
53
  * Convert hyphen separated word to camel case
38
54
  *
39
- * @param {string} str
55
+ * @param {string?} str
40
56
  * @returns {string} The hyphen separated word translated to camel case
41
57
  */
42
58
  function toCamelCase(str) {
@@ -47,19 +63,16 @@ function toCamelCase(str) {
47
63
  const out = tokens.join('');
48
64
  return out.charAt(0).toLowerCase() + out.slice(1);
49
65
  }
50
- /**
51
- * @typedef {Object} CssNameValueObject
52
- * @property {string} [name] The name of the CSS object
53
- * @property {string} [value] The value of the CSS object
54
- */
55
66
  /**
56
67
  * Get the boolean from a CSS object. If empty, return true. If not true/false/empty, throw exception
57
68
  *
58
- * @param {CssNameValueObject} css A CSS object that has 'name' and 'value'
69
+ * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssAttr
59
70
  * @returns {string} Either 'true' or 'false'. If value is empty, return 'true'
60
71
  */
61
- function requireBoolean(css) {
62
- const val = css.value?.toLowerCase() || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
72
+ function requireBoolean(cssAttr) {
73
+ // @ts-ignore We only support strings
74
+ const attrValue = cssAttr.value?.value;
75
+ const val = lodash_1.default.toLower(attrValue) || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
63
76
  switch (val) {
64
77
  case '0':
65
78
  case 'false':
@@ -68,7 +81,7 @@ function requireBoolean(css) {
68
81
  case 'true':
69
82
  return '1';
70
83
  default:
71
- throw new TypeError(`'${css.name}' must be true, false or empty. Found '${css.value}'`);
84
+ throw new TypeError(`'${cssAttr.name}' must be true/1 or false/0 or empty. Found '${attrValue}'`);
72
85
  }
73
86
  }
74
87
  /**
@@ -77,43 +90,38 @@ function requireBoolean(css) {
77
90
  * Converts to lowercase and if an attribute name is an alias for something else, return
78
91
  * what it is an alias for
79
92
  *
80
- * @param {Object} css CSS object
93
+ * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssEntity
81
94
  * @returns {string} The canonical attribute name
82
95
  */
83
- function requireAttributeName(css) {
84
- const attrName = css.name.toLowerCase();
96
+ function requireEntityName(cssEntity) {
97
+ const entityName = cssEntity.name.toLowerCase();
85
98
  // Check if it's supported and if it is, return it
86
- if (ALL_ATTRS.includes(attrName)) {
87
- return attrName.toLowerCase();
99
+ if (ALL_ATTRS.includes(entityName)) {
100
+ return entityName.toLowerCase();
88
101
  }
89
102
  // If attrName is an alias for something else, return that
90
103
  for (const [officialAttr, aliasAttrs] of ATTRIBUTE_ALIASES) {
91
- if (aliasAttrs.includes(attrName)) {
104
+ if (aliasAttrs.includes(entityName)) {
92
105
  return officialAttr;
93
106
  }
94
107
  }
95
- throw new Error(`'${attrName}' is not a valid attribute. ` +
96
- `Supported attributes are '${ALL_ATTRS.join(', ')}'`);
108
+ throw new Error(`'${entityName}' is not a valid attribute. ` +
109
+ `Supported attributes are: '${ALL_ATTRS.join(', ')}'`);
97
110
  }
98
- /**
99
- * @typedef {Object} CssAttr
100
- * @property {string} [name]
101
- * @property {string} [valueType] Type of attribute (must be string or empty)
102
- * @property {string} [value] Value of the attribute
103
- * @property {string} [operator] The operator between value and value type (=, *=, , ^=, $=)
104
- */
105
111
  /**
106
112
  * Convert a CSS attribute into a UiSelector method call
107
113
  *
108
- * @param {CssAttr} cssAttr CSS attribute object
114
+ * @param {import('css-selector-parser').AstAttribute} cssAttr CSS attribute object
109
115
  * @returns {string|{index: string|undefined}} CSS attribute parsed as UiSelector
110
116
  */
111
117
  function parseAttr(cssAttr) {
112
- if (cssAttr.valueType && cssAttr.valueType !== 'string') {
113
- throw new TypeError(`'${cssAttr.name}=${cssAttr.value}' is an invalid attribute. ` +
114
- `Only 'string' and empty attribute types are supported. Found '${cssAttr.valueType}'`);
118
+ // @ts-ignore We only care for strings
119
+ const attrValue = cssAttr.value?.value;
120
+ if (!lodash_1.default.isString(attrValue) && !lodash_1.default.isEmpty(attrValue)) {
121
+ throw new TypeError(`'${cssAttr.name}=${attrValue}' is an invalid attribute. ` +
122
+ `Only 'string' and empty attribute types are supported. Found '${attrValue}'`);
115
123
  }
116
- const attrName = toCamelCase(requireAttributeName(cssAttr));
124
+ const attrName = toCamelCase(requireEntityName(cssAttr));
117
125
  // Validate that it's a supported attribute
118
126
  if (!STR_ATTRS.includes(attrName) && !BOOLEAN_ATTRS.includes(attrName)) {
119
127
  throw new Error(`'${attrName}' is not supported. Supported attributes are ` +
@@ -121,12 +129,12 @@ function parseAttr(cssAttr) {
121
129
  }
122
130
  // Parse index if it's an index attribute
123
131
  if (attrName === 'index') {
124
- return { index: cssAttr.value };
132
+ return { index: attrValue };
125
133
  }
126
134
  if (BOOLEAN_ATTRS.includes(attrName)) {
127
135
  return `${attrName} == ${requireBoolean(cssAttr)}`;
128
136
  }
129
- let value = cssAttr.value || '';
137
+ let value = attrValue || '';
130
138
  if (value === '') {
131
139
  return `[${attrName} LIKE ${value}]`;
132
140
  }
@@ -147,49 +155,34 @@ function parseAttr(cssAttr) {
147
155
  ` '=', '*=', '^=', '$=' and '~=' are supported.`);
148
156
  }
149
157
  }
150
- /**
151
- * @typedef {Object} CssPseudo
152
- * @property {string} [valueType] The type of CSS pseudo selector (https://www.npmjs.com/package/css-selector-parser for reference)
153
- * @property {string} [name] The name of the pseudo selector
154
- * @property {string} [value] The value of the pseudo selector
155
- */
156
158
  /**
157
159
  * Convert a CSS pseudo class to a UiSelector
158
160
  *
159
- * @param {CssPseudo} cssPseudo CSS Pseudo class
161
+ * @param {import('css-selector-parser').AstPseudoClass} cssPseudo
160
162
  * @returns {string|{index: string|undefined}|undefined} Pseudo selector parsed as UiSelector
161
163
  */
162
164
  function parsePseudo(cssPseudo) {
163
- if (cssPseudo.valueType && cssPseudo.valueType !== 'string') {
164
- throw new Error(`'${cssPseudo.name}=${cssPseudo.value}'. ` +
165
- `Unsupported css pseudo class value type: '${cssPseudo.valueType}'. Only 'string' type or empty is supported.`);
165
+ // @ts-ignore We only care for strings
166
+ const argValue = cssPseudo.argument?.value;
167
+ if (!lodash_1.default.isString(argValue) && !lodash_1.default.isEmpty(argValue)) {
168
+ throw new TypeError(`'${cssPseudo.name}=${argValue}'. ` +
169
+ `Unsupported css pseudo class value: '${argValue}'. Only 'string' type or empty is supported.`);
166
170
  }
167
- const pseudoName = requireAttributeName(cssPseudo);
171
+ const pseudoName = requireEntityName(cssPseudo);
168
172
  if (BOOLEAN_ATTRS.includes(pseudoName)) {
169
173
  return `${toCamelCase(pseudoName)} == ${requireBoolean(cssPseudo)}`;
170
174
  }
171
175
  if (pseudoName === 'index') {
172
- return { index: cssPseudo.value };
176
+ return { index: argValue };
173
177
  }
174
178
  }
175
- /**
176
- * @typedef {Object} CssRule
177
- * @property {string} [nestingOperator] The nesting operator (aka: combinator https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)
178
- * @property {string} [tagName] The tag name (aka: type selector https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
179
- * @property {string[]} [classNames] An array of CSS class names
180
- * @property {CssAttr[]} [attrs] An array of CSS attributes
181
- * @property {CssPseudo[]} [pseudos] An array of CSS pseudos
182
- * @property {string} [id] CSS identifier
183
- * @property {CssRule} [rule] A descendant of this CSS rule
184
- */
185
179
  /**
186
180
  * Convert a CSS rule to a UiSelector
187
- * @param {CssRule} cssRule CSS rule definition
181
+ * @param {import('css-selector-parser').AstRule} cssRule CSS rule definition
188
182
  */
189
183
  function parseCssRule(cssRule) {
190
- const { nestingOperator } = cssRule;
191
- if (nestingOperator && nestingOperator !== ' ' && nestingOperator !== '>') {
192
- throw new Error(`'${nestingOperator}' is not a supported combinator. ` +
184
+ if (cssRule.combinator && ![' ', '>'].includes(cssRule.combinator)) {
185
+ throw new Error(`'${cssRule.combinator}' is not a supported combinator. ` +
193
186
  `Only child combinator (>) and descendant combinator are supported.`);
194
187
  }
195
188
  let iosClassChainSelector = '';
@@ -198,67 +191,47 @@ function parseCssRule(cssRule) {
198
191
  is not a valid ios class. Must be a single string (e.g.: XCUIElementTypeWindow) without
199
192
  dots separating them`);
200
193
  }
201
- if (cssRule.tagName && cssRule.tagName !== '*' && !cssRule.tagName.toLowerCase().startsWith('xcuielementtype')) {
202
- const capitalizedTagName = cssRule.tagName.charAt(0).toUpperCase() + cssRule.tagName.slice(1);
203
- cssRule.tagName = `XCUIElementType${capitalizedTagName}`;
194
+ // @ts-ignore name presense
195
+ let tagName = cssRule.tag?.name ?? '';
196
+ if (tagName && tagName !== '*' && !lodash_1.default.startsWith(lodash_1.default.toLower(tagName), 'xcuielementtype')) {
197
+ const capitalizedTagName = tagName.charAt(0).toUpperCase() + tagName.slice(1);
198
+ tagName = `XCUIElementType${capitalizedTagName}`;
204
199
  }
205
- iosClassChainSelector += (cssRule.tagName || '*');
206
- let attrs = [];
207
- if (cssRule.id) {
208
- attrs.push(`name == "${cssRule.id}"`);
200
+ iosClassChainSelector += (tagName || '*');
201
+ const attrs = [];
202
+ if (cssRule.ids && !lodash_1.default.isEmpty(cssRule.ids)) {
203
+ attrs.push(`name == "${cssRule.ids[0]}"`);
209
204
  }
210
- if (cssRule.attrs) {
211
- for (const attr of cssRule.attrs) {
212
- attrs.push(parseAttr(attr));
213
- }
205
+ for (const attr of cssRule.attributes ?? []) {
206
+ attrs.push(parseAttr(attr));
214
207
  }
215
- if (cssRule.pseudos) {
216
- for (const pseudo of cssRule.pseudos) {
217
- attrs.push(parsePseudo(pseudo));
218
- }
208
+ for (const pseudo of cssRule.pseudoClasses ?? []) {
209
+ attrs.push(parsePseudo(pseudo));
219
210
  }
220
211
  const nonIndexAttrs = attrs.filter((attr) => lodash_1.default.isString(attr));
221
- if (nonIndexAttrs && nonIndexAttrs.length > 0) {
212
+ if (!lodash_1.default.isEmpty(nonIndexAttrs)) {
222
213
  iosClassChainSelector += `[\`${nonIndexAttrs.join(' AND ')}\`]`;
223
214
  }
224
215
  const indexAttr = attrs.find((attr) => lodash_1.default.isObject(attr) && attr.index);
225
216
  if (indexAttr) {
226
217
  iosClassChainSelector += `[${ /** @type { {index: string} } */(indexAttr).index}]`;
227
218
  }
228
- if (cssRule.rule) {
229
- iosClassChainSelector += `/${parseCssRule(cssRule.rule)}`;
230
- }
231
- if (cssRule.nestingOperator === '>') {
232
- return iosClassChainSelector;
233
- }
234
- else {
235
- return `**/` + iosClassChainSelector;
219
+ if (cssRule.nestedRule) {
220
+ iosClassChainSelector += `/${parseCssRule(cssRule.nestedRule)}`;
236
221
  }
222
+ return cssRule.combinator === '>' ? iosClassChainSelector : `**/${iosClassChainSelector}`;
237
223
  }
238
- /**
239
- * @typedef {Object} CssObject
240
- * @property {string} [type] Type of CSS object. 'rule', 'ruleset' or 'selectors'
241
- */
242
224
  /**
243
225
  * Convert CSS object to iOS Class Chain selector
244
- * @param {CssObject} css CSS object
226
+ *
227
+ * @param {import('css-selector-parser').AstSelector} css CSS object
245
228
  * @returns {string} The CSS object parsed as a UiSelector
246
229
  */
247
230
  function parseCssObject(css) {
248
- switch (css.type) {
249
- case 'rule':
250
- // @ts-expect-error this is extremely broken
251
- return parseCssRule(css);
252
- case 'ruleSet':
253
- // @ts-expect-error this is extremely broken
254
- return parseCssObject(css.rule);
255
- case 'selectors':
256
- // @ts-expect-error this is extremely broken
257
- return css.selectors.map((selector) => parseCssObject(selector)).join('; ');
258
- default:
259
- // This is never reachable, but if it ever is do this.
260
- throw new Error(`iOS Class Chain does not support '${css.type}' css. Only supports 'rule', 'ruleSet', 'selectors'`);
231
+ if (!lodash_1.default.isEmpty(css.rules)) {
232
+ return parseCssRule(css.rules[0]);
261
233
  }
234
+ throw new Error('No rules could be parsed out of the current selector');
262
235
  }
263
236
  /**
264
237
  * Convert a CSS selector to a iOS Class Chain selector
@@ -268,15 +241,17 @@ function parseCssObject(css) {
268
241
  CssConverter.toIosClassChainSelector = function toIosClassChainSelector(cssSelector) {
269
242
  let cssObj;
270
243
  try {
271
- cssObj = parser.parse(cssSelector);
244
+ cssObj = parseCssSelector(cssSelector);
272
245
  }
273
246
  catch (e) {
247
+ logger_js_1.default.debug(e.stack);
274
248
  throw new driver_1.errors.InvalidSelectorError(`Invalid CSS selector '${cssSelector}'. Reason: '${e.message}'`);
275
249
  }
276
250
  try {
277
251
  return parseCssObject(cssObj);
278
252
  }
279
253
  catch (e) {
254
+ logger_js_1.default.debug(e.stack);
280
255
  throw new driver_1.errors.InvalidSelectorError(`Unsupported CSS selector '${cssSelector}'. Reason: '${e.message}'`);
281
256
  }
282
257
  };
@@ -1 +1 @@
1
- {"version":3,"file":"css-converter.js","sourceRoot":"","sources":["../../lib/css-converter.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"css-converter.js","sourceRoot":"","sources":["../../lib/css-converter.js"],"names":[],"mappings":"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"}
@@ -1,14 +1,30 @@
1
- import { CssSelectorParser } from 'css-selector-parser';
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';
4
5
 
5
6
  const CssConverter = {};
6
7
 
7
- const parser = new CssSelectorParser();
8
- parser.registerSelectorPseudos('has');
9
- parser.registerNestingOperators('>', '+', '~');
10
- parser.registerAttrEqualityMods('^', '$', '*', '~');
11
- parser.enableSubstitutes();
8
+ const parseCssSelector = createParser({
9
+ syntax: {
10
+ pseudoClasses: {
11
+ unknown: 'accept',
12
+ definitions: {
13
+ Selector: ['has'],
14
+ }
15
+ },
16
+ combinators: ['>', '+', '~'],
17
+ attributes: {
18
+ operators: ['^=', '$=', '*=', '~=', '=']
19
+ },
20
+ ids: true,
21
+ classNames: true,
22
+ tag: {
23
+ wildcard: true
24
+ },
25
+ },
26
+ substitutes: true
27
+ });
12
28
 
13
29
  const BOOLEAN_ATTRS = [
14
30
  'visible', 'accessible', 'accessibility-container', 'enabled',
@@ -39,7 +55,7 @@ const ATTRIBUTE_ALIASES = [
39
55
  /**
40
56
  * Convert hyphen separated word to camel case
41
57
  *
42
- * @param {string} str
58
+ * @param {string?} str
43
59
  * @returns {string} The hyphen separated word translated to camel case
44
60
  */
45
61
  function toCamelCase (str) {
@@ -51,20 +67,16 @@ function toCamelCase (str) {
51
67
  return out.charAt(0).toLowerCase() + out.slice(1);
52
68
  }
53
69
 
54
- /**
55
- * @typedef {Object} CssNameValueObject
56
- * @property {string} [name] The name of the CSS object
57
- * @property {string} [value] The value of the CSS object
58
- */
59
-
60
70
  /**
61
71
  * Get the boolean from a CSS object. If empty, return true. If not true/false/empty, throw exception
62
72
  *
63
- * @param {CssNameValueObject} css A CSS object that has 'name' and 'value'
73
+ * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssAttr
64
74
  * @returns {string} Either 'true' or 'false'. If value is empty, return 'true'
65
75
  */
66
- function requireBoolean (css) {
67
- const val = css.value?.toLowerCase() || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
76
+ function requireBoolean (cssAttr) {
77
+ // @ts-ignore We only support strings
78
+ const attrValue = cssAttr.value?.value;
79
+ const val = _.toLower(attrValue) || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
68
80
  switch (val) {
69
81
  case '0':
70
82
  case 'false':
@@ -73,7 +85,7 @@ function requireBoolean (css) {
73
85
  case 'true':
74
86
  return '1';
75
87
  default:
76
- throw new TypeError(`'${css.name}' must be true, false or empty. Found '${css.value}'`);
88
+ throw new TypeError(`'${cssAttr.name}' must be true/1 or false/0 or empty. Found '${attrValue}'`);
77
89
  }
78
90
  }
79
91
 
@@ -83,47 +95,41 @@ function requireBoolean (css) {
83
95
  * Converts to lowercase and if an attribute name is an alias for something else, return
84
96
  * what it is an alias for
85
97
  *
86
- * @param {Object} css CSS object
98
+ * @param {import('css-selector-parser').AstAttribute|import('css-selector-parser').AstPseudoClass} cssEntity
87
99
  * @returns {string} The canonical attribute name
88
100
  */
89
- function requireAttributeName (css) {
90
- const attrName = css.name.toLowerCase();
101
+ function requireEntityName (cssEntity) {
102
+ const entityName = cssEntity.name.toLowerCase();
91
103
 
92
104
  // Check if it's supported and if it is, return it
93
- if (ALL_ATTRS.includes(attrName)) {
94
- return attrName.toLowerCase();
105
+ if (ALL_ATTRS.includes(entityName)) {
106
+ return entityName.toLowerCase();
95
107
  }
96
108
 
97
109
  // If attrName is an alias for something else, return that
98
110
  for (const [officialAttr, aliasAttrs] of ATTRIBUTE_ALIASES) {
99
- if (aliasAttrs.includes(attrName)) {
111
+ if (aliasAttrs.includes(entityName)) {
100
112
  return officialAttr;
101
113
  }
102
114
  }
103
- throw new Error(`'${attrName}' is not a valid attribute. ` +
104
- `Supported attributes are '${ALL_ATTRS.join(', ')}'`);
115
+ throw new Error(`'${entityName}' is not a valid attribute. ` +
116
+ `Supported attributes are: '${ALL_ATTRS.join(', ')}'`);
105
117
  }
106
118
 
107
- /**
108
- * @typedef {Object} CssAttr
109
- * @property {string} [name]
110
- * @property {string} [valueType] Type of attribute (must be string or empty)
111
- * @property {string} [value] Value of the attribute
112
- * @property {string} [operator] The operator between value and value type (=, *=, , ^=, $=)
113
- */
114
-
115
119
  /**
116
120
  * Convert a CSS attribute into a UiSelector method call
117
121
  *
118
- * @param {CssAttr} cssAttr CSS attribute object
122
+ * @param {import('css-selector-parser').AstAttribute} cssAttr CSS attribute object
119
123
  * @returns {string|{index: string|undefined}} CSS attribute parsed as UiSelector
120
124
  */
121
125
  function parseAttr (cssAttr) {
122
- if (cssAttr.valueType && cssAttr.valueType !== 'string') {
123
- throw new TypeError(`'${cssAttr.name}=${cssAttr.value}' is an invalid attribute. ` +
124
- `Only 'string' and empty attribute types are supported. Found '${cssAttr.valueType}'`);
126
+ // @ts-ignore We only care for strings
127
+ const attrValue = cssAttr.value?.value;
128
+ if (!_.isString(attrValue) && !_.isEmpty(attrValue)) {
129
+ throw new TypeError(`'${cssAttr.name}=${attrValue}' is an invalid attribute. ` +
130
+ `Only 'string' and empty attribute types are supported. Found '${attrValue}'`);
125
131
  }
126
- const attrName = toCamelCase(requireAttributeName(cssAttr));
132
+ const attrName = toCamelCase(requireEntityName(cssAttr));
127
133
 
128
134
  // Validate that it's a supported attribute
129
135
  if (!STR_ATTRS.includes(attrName) && !BOOLEAN_ATTRS.includes(attrName)) {
@@ -133,13 +139,13 @@ function parseAttr (cssAttr) {
133
139
 
134
140
  // Parse index if it's an index attribute
135
141
  if (attrName === 'index') {
136
- return {index: cssAttr.value};
142
+ return {index: attrValue};
137
143
  }
138
144
  if (BOOLEAN_ATTRS.includes(attrName)) {
139
145
  return `${attrName} == ${requireBoolean(cssAttr)}`;
140
146
  }
141
147
 
142
- let value = cssAttr.value || '';
148
+ let value = attrValue || '';
143
149
  if (value === '') {
144
150
  return `[${attrName} LIKE ${value}]`;
145
151
  }
@@ -162,55 +168,38 @@ function parseAttr (cssAttr) {
162
168
  }
163
169
  }
164
170
 
165
- /**
166
- * @typedef {Object} CssPseudo
167
- * @property {string} [valueType] The type of CSS pseudo selector (https://www.npmjs.com/package/css-selector-parser for reference)
168
- * @property {string} [name] The name of the pseudo selector
169
- * @property {string} [value] The value of the pseudo selector
170
- */
171
-
172
171
  /**
173
172
  * Convert a CSS pseudo class to a UiSelector
174
173
  *
175
- * @param {CssPseudo} cssPseudo CSS Pseudo class
174
+ * @param {import('css-selector-parser').AstPseudoClass} cssPseudo
176
175
  * @returns {string|{index: string|undefined}|undefined} Pseudo selector parsed as UiSelector
177
176
  */
178
177
  function parsePseudo (cssPseudo) {
179
- if (cssPseudo.valueType && cssPseudo.valueType !== 'string') {
180
- throw new Error(`'${cssPseudo.name}=${cssPseudo.value}'. ` +
181
- `Unsupported css pseudo class value type: '${cssPseudo.valueType}'. Only 'string' type or empty is supported.`);
178
+ // @ts-ignore We only care for strings
179
+ const argValue = cssPseudo.argument?.value;
180
+ if (!_.isString(argValue) && !_.isEmpty(argValue)) {
181
+ throw new TypeError(`'${cssPseudo.name}=${argValue}'. ` +
182
+ `Unsupported css pseudo class value: '${argValue}'. Only 'string' type or empty is supported.`);
182
183
  }
183
184
 
184
- const pseudoName = requireAttributeName(cssPseudo);
185
+ const pseudoName = requireEntityName(cssPseudo);
185
186
 
186
187
  if (BOOLEAN_ATTRS.includes(pseudoName)) {
187
188
  return `${toCamelCase(pseudoName)} == ${requireBoolean(cssPseudo)}`;
188
189
  }
189
190
 
190
191
  if (pseudoName === 'index') {
191
- return {index: cssPseudo.value};
192
+ return {index: argValue};
192
193
  }
193
194
  }
194
195
 
195
- /**
196
- * @typedef {Object} CssRule
197
- * @property {string} [nestingOperator] The nesting operator (aka: combinator https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)
198
- * @property {string} [tagName] The tag name (aka: type selector https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
199
- * @property {string[]} [classNames] An array of CSS class names
200
- * @property {CssAttr[]} [attrs] An array of CSS attributes
201
- * @property {CssPseudo[]} [pseudos] An array of CSS pseudos
202
- * @property {string} [id] CSS identifier
203
- * @property {CssRule} [rule] A descendant of this CSS rule
204
- */
205
-
206
196
  /**
207
197
  * Convert a CSS rule to a UiSelector
208
- * @param {CssRule} cssRule CSS rule definition
198
+ * @param {import('css-selector-parser').AstRule} cssRule CSS rule definition
209
199
  */
210
200
  function parseCssRule (cssRule) {
211
- const { nestingOperator } = cssRule;
212
- if (nestingOperator && nestingOperator !== ' ' && nestingOperator !== '>') {
213
- throw new Error(`'${nestingOperator}' is not a supported combinator. ` +
201
+ if (cssRule.combinator && ![' ', '>'].includes(cssRule.combinator)) {
202
+ throw new Error(`'${cssRule.combinator}' is not a supported combinator. ` +
214
203
  `Only child combinator (>) and descendant combinator are supported.`);
215
204
  }
216
205
 
@@ -220,28 +209,26 @@ function parseCssRule (cssRule) {
220
209
  is not a valid ios class. Must be a single string (e.g.: XCUIElementTypeWindow) without
221
210
  dots separating them`);
222
211
  }
223
- if (cssRule.tagName && cssRule.tagName !== '*' && !cssRule.tagName.toLowerCase().startsWith('xcuielementtype')) {
224
- const capitalizedTagName = cssRule.tagName.charAt(0).toUpperCase() + cssRule.tagName.slice(1);
225
- cssRule.tagName = `XCUIElementType${capitalizedTagName}`;
212
+ // @ts-ignore name presense
213
+ let tagName = cssRule.tag?.name ?? '';
214
+ if (tagName && tagName !== '*' && !_.startsWith(_.toLower(tagName), 'xcuielementtype')) {
215
+ const capitalizedTagName = tagName.charAt(0).toUpperCase() + tagName.slice(1);
216
+ tagName = `XCUIElementType${capitalizedTagName}`;
226
217
  }
227
- iosClassChainSelector += (cssRule.tagName || '*');
218
+ iosClassChainSelector += (tagName || '*');
228
219
 
229
- let attrs = [];
230
- if (cssRule.id) {
231
- attrs.push(`name == "${cssRule.id}"`);
220
+ const attrs = [];
221
+ if (cssRule.ids && !_.isEmpty(cssRule.ids)) {
222
+ attrs.push(`name == "${cssRule.ids[0]}"`);
232
223
  }
233
- if (cssRule.attrs) {
234
- for (const attr of cssRule.attrs) {
235
- attrs.push(parseAttr(attr));
236
- }
224
+ for (const attr of cssRule.attributes ?? []) {
225
+ attrs.push(parseAttr(attr));
237
226
  }
238
- if (cssRule.pseudos) {
239
- for (const pseudo of cssRule.pseudos) {
240
- attrs.push(parsePseudo(pseudo));
241
- }
227
+ for (const pseudo of cssRule.pseudoClasses ?? []) {
228
+ attrs.push(parsePseudo(pseudo));
242
229
  }
243
230
  const nonIndexAttrs = attrs.filter((attr) => _.isString(attr));
244
- if (nonIndexAttrs && nonIndexAttrs.length > 0) {
231
+ if (!_.isEmpty(nonIndexAttrs)) {
245
232
  iosClassChainSelector += `[\`${nonIndexAttrs.join(' AND ')}\`]`;
246
233
  }
247
234
 
@@ -250,43 +237,25 @@ function parseCssRule (cssRule) {
250
237
  iosClassChainSelector += `[${/** @type { {index: string} } */(indexAttr).index}]`;
251
238
  }
252
239
 
253
- if (cssRule.rule) {
254
- iosClassChainSelector += `/${parseCssRule(cssRule.rule)}`;
240
+ if (cssRule.nestedRule) {
241
+ iosClassChainSelector += `/${parseCssRule(cssRule.nestedRule)}`;
255
242
  }
256
243
 
257
- if (cssRule.nestingOperator === '>') {
258
- return iosClassChainSelector;
259
- } else {
260
- return `**/` + iosClassChainSelector;
261
- }
244
+ return cssRule.combinator === '>' ? iosClassChainSelector : `**/${iosClassChainSelector}`;
262
245
  }
263
246
 
264
- /**
265
- * @typedef {Object} CssObject
266
- * @property {string} [type] Type of CSS object. 'rule', 'ruleset' or 'selectors'
267
- */
268
-
269
247
  /**
270
248
  * Convert CSS object to iOS Class Chain selector
271
- * @param {CssObject} css CSS object
249
+ *
250
+ * @param {import('css-selector-parser').AstSelector} css CSS object
272
251
  * @returns {string} The CSS object parsed as a UiSelector
273
252
  */
274
253
  function parseCssObject (css) {
275
- switch (css.type) {
276
- case 'rule':
277
- // @ts-expect-error this is extremely broken
278
- return parseCssRule(css);
279
- case 'ruleSet':
280
- // @ts-expect-error this is extremely broken
281
- return parseCssObject(css.rule);
282
- case 'selectors':
283
- // @ts-expect-error this is extremely broken
284
- return css.selectors.map((selector) => parseCssObject(selector)).join('; ');
285
-
286
- default:
287
- // This is never reachable, but if it ever is do this.
288
- throw new Error(`iOS Class Chain does not support '${css.type}' css. Only supports 'rule', 'ruleSet', 'selectors'`);
254
+ if (!_.isEmpty(css.rules)) {
255
+ return parseCssRule(css.rules[0]);
289
256
  }
257
+
258
+ throw new Error('No rules could be parsed out of the current selector');
290
259
  }
291
260
 
292
261
  /**
@@ -297,13 +266,15 @@ function parseCssObject (css) {
297
266
  CssConverter.toIosClassChainSelector = function toIosClassChainSelector (cssSelector) {
298
267
  let cssObj;
299
268
  try {
300
- cssObj = parser.parse(cssSelector);
269
+ cssObj = parseCssSelector(cssSelector);
301
270
  } catch (e) {
271
+ log.debug(e.stack);
302
272
  throw new errors.InvalidSelectorError(`Invalid CSS selector '${cssSelector}'. Reason: '${e.message}'`);
303
273
  }
304
274
  try {
305
275
  return parseCssObject(cssObj);
306
276
  } catch (e) {
277
+ log.debug(e.stack);
307
278
  throw new errors.InvalidSelectorError(`Unsupported CSS selector '${cssSelector}'. Reason: '${e.message}'`);
308
279
  }
309
280
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "appium-xcuitest-driver",
3
- "version": "4.32.3",
3
+ "version": "4.32.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-xcuitest-driver",
9
- "version": "4.32.3",
9
+ "version": "4.32.4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@xmldom/xmldom": "0.8.8",
@@ -19,7 +19,7 @@
19
19
  "async-lock": "1.4.0",
20
20
  "asyncbox": "2.9.4",
21
21
  "bluebird": "3.7.2",
22
- "css-selector-parser": "1.4.1",
22
+ "css-selector-parser": "2.2.3",
23
23
  "fancy-log": "2.0.0",
24
24
  "js2xmlparser2": "0.2.0",
25
25
  "lodash": "4.17.21",
@@ -49,7 +49,7 @@
49
49
  "@types/chai-as-promised": "7.1.5",
50
50
  "@types/lodash": "4.14.195",
51
51
  "@types/mocha": "10.0.1",
52
- "@types/node": "18.16.16",
52
+ "@types/node": "18.16.18",
53
53
  "@types/portscanner": "2.1.1",
54
54
  "@types/sinon": "10.0.15",
55
55
  "@types/sinon-chai": "3.2.9",
@@ -2530,9 +2530,9 @@
2530
2530
  }
2531
2531
  },
2532
2532
  "node_modules/@types/node": {
2533
- "version": "18.16.16",
2534
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz",
2535
- "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g=="
2533
+ "version": "18.16.18",
2534
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.18.tgz",
2535
+ "integrity": "sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw=="
2536
2536
  },
2537
2537
  "node_modules/@types/normalize-package-data": {
2538
2538
  "version": "2.4.1",
@@ -5244,9 +5244,19 @@
5244
5244
  }
5245
5245
  },
5246
5246
  "node_modules/css-selector-parser": {
5247
- "version": "1.4.1",
5248
- "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz",
5249
- "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g=="
5247
+ "version": "2.2.3",
5248
+ "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-2.2.3.tgz",
5249
+ "integrity": "sha512-m5+MAFyt1pdzS754fwxCdya7E+fouV5oXLCG1KkMtR+5JDBEegM7ilSUNtnOTrVA46pVEEgC9+YO/VEOVFRYIw==",
5250
+ "funding": [
5251
+ {
5252
+ "type": "github",
5253
+ "url": "https://github.com/sponsors/mdevils"
5254
+ },
5255
+ {
5256
+ "type": "patreon",
5257
+ "url": "https://patreon.com/mdevils"
5258
+ }
5259
+ ]
5250
5260
  },
5251
5261
  "node_modules/css-shorthand-properties": {
5252
5262
  "version": "1.1.1",
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "xcuitest",
9
9
  "xctest"
10
10
  ],
11
- "version": "4.32.3",
11
+ "version": "4.32.4",
12
12
  "author": "Appium Contributors",
13
13
  "license": "Apache-2.0",
14
14
  "repository": {
@@ -78,7 +78,7 @@
78
78
  "async-lock": "1.4.0",
79
79
  "asyncbox": "2.9.4",
80
80
  "bluebird": "3.7.2",
81
- "css-selector-parser": "1.4.1",
81
+ "css-selector-parser": "2.2.3",
82
82
  "fancy-log": "2.0.0",
83
83
  "js2xmlparser2": "0.2.0",
84
84
  "lodash": "4.17.21",
@@ -146,7 +146,7 @@
146
146
  "@types/chai-as-promised": "7.1.5",
147
147
  "@types/lodash": "4.14.195",
148
148
  "@types/mocha": "10.0.1",
149
- "@types/node": "18.16.16",
149
+ "@types/node": "18.16.18",
150
150
  "@types/portscanner": "2.1.1",
151
151
  "@types/sinon": "10.0.15",
152
152
  "@types/sinon-chai": "3.2.9",