diff --git a/lib/rules/color-contrast-matches.js b/lib/rules/color-contrast-matches.js index 9b3bf4e0b1..0b27f50168 100644 --- a/lib/rules/color-contrast-matches.js +++ b/lib/rules/color-contrast-matches.js @@ -10,6 +10,32 @@ if ( return false; } +// form elements that don't have direct child text nodes need to check that +// the text indent has not been changed and moved the text away from the +// control +const formElements = ['INPUT', 'SELECT', 'TEXTAREA']; +if (formElements.includes(nodeName)) { + const style = window.getComputedStyle(node); + const textIndent = parseInt(style.getPropertyValue('text-indent'), 10); + + if (textIndent) { + // since we can't get the actual bounding rect of the text node, we'll + // use the current nodes bounding rect and adjust by the text-indent to + // see if it still overlaps the node + let rect = node.getBoundingClientRect(); + rect = { + top: rect.top, + bottom: rect.bottom, + left: rect.left + textIndent, + right: rect.right + textIndent + }; + + if (!axe.commons.dom.visuallyOverlaps(rect, node)) { + return false; + } + } +} + if (nodeName === 'INPUT') { return ( ['hidden', 'range', 'color', 'checkbox', 'radio', 'image'].indexOf( diff --git a/test/rule-matches/color-contrast-matches.js b/test/rule-matches/color-contrast-matches.js index b00bb8a361..c6e4ce22ee 100644 --- a/test/rule-matches/color-contrast-matches.js +++ b/test/rule-matches/color-contrast-matches.js @@ -75,6 +75,32 @@ describe('color-contrast-matches', function() { assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(target))); }); + it('should not match input when there is text that is out of the container', function() { + fixture.innerHTML = + ''; + var target = fixture.querySelector('input'); + axe.testUtils.flatTreeSetup(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(target))); + }); + + it('should not match select when there is text that is out of the container', function() { + fixture.innerHTML = + ''; + var target = fixture.querySelector('select'); + axe.testUtils.flatTreeSetup(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(target))); + }); + + it('should not match textarea when there is text that is out of the container', function() { + fixture.innerHTML = + ''; + var target = fixture.querySelector('textarea'); + axe.testUtils.flatTreeSetup(fixture); + assert.isFalse(rule.matches(target, axe.utils.getNodeFromTree(target))); + }); + it('should not match when there is text that is out of the container with overflow hidden', function() { fixture.innerHTML = '
' +