diff --git a/lib/rules/color-contrast-matches.js b/lib/rules/color-contrast-matches.js index 053b78fc14..04ee5fdebf 100644 --- a/lib/rules/color-contrast-matches.js +++ b/lib/rules/color-contrast-matches.js @@ -2,7 +2,7 @@ var nodeName = node.nodeName.toUpperCase(), nodeType = node.type, - doc = document; + doc = axe.commons.dom.getRootNode(node); if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.findUp(node, '[aria-disabled="true"]')) { return false; @@ -45,9 +45,9 @@ if (nodeName === 'LABEL' || nodeParentLabel) { return false; } - var candidate = node.querySelector('input:not([type="hidden"]):not([type="image"])' + + var candidate = axe.utils.querySelectorAll(virtualNode, 'input:not([type="hidden"]):not([type="image"])' + ':not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea'); - if (candidate && candidate.disabled) { + if (candidate.length && candidate[0].actualNode.disabled) { return false; } @@ -66,15 +66,15 @@ if (axe.commons.text.visible(virtualNode, false, true) === '') { } var range = document.createRange(), - childNodes = node.childNodes, + childNodes = virtualNode.children, length = childNodes.length, child, index; for (index = 0; index < length; index++) { child = childNodes[index]; - if (child.nodeType === 3 && axe.commons.text.sanitize(child.nodeValue) !== '') { - range.selectNodeContents(child); + if (child.actualNode.nodeType === 3 && axe.commons.text.sanitize(child.actualNode.nodeValue) !== '') { + range.selectNodeContents(child.actualNode); } } diff --git a/test/rule-matches/color-contrast-matches.js b/test/rule-matches/color-contrast-matches.js index c13d485f04..c3f0e4a10e 100644 --- a/test/rule-matches/color-contrast-matches.js +++ b/test/rule-matches/color-contrast-matches.js @@ -1,4 +1,3 @@ -/* global xit */ describe('color-contrast-matches', function () { 'use strict'; @@ -72,86 +71,99 @@ describe('color-contrast-matches', function () { it('should match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); - assert.isTrue(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); // Some browsers will fallback to type=text for unknown input types (looking at you IE) if (target.type === 'color') { - assert.isFalse(rule.matches(target)); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); } }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); // Some browsers will fallback to type=text for unknown input types (looking at you IE) if (target.type === 'range') { - assert.isFalse(rule.matches(target)); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); } }); it('should match '; var target = fixture.querySelector('select'); - assert.isTrue(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match '; var target = fixture.querySelector('select'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should match '; var target = fixture.querySelector('textarea'); - assert.isTrue(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match '; var target = fixture.querySelector('select'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should match '; var target = fixture.querySelector('button'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('button'); - assert.isFalse(rule.matches(target.querySelector('span'))); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target.querySelector('span'), axe.utils.getNodeFromTree(tree[0], target.querySelector('span')))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('button'); - assert.isFalse(rule.matches(target.querySelector('i'))); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target.querySelector('i'), axe.utils.getNodeFromTree(tree[0], target.querySelector('i')))); }); it('should not match ', function () { fixture.innerHTML = ''; var target = fixture.querySelector('input'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a disabled input\'s label - explicit label', function () { fixture.innerHTML = ''; var target = fixture.querySelector('label'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a disabled input\'s label - implicit label (input)', function () { fixture.innerHTML = ''; var target = fixture.querySelector('label'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a disabled input\'s label - implicit label (textarea)', function () { fixture.innerHTML = ''; var target = fixture.querySelector('label'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a disabled input\'s label - implicit label (select)', function () { fixture.innerHTML = ''; var target = fixture.querySelector('label'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a disabled input\'s label - aria-labelledby', function () { fixture.innerHTML = '
Test
'; var target = fixture.querySelector('div'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match aria-disabled=true', function () { fixture.innerHTML = '
hi
'; var target = fixture.querySelector('div'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a descendant of aria-disabled=true', function () { fixture.innerHTML = '
hi
'; var target = fixture.querySelector('span'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a descendant of a disabled fieldset', function () { fixture.innerHTML = '
'; var target = fixture.querySelector('label'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a descendant of an explicit label for a disabled input', function () { fixture.innerHTML = ''; var target = fixture.querySelector('span'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); it('should not match a descendant of an implicit label for a disabled input', function () { fixture.innerHTML = ''; var target = fixture.querySelector('span'); - assert.isFalse(rule.matches(target)); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(tree[0], target))); }); - (shadowSupport ? it : xit) - ('should match a descendant of an element across a shadow boundary', function () { - fixture.innerHTML = '
' + + if (shadowSupport) { + it('should match a descendant of an element across a shadow boundary', function () { + fixture.innerHTML = '
' + + '
'; + + var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
Text
'; + + var shadowTarget = fixture.firstChild.shadowRoot.querySelector('#shadowTarget'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(rule.matches(shadowTarget, axe.utils.getNodeFromTree(tree[0], shadowTarget))); + }); + + it('should look at the correct root node when looking up an explicit label and disabled input', function () { + fixture.innerHTML = '
'+ + '' + '
'; - var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); - shadowRoot.innerHTML = '
Text
'; + var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '' + + '
'; - var shadowTarget = fixture.firstChild.shadowRoot.querySelector('#shadowTarget'); - var tree = axe._tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue(rule.matches(shadowTarget, axe.utils.getNodeFromTree(tree[0], shadowTarget))); - }); + var shadowLabel = fixture.firstChild.shadowRoot.querySelector('#shadowLabel'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(shadowLabel, axe.utils.getNodeFromTree(tree[0], shadowLabel))); + }); + + it('should look at the correct root node when looking up implicit label and disabled input', function () { + fixture.innerHTML = '
'+ + '' + + '
'; + + var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '
'; + + var shadowLabel = fixture.firstChild.shadowRoot.querySelector('#shadowLabel'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(shadowLabel, axe.utils.getNodeFromTree(tree[0], shadowLabel))); + }); + + it('should look at the correct root node for a disabled control\'s label associated w/ aria-labelledby', function () { + fixture.innerHTML = '
'+ + '' + + '
'; + + var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '' + + '
'; + + var shadowLabel = fixture.firstChild.shadowRoot.querySelector('#shadowLabel'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(rule.matches(shadowLabel, axe.utils.getNodeFromTree(tree[0], shadowLabel))); + }); + + it('should look at the children of a virtual node for overlap', function () { + fixture.innerHTML = '
'+ + '
' + + '
'; + + var shadowRoot = document.getElementById('firstChild').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = 'Some text' + + '

Other text

'; + + var firstChild = fixture.querySelector('#firstChild'); + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(rule.matches(firstChild, axe.utils.getNodeFromTree(tree[0], firstChild))); + }); + } });