From ed826eb79578b14b4af2c6c99844991e82e7f65e Mon Sep 17 00:00:00 2001 From: fczbkk Date: Tue, 24 Aug 2021 04:25:55 +0200 Subject: [PATCH] feat: simplified attribute selectors refs #77 --- src/selector-attribute.ts | 19 +++++++++++++++--- test/selector-attribute.spec.js | 35 +++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/selector-attribute.ts b/src/selector-attribute.ts index 15aab9c1e..4522415d6 100644 --- a/src/selector-attribute.ts +++ b/src/selector-attribute.ts @@ -11,7 +11,16 @@ export const ATTRIBUTE_BLACKLIST = convertMatchListToRegExp([ ]) /** - * Get attribute selectors for an element. + * Get simplified attribute selector for an element. + */ +export function attributeNodeToSimplifiedSelector ({ + nodeName +}: Node): CssSelector { + return `[${nodeName}]` +} + +/** + * Get attribute selector for an element. */ export function attributeNodeToSelector ({ nodeName, @@ -31,9 +40,13 @@ export function isValidAttributeNode ({nodeName}: Node): boolean { * Get attribute selectors for an element. */ export function getElementAttributeSelectors (element: Element): CssSelector[] { - return Array.from(element.attributes) + const validAttributes = Array.from(element.attributes) .filter(isValidAttributeNode) - .map(attributeNodeToSelector) + return [ + ...validAttributes.map(attributeNodeToSimplifiedSelector), + ...validAttributes.map(attributeNodeToSelector) + ] + } /** diff --git a/test/selector-attribute.spec.js b/test/selector-attribute.spec.js index bad213829..7408b19bf 100644 --- a/test/selector-attribute.spec.js +++ b/test/selector-attribute.spec.js @@ -1,4 +1,5 @@ import {assert} from 'chai' +import getCssSelector from '../src' import {getAttributeSelectors} from '../src/selector-attribute.ts' describe('selector - attribute', function () { @@ -16,9 +17,18 @@ describe('selector - attribute', function () { it('should generate attribute selectors', function () { root.innerHTML = '
' const result = getAttributeSelectors([root.firstElementChild]) - assert.lengthOf(result, 2) - assert.include(result, "[aaa='bbb']") - assert.include(result, '[ccc=\'ddd\']') + assert.sameMembers(result, [ + '[aaa]', + "[aaa='bbb']", + '[ccc]', + "[ccc='ddd']" + ]) + }) + + it('should put simplified selector before full selector', () => { + root.innerHTML = '
' + const result = getAttributeSelectors([root.firstElementChild]) + assert.sameOrderedMembers(result, ['[aaa]', "[aaa='bbb']"]) }) it('should ignore ID attribute', function () { @@ -60,9 +70,26 @@ describe('selector - attribute', function () { const elements = root.querySelectorAll('div') const withIntersection = getAttributeSelectors([elements[0], elements[1]]) const noIntersection = getAttributeSelectors([elements[0], elements[2]]) - assert.sameMembers(withIntersection, ["[aaa='bbb']"]) + assert.sameMembers(withIntersection, ['[aaa]', "[aaa='bbb']"]) assert.sameMembers(noIntersection, []) }) + it('should prefer simplified selector if possible', () => { + root.innerHTML = ` +
+
+ ` + const result = getCssSelector(root.firstElementChild) + assert.equal(result, '[aaa]') + }) + + it('should use full selector', () => { + root.innerHTML = ` +
+
+ ` + const result = getCssSelector(root.firstElementChild) + assert.equal(result, "[aaa='bbb']") + }) })