@cypress/unique-selector 1.2.0 → 2.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.
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
@@ -7,19 +7,20 @@ Object.defineProperty(exports, "__esModule", {
7
7
  * Returns the {attr} selector of the element
8
8
  * @param { Element } el - The element.
9
9
  * @param { String } attribute - The attribute name.
10
+ * @param { Function } filter
10
11
  * @return { String | null } - The {attr} selector of the element.
11
12
  */
12
- var getAttributeSelector = exports.getAttributeSelector = function getAttributeSelector(el, attribute) {
13
+ var getAttributeSelector = exports.getAttributeSelector = function getAttributeSelector(el, attribute, filter) {
13
14
  var attributeValue = el.getAttribute(attribute);
14
15
 
15
- if (attributeValue === null) {
16
+ if (attributeValue === null || filter && !filter('attribute', attribute, attributeValue)) {
16
17
  return null;
17
18
  }
18
19
 
19
20
  if (attributeValue) {
20
21
  // if we have value that needs quotes
21
- return "[" + attribute + "=\"" + attributeValue + "\"]";
22
+ return '[' + attribute + '="' + attributeValue + '"]';
22
23
  }
23
24
 
24
- return "[" + attribute + "]";
25
+ return '[' + attribute + ']';
25
26
  };
@@ -22,7 +22,7 @@ function getAttributes(el) {
22
22
  var attrs = [].concat(_toConsumableArray(attributes));
23
23
 
24
24
  return attrs.reduce(function (sum, next) {
25
- if (!(attributesToIgnore.indexOf(next.nodeName) > -1) && (!filter || filter('attributes', next.nodeName, next.value))) {
25
+ if (!(attributesToIgnore.indexOf(next.nodeName) > -1) && (!filter || filter('attribute', next.nodeName, next.value))) {
26
26
  sum.push('[' + next.nodeName + '="' + next.value + '"]');
27
27
  }
28
28
  return sum;
package/lib/getClasses.js CHANGED
@@ -22,7 +22,7 @@ function getClasses(el, filter) {
22
22
 
23
23
  try {
24
24
  return Array.prototype.slice.call(el.classList).filter(function (cls) {
25
- return !filter || filter('class', 'class', cls);
25
+ return !filter || filter('attribute', 'class', cls);
26
26
  });
27
27
  } catch (e) {
28
28
  var className = el.getAttribute('class');
package/lib/getID.js CHANGED
@@ -16,7 +16,7 @@ require('css.escape');
16
16
  function getID(el, filter) {
17
17
  var id = el.getAttribute('id');
18
18
 
19
- if (id !== null && id !== '' && (!filter || filter('id', 'id', id))) {
19
+ if (id !== null && id !== '' && (!filter || filter('attribute', 'id', id))) {
20
20
  return '#' + CSS.escape(id);
21
21
  }
22
22
  return null;
package/lib/getName.js CHANGED
@@ -13,7 +13,7 @@ exports.getName = getName;
13
13
  function getName(el, filter) {
14
14
  var name = el.getAttribute('name');
15
15
 
16
- if (name !== null && name !== '' && (!filter || filter('name', 'name', name))) {
16
+ if (name !== null && name !== '' && (!filter || filter('attribute', 'name', name))) {
17
17
  return '[name="' + name + '"]';
18
18
  }
19
19
  return null;
package/lib/index.js CHANGED
@@ -32,12 +32,21 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr
32
32
  var dataRegex = /^data-.+/;
33
33
  var attrRegex = /^attribute:(.+)/m;
34
34
 
35
+ /**
36
+ * @typedef Filter
37
+ * @type {Function}
38
+ * @param {string} type - the trait being considered ('attribute', 'tag', 'nth-child').
39
+ * @param {string} key - your trait key (for 'attribute' will be the attribute name, for others will typically be the same as 'type').
40
+ * @param {string} value - the trait value.
41
+ * @returns {boolean} whether this trait can be used when building the selector (true = allow). Defaults to 'true' if no value returned.
42
+ */
43
+
35
44
  /**
36
45
  * Returns all the selectors of the element
37
46
  * @param { Object } element
38
47
  * @return { Object }
39
48
  */
40
- function getAllSelectors(el, selectors, attributesToIgnore, filters) {
49
+ function getAllSelectors(el, selectors, attributesToIgnore, filter) {
41
50
  var consolidatedAttributesToIgnore = [].concat(_toConsumableArray(attributesToIgnore));
42
51
  var nonAttributeSelectors = [];
43
52
  var _iteratorNormalCompletion = true;
@@ -73,22 +82,22 @@ function getAllSelectors(el, selectors, attributesToIgnore, filters) {
73
82
 
74
83
  var funcs = {
75
84
  'tag': function tag(elem) {
76
- return (0, _getTag.getTag)(elem, filters.tag);
85
+ return (0, _getTag.getTag)(elem, filter);
77
86
  },
78
87
  'nth-child': function nthChild(elem) {
79
- return (0, _getNthChild.getNthChild)(elem, filters.nthChild);
88
+ return (0, _getNthChild.getNthChild)(elem, filter);
80
89
  },
81
90
  'attributes': function attributes(elem) {
82
- return (0, _getAttributes.getAttributes)(elem, consolidatedAttributesToIgnore, filters.attributes);
91
+ return (0, _getAttributes.getAttributes)(elem, consolidatedAttributesToIgnore, filter);
83
92
  },
84
93
  'class': function _class(elem) {
85
- return (0, _getClasses.getClassSelectors)(elem, filters.class);
94
+ return (0, _getClasses.getClassSelectors)(elem, filter);
86
95
  },
87
96
  'id': function id(elem) {
88
- return (0, _getID.getID)(elem, filters.id);
97
+ return (0, _getID.getID)(elem, filter);
89
98
  },
90
99
  'name': function name(elem) {
91
- return (0, _getName.getName)(elem, filters.name);
100
+ return (0, _getName.getName)(elem, filter);
92
101
  }
93
102
  };
94
103
 
@@ -160,10 +169,10 @@ function getUniqueCombination(element, items, tag) {
160
169
  * @param { Array } options
161
170
  * @return { String }
162
171
  */
163
- function getUniqueSelector(element, selectorTypes, attributesToIgnore, filters) {
172
+ function getUniqueSelector(element, selectorTypes, attributesToIgnore, filter) {
164
173
  var foundSelector = void 0;
165
174
 
166
- var elementSelectors = getAllSelectors(element, selectorTypes, attributesToIgnore, filters);
175
+ var elementSelectors = getAllSelectors(element, selectorTypes, attributesToIgnore, filter);
167
176
 
168
177
  var _iteratorNormalCompletion2 = true;
169
178
  var _didIteratorError2 = false;
@@ -180,12 +189,10 @@ function getUniqueSelector(element, selectorTypes, attributesToIgnore, filters)
180
189
  var isAttributeSelectorType = !isDataAttributeSelectorType && attrRegex.test(selectorType);
181
190
  if (isDataAttributeSelectorType || isAttributeSelectorType) {
182
191
  var attributeToQuery = isDataAttributeSelectorType ? selectorType : selectorType.replace(attrRegex, '$1');
183
- var attributeValue = element.getAttribute(attributeToQuery);
184
- var attributeFilter = filters[selectorType];
185
-
192
+ var attributeSelector = (0, _getAttribute.getAttributeSelector)(element, attributeToQuery, filter);
186
193
  // if we found a selector via attribute
187
- if (attributeValue !== null && (!attributeFilter || attributeFilter(selectorType, attributeToQuery, attributeValue))) {
188
- selector = (0, _getAttribute.getAttributeSelector)(element, attributeToQuery);
194
+ if (attributeSelector) {
195
+ selector = attributeSelector;
189
196
  selectorType = 'attribute';
190
197
  }
191
198
  }
@@ -243,10 +250,7 @@ function getUniqueSelector(element, selectorTypes, attributesToIgnore, filters)
243
250
  * @param {Object} options (optional) Customize various behaviors of selector generation
244
251
  * @param {String[]} options.selectorTypes Specify the set of traits to leverage when building selectors in precedence order
245
252
  * @param {String[]} options.attributesToIgnore Specify a set of attributes to *not* leverage when building selectors
246
- * @param {Object} options.filters Specify a set of filter functions to conditionally reject various traits when building selectors. Keys correspond to a `selectorTypes` entry, values should be a function accepting three parameters:
247
- * * selectorType: The selector type/category being generated
248
- * * key: The key being evaluated - this will typically match the `selectorType` except in aggregate types like `attributes`
249
- * * value: The value to consider. Returning `true` will allow its use in selector generation, `false` will prevent.
253
+ * @param {Filter} options.filter Provide a filter function to conditionally reject various traits when building selectors.
250
254
  * @param {Map<Element, String>} options.selectorCache Provide a cache to improve performance of repeated selector generation - it is the responsibility of the caller to handle cache invalidation. Caching is performed using the input Element as key. This cache handles Element -> Selector caching.
251
255
  * @param {Map<String, Boolean>} options.isUniqueCache Provide a cache to improve performance of repeated selector generation - it is the responsibility of the caller to handle cache invalidation. Caching is performed using the input Element as key. This cache handles Selector -> isUnique caching.
252
256
  * @return {String}
@@ -259,11 +263,18 @@ function unique(el) {
259
263
  selectorTypes = _options$selectorType === undefined ? ['id', 'name', 'class', 'tag', 'nth-child'] : _options$selectorType,
260
264
  _options$attributesTo = options.attributesToIgnore,
261
265
  attributesToIgnore = _options$attributesTo === undefined ? ['id', 'class', 'length'] : _options$attributesTo,
262
- _options$filters = options.filters,
263
- filters = _options$filters === undefined ? {} : _options$filters,
266
+ filter = options.filter,
264
267
  selectorCache = options.selectorCache,
265
268
  isUniqueCache = options.isUniqueCache;
269
+ // If filter was provided wrap it to ensure a default value of `true` is returned if the provided function fails to return a value
266
270
 
271
+ var normalizedFilter = filter && function (type, key, value) {
272
+ var result = filter(type, key, value);
273
+ if (result === null || result === undefined) {
274
+ return true;
275
+ }
276
+ return result;
277
+ };
267
278
  var allSelectors = [];
268
279
 
269
280
  var currentElement = el;
@@ -271,7 +282,7 @@ function unique(el) {
271
282
  var selector = selectorCache ? selectorCache.get(currentElement) : undefined;
272
283
 
273
284
  if (!selector) {
274
- selector = getUniqueSelector(currentElement, selectorTypes, attributesToIgnore, filters);
285
+ selector = getUniqueSelector(currentElement, selectorTypes, attributesToIgnore, normalizedFilter);
275
286
  if (selectorCache) {
276
287
  selectorCache.set(currentElement, selector);
277
288
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cypress/unique-selector",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "Given a DOM node, return a unique CSS selector matching only that element",
5
5
  "main": "./lib/index.js",
6
6
  "jsnext:main": "./src/index.js",