diff --git a/lib/core/utils/matches.js b/lib/core/utils/matches.js
index 412dfcf837..5a20573edf 100644
--- a/lib/core/utils/matches.js
+++ b/lib/core/utils/matches.js
@@ -16,7 +16,7 @@ function matchesAttributes(vNode, exp) {
!exp.attributes ||
exp.attributes.every(att => {
var nodeAtt = vNode.attr(att.key);
- return nodeAtt !== null && (!att.value || att.test(nodeAtt));
+ return nodeAtt !== null && att.test(nodeAtt);
})
);
}
@@ -108,9 +108,10 @@ function convertAttributes(atts) {
return attributeValue !== value;
};
break;
+ // attribute existence
default:
test = value => {
- return !!value;
+ return value !== null;
};
}
diff --git a/test/core/utils/matches.js b/test/core/utils/matches.js
index ad5aac90dc..6951243588 100644
--- a/test/core/utils/matches.js
+++ b/test/core/utils/matches.js
@@ -1,32 +1,32 @@
-describe('utils.matches', function() {
+describe('utils.matches', function () {
var matches = axe.utils.matches;
var fixture = document.querySelector('#fixture');
var queryFixture = axe.testUtils.queryFixture;
var convertSelector = axe._thisWillBeDeletedDoNotUse.utils.convertSelector;
- afterEach(function() {
+ afterEach(function () {
fixture.innerHTML = '';
});
- describe('tag', function() {
- it('returns true if tag matches', function() {
+ describe('tag', function () {
+ it('returns true if tag matches', function () {
var virtualNode = queryFixture('
foo
');
assert.isTrue(matches(virtualNode, 'h1'));
});
- it('returns false if the tag does not match', function() {
+ it('returns false if the tag does not match', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'div'));
});
- it('is case sensitive for XHTML', function() {
+ it('is case sensitive for XHTML', function () {
var virtualNode = queryFixture('foo
');
delete virtualNode._cache.props;
virtualNode._isXHTML = true;
assert.isFalse(matches(virtualNode, 'h1'));
});
- it('is case insensitive for HTML, but not for XHTML', function() {
+ it('is case insensitive for HTML, but not for XHTML', function () {
var virtualNode = queryFixture('foo
');
delete virtualNode._cache.props;
virtualNode._isXHTML = true;
@@ -34,22 +34,22 @@ describe('utils.matches', function() {
});
});
- describe('classes', function() {
- it('returns true if all classes match', function() {
+ describe('classes', function () {
+ it('returns true if all classes match', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '.foo.bar.baz'));
});
- it('returns false if some classes do not match', function() {
+ it('returns false if some classes do not match', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, '.foo.bar.bazz'));
});
- it('returns false if any classes are missing', function() {
+ it('returns false if any classes are missing', function () {
var virtualNode = queryFixture(
''
);
@@ -57,168 +57,196 @@ describe('utils.matches', function() {
});
});
- describe('attributes', function() {
- it('returns true if attribute exists', function() {
+ describe('attributes', function () {
+ it('returns true if attribute exists', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo]'));
});
- it('returns true if attribute matches', function() {
+ it('returns true if attribute matches', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo=baz]'));
});
- it('returns true if all attributes match', function() {
+ it('returns true if all attributes match', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo="baz"][bar="foo"][baz="bar"]'));
});
- it('returns false if some attributes do not match', function() {
+ it('returns false if some attributes do not match', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, '[foo="baz"][bar="foo"][baz="baz"]'));
});
- it('returns false if any attributes are missing', function() {
+ it('returns false if any attributes are missing', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, '[foo="baz"][bar="foo"][baz="bar"]'));
});
- it('returns true if attribute starts with value', function() {
+ it('returns true if attribute starts with value', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo^="baz"]'));
});
- it('returns true if attribute ends with value', function() {
+ it('returns true if attribute ends with value', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo$="hone"]'));
});
- it('returns true if attribute contains value', function() {
+ it('returns true if attribute contains value', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo*="baz"]'));
});
- it('returns true if attribute has value', function() {
+ it('returns true if attribute has value', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, '[foo~="baz"]'));
});
+
+ it('returns true if attribute matches having an empty value', function () {
+ var virtualNode = queryFixture(
+ ''
+ );
+ assert.isTrue(matches(virtualNode, '[foo=""]'));
+ });
+
+ it('returns true if attribute matches not having value', function () {
+ var virtualNode = queryFixture(
+ ''
+ );
+ assert.isTrue(matches(virtualNode, '[foo=""]'));
+ });
+
+ it('returns false if attribute should not have value', function () {
+ var virtualNode = queryFixture(
+ ''
+ );
+ assert.isFalse(matches(virtualNode, '[foo=""]'));
+ });
+
+ it('should return true if attribute exists without value', function () {
+ var virtualNode = queryFixture(
+ ''
+ );
+ assert.isTrue(matches(virtualNode, '[foo]'));
+ });
});
- describe('id', function() {
- it('returns true if id matches', function() {
+ describe('id', function () {
+ it('returns true if id matches', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, '#target'));
});
- it('returns false if the id does not match', function() {
+ it('returns false if the id does not match', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, '#notTarget'));
});
});
- describe('pseudos', function() {
- it('throws error if pseudo is not implemented', function() {
+ describe('pseudos', function () {
+ it('throws error if pseudo is not implemented', function () {
var virtualNode = queryFixture('foo
');
- assert.throws(function() {
+ assert.throws(function () {
matches(virtualNode, 'h1:empty');
});
- assert.throws(function() {
+ assert.throws(function () {
matches(virtualNode, 'h1::before');
});
});
- describe(':not', function() {
- it('returns true if :not matches using tag', function() {
+ describe(':not', function () {
+ it('returns true if :not matches using tag', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:not(span)'));
});
- it('returns true if :not matches using class', function() {
+ it('returns true if :not matches using class', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:not(.foo)'));
});
- it('returns true if :not matches using attribute', function() {
+ it('returns true if :not matches using attribute', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:not([class])'));
});
- it('returns true if :not matches using id', function() {
+ it('returns true if :not matches using id', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:not(#foo)'));
});
- it('returns true if :not matches none of the selectors', function() {
+ it('returns true if :not matches none of the selectors', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:not([role=heading], span)'));
});
- it('returns false if :not matches element', function() {
+ it('returns false if :not matches element', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'h1:not([id])'));
});
- it('returns false if :not matches one of the selectors', function() {
+ it('returns false if :not matches one of the selectors', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'h1:not([role=heading], [id])'));
});
});
- describe(':is', function() {
- it('returns true if :is matches using tag', function() {
+ describe(':is', function () {
+ it('returns true if :is matches using tag', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, ':is(h1)'));
});
- it('returns true if :is matches using class', function() {
+ it('returns true if :is matches using class', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:is(.foo)'));
});
- it('returns true if :is matches using attribute', function() {
+ it('returns true if :is matches using attribute', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:is([class])'));
});
- it('returns true if :is matches using id', function() {
+ it('returns true if :is matches using id', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:is(#target)'));
});
- it('returns true if :is matches one of the selectors', function() {
+ it('returns true if :is matches one of the selectors', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, ':is([role=heading], h1)'));
});
- it('returns true if :is matches complex selector', function() {
+ it('returns true if :is matches complex selector', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'h1:is(div > #target)'));
});
- it('returns false if :is does not match element', function() {
+ it('returns false if :is does not match element', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'h1:is([class])'));
});
- it('returns false if :is matches none of the selectors', function() {
+ it('returns false if :is matches none of the selectors', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(
matches(virtualNode, 'h1:is([class], span, #foo, .bar)')
@@ -227,22 +255,22 @@ describe('utils.matches', function() {
});
});
- describe('complex', function() {
- it('returns true for complex selector', function() {
+ describe('complex', function () {
+ it('returns true for complex selector', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, 'span.foo[id="target"]:not(div)'));
});
- it('returns false if any part of the selector does not match', function() {
+ it('returns false if any part of the selector does not match', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, 'span.foo[id="target"]:not(span)'));
});
- it('returns true if a comma-separated list of selectors match', function() {
+ it('returns true if a comma-separated list of selectors match', function () {
var virtualNode = queryFixture(
''
);
@@ -250,92 +278,92 @@ describe('utils.matches', function() {
});
});
- describe('combinator', function() {
- it('returns true if parent selector matches', function() {
+ describe('combinator', function () {
+ it('returns true if parent selector matches', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'div > h1'));
});
- it('returns true if nested parent selector matches', function() {
+ it('returns true if nested parent selector matches', function () {
var virtualNode = queryFixture(
'foo
'
);
assert.isTrue(matches(virtualNode, 'main > div > h1'));
});
- it('returns true if hierarchical selector matches', function() {
+ it('returns true if hierarchical selector matches', function () {
var virtualNode = queryFixture('foo
');
assert.isTrue(matches(virtualNode, 'div h1'));
});
- it('returns true if nested hierarchical selector matches', function() {
+ it('returns true if nested hierarchical selector matches', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, 'div tr h1'));
});
- it('returns true if mixed parent and hierarchical selector matches', function() {
+ it('returns true if mixed parent and hierarchical selector matches', function () {
var virtualNode = queryFixture(
''
);
assert.isTrue(matches(virtualNode, 'div tr > td h1'));
});
- it('returns false if parent selector does not match', function() {
+ it('returns false if parent selector does not match', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'span > h1'));
});
- it('returns false if nested parent selector does not match', function() {
+ it('returns false if nested parent selector does not match', function () {
var virtualNode = queryFixture(
'foo
'
);
assert.isFalse(matches(virtualNode, 'span > div > h1'));
});
- it('returns false if hierarchical selector does not match', function() {
+ it('returns false if hierarchical selector does not match', function () {
var virtualNode = queryFixture('foo
');
assert.isFalse(matches(virtualNode, 'span h1'));
});
- it('returns false if nested hierarchical selector does not match', function() {
+ it('returns false if nested hierarchical selector does not match', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, 'div span h1'));
});
- it('returns false if mixed parent and hierarchical selector does not match', function() {
+ it('returns false if mixed parent and hierarchical selector does not match', function () {
var virtualNode = queryFixture(
''
);
assert.isFalse(matches(virtualNode, 'div span > td h1'));
});
- it('throws error if combinator is not implemented', function() {
+ it('throws error if combinator is not implemented', function () {
var virtualNode = queryFixture('foo
');
- assert.throws(function() {
+ assert.throws(function () {
matches(virtualNode, 'div + h1');
});
- assert.throws(function() {
+ assert.throws(function () {
matches(virtualNode, 'div ~ h1');
});
});
});
- describe('convertSelector', function() {
- it('should set type to attrExist for attribute selector', function() {
+ describe('convertSelector', function () {
+ it('should set type to attrExist for attribute selector', function () {
var expression = convertSelector('[disabled]');
assert.equal(expression[0][0].attributes[0].type, 'attrExist');
});
- it('should set type to attrValue for attribute value selector', function() {
+ it('should set type to attrValue for attribute value selector', function () {
var expression = convertSelector('[aria-pressed="true"]');
assert.equal(expression[0][0].attributes[0].type, 'attrValue');
});
- it('should set type to attrValue for empty attribute value selector', function() {
+ it('should set type to attrValue for empty attribute value selector', function () {
var expression = convertSelector('[aria-pressed=""]');
assert.equal(expression[0][0].attributes[0].type, 'attrValue');
});