From f98f8bdacc551579c259aefd88bef41ed8157b68 Mon Sep 17 00:00:00 2001 From: Michael Fairchild Date: Thu, 7 Sep 2017 17:12:21 -0500 Subject: [PATCH] fix(color-contrast): Include `THEAD` and `TBODY` in contrast checks (#514) --- lib/commons/color/get-background-color.js | 35 +++++++++++++---------- test/checks/color/color-contrast.js | 14 +++++++++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/commons/color/get-background-color.js b/lib/commons/color/get-background-color.js index 47e19e2a93..a64a95a0fc 100644 --- a/lib/commons/color/get-background-color.js +++ b/lib/commons/color/get-background-color.js @@ -121,29 +121,34 @@ function elmPartiallyObscured(elm, bgElm, bgColor) { * @param {Element} elm */ function includeMissingElements(elmStack, elm) { - const elementMap = {'TD': 'TR', 'TH': 'TR', 'INPUT': 'LABEL'}; + const elementMap = {'TD': ['TR', 'TBODY'], 'TH': ['TR', 'THEAD'], 'INPUT': ['LABEL']}; const tagArray = elmStack.map((elm) => { return elm.tagName; }); let bgNodes = elmStack; + //jshint maxdepth:7 for (let candidate in elementMap) { - // check that TR or LABEL has paired nodeName from elementMap, but don't expect elm to be that candidate + // check that TR or LABEL has paired nodeName from elementMap, but don't expect elm to be that candidate if (tagArray.includes(candidate)) { - // look up the tree for a matching candidate - let ancestorMatch = axe.commons.dom.findUp(elm, elementMap[candidate]); - if (ancestorMatch && elmStack.indexOf(ancestorMatch) === -1) { - // found an ancestor not in elmStack, and it overlaps - let overlaps = axe.commons.dom.visuallyOverlaps(elm.getBoundingClientRect(), ancestorMatch); - if (overlaps) { - // if target is in the elementMap, use its position. - bgNodes.splice(tagArray.indexOf(candidate) + 1, 0, ancestorMatch); + for (let candidateIndex in elementMap[candidate]) { + if (candidate.hasOwnProperty(candidateIndex)) { + // look up the tree for a matching candidate + let ancestorMatch = axe.commons.dom.findUp(elm, elementMap[candidate][candidateIndex]); + if (ancestorMatch && elmStack.indexOf(ancestorMatch) === -1) { + // found an ancestor not in elmStack, and it overlaps + let overlaps = axe.commons.dom.visuallyOverlaps(elm.getBoundingClientRect(), ancestorMatch); + if (overlaps) { + // if target is in the elementMap, use its position. + bgNodes.splice(tagArray.indexOf(candidate) + 1, 0, ancestorMatch); + } + } + // tagName matches value + // (such as LABEL, when matching itself. It should be in the list, but Phantom skips it) + if (elm.tagName === elementMap[candidate][candidateIndex] && tagArray.indexOf(elm.tagName) === -1) { + bgNodes.splice(tagArray.indexOf(candidate) + 1, 0, elm); + } } } - // tagName matches value - // (such as LABEL, when matching itself. It should be in the list, but Phantom skips it) - if (elm.tagName === elementMap[candidate] && tagArray.indexOf(elm.tagName) === -1) { - bgNodes.splice(tagArray.indexOf(candidate) + 1, 0, elm); - } } } return bgNodes; diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 340dd3c2f6..faca6291bb 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -190,6 +190,20 @@ describe('color-contrast', function () { assert.isTrue(result); }); + it('should return true when there is sufficient contrast based on thead', function () { + fixture.innerHTML = '
Col 1
'; + var target = fixture.querySelector('#target'); + assert.isTrue(checks['color-contrast'].evaluate.call(checkContext, target)); + assert.deepEqual(checkContext._relatedNodes, []); + }); + + it('should return true when there is sufficient contrast based on tbody', function () { + fixture.innerHTML = '
Col 1
'; + var target = fixture.querySelector('#target'); + assert.isTrue(checks['color-contrast'].evaluate.call(checkContext, target)); + assert.deepEqual(checkContext._relatedNodes, []); + }); + it('should return undefined if element overlaps text content', function () { fixture.innerHTML = '
' + '
Hi
' +