From ab877f9d709205c2dadffc656f82dc631b66687b Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Wed, 9 Nov 2022 13:32:25 -0700 Subject: [PATCH] fix(link-in-text-block): don't match style or script text (#3775) * fix(link-in-text-block): don't match style or script text * fake img --- .../color/link-in-text-block-evaluate.js | 21 ++++-- lib/rules/link-in-text-block-matches.js | 2 +- test/checks/color/link-in-text-block.js | 50 ++++++++++++++ .../link-in-text-block.html | 12 ++++ .../link-in-text-block-matches.js | 67 ++++++++++++------- 5 files changed, 120 insertions(+), 32 deletions(-) diff --git a/lib/checks/color/link-in-text-block-evaluate.js b/lib/checks/color/link-in-text-block-evaluate.js index f051413017..df9b03f446 100644 --- a/lib/checks/color/link-in-text-block-evaluate.js +++ b/lib/checks/color/link-in-text-block-evaluate.js @@ -51,6 +51,9 @@ function linkInTextBlockEvaluate(node, options) { // Compute contrasts, giving preference to foreground color and doing as little work as possible var textContrast = nodeColor && parentColor ? getContrast(nodeColor, parentColor) : undefined; + if (textContrast) { + textContrast = Math.floor(textContrast * 100) / 100; + } if (textContrast && textContrast >= requiredContrastRatio) { return true; @@ -61,6 +64,10 @@ function linkInTextBlockEvaluate(node, options) { ? getContrast(nodeBackgroundColor, parentBackgroundColor) : undefined; + if (backgroundContrast) { + backgroundContrast = Math.floor(backgroundContrast * 100) / 100; + } + if (backgroundContrast && backgroundContrast >= requiredContrastRatio) { return true; } @@ -80,13 +87,17 @@ function linkInTextBlockEvaluate(node, options) { } // Report bgContrast only if the background changes but text color stays the same - if (textContrast === 1.0 && backgroundContrast > 1.0) { + if (textContrast === 1 && backgroundContrast > 1) { this.data({ messageKey: 'bgContrast', contrastRatio: backgroundContrast, requiredContrastRatio, - nodeBackgroundColor, - parentBackgroundColor + nodeBackgroundColor: nodeBackgroundColor + ? nodeBackgroundColor.toHexString() + : undefined, + parentBackgroundColor: parentBackgroundColor + ? parentBackgroundColor.toHexString() + : undefined }); return false; } @@ -95,8 +106,8 @@ function linkInTextBlockEvaluate(node, options) { messageKey: 'fgContrast', contrastRatio: textContrast, requiredContrastRatio, - nodeColor, - parentColor + nodeColor: nodeColor ? nodeColor.toHexString() : undefined, + parentColor: parentColor ? parentColor.toHexString() : undefined }); return false; } diff --git a/lib/rules/link-in-text-block-matches.js b/lib/rules/link-in-text-block-matches.js index 6ef7a0c3cc..448740e253 100644 --- a/lib/rules/link-in-text-block-matches.js +++ b/lib/rules/link-in-text-block-matches.js @@ -2,7 +2,7 @@ import { sanitize } from '../commons/text'; import { isVisibleOnScreen, isInTextBlock } from '../commons/dom'; function linkInTextBlockMatches(node) { - var text = sanitize(node.textContent); + var text = sanitize(node.innerText); var role = node.getAttribute('role'); if (role && role !== 'link') { diff --git a/test/checks/color/link-in-text-block.js b/test/checks/color/link-in-text-block.js index fb43a2f6d9..9811041797 100644 --- a/test/checks/color/link-in-text-block.js +++ b/test/checks/color/link-in-text-block.js @@ -303,5 +303,55 @@ describe('link-in-text-block', function () { ); assert.equal(checkContext._relatedNodes[0], linkElm.parentNode); }); + + it('should return the proper values stored in data (fgContrast)', function () { + fixture.innerHTML = + '
' + + '

' + + ' link text ' + + ' inside block

inside block' + + '
outside block
'; + + axe.testUtils.flatTreeSetup(fixture); + var linkElm = document.getElementById('link'); + + axe.testUtils + .getCheckEvaluate('link-in-text-block') + .call(checkContext, linkElm); + + assert.deepEqual(checkContext._data, { + messageKey: 'fgContrast', + contrastRatio: 2.18, + requiredContrastRatio: 3, + nodeColor: '#0000ee', + parentColor: '#110000' + }); + }); + + it('should return the proper values stored in data (bgContrast)', function () { + var linkElm = getLinkElm( + { + color: 'black', + backgroundColor: 'white' + }, + { + color: 'black', + backgroundColor: '#F0F0F0' + } + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('link-in-text-block') + .call(checkContext, linkElm) + ); + + assert.deepEqual(checkContext._data, { + messageKey: 'bgContrast', + contrastRatio: 1.13, + requiredContrastRatio: 3, + nodeBackgroundColor: '#ffffff', + parentBackgroundColor: '#f0f0f0' + }); + }); }); }); diff --git a/test/integration/rules/link-in-text-block/link-in-text-block.html b/test/integration/rules/link-in-text-block/link-in-text-block.html index d3826754af..f8f79e02fa 100644 --- a/test/integration/rules/link-in-text-block/link-in-text-block.html +++ b/test/integration/rules/link-in-text-block/link-in-text-block.html @@ -26,6 +26,18 @@

General applicability tests

Link text

+

+ hello world, goodbye world + + + + +

+

Default styling tests

diff --git a/test/rule-matches/link-in-text-block-matches.js b/test/rule-matches/link-in-text-block-matches.js index 7ac1d20c62..e1740114d4 100644 --- a/test/rule-matches/link-in-text-block-matches.js +++ b/test/rule-matches/link-in-text-block-matches.js @@ -1,67 +1,82 @@ -describe('link-in-text-block-matches', function () { +describe('link-in-text-block-matches', () => { 'use strict'; - var fixture = document.getElementById('fixture'); - var fixtureSetup = axe.testUtils.fixtureSetup; - var rule; + const { fixtureSetup } = axe.testUtils; + const rule = axe.utils.getRule('link-in-text-block'); - beforeEach(function () { - rule = axe.utils.getRule('link-in-text-block'); - }); - - afterEach(function () { - fixture.innerHTML = ''; - }); - - it('should return true if link is in text block', function () { + it('should return true if link is in text block', () => { fixtureSetup( '

Some paragraph with text world

' ); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isTrue(rule.matches(node)); }); - it('should return false if element has a non-link role', function () { + it('should return false if element has a non-link role', () => { fixtureSetup( '

Some paragraph with text hello

' ); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); - it('should should return false if element does not have text', function () { + it('should should return false if element does not have text', () => { fixtureSetup( '

Some paragraph with text

' ); - var node = document.getElementById('target'); + const node = document.getElementById('target'); + assert.isFalse(rule.matches(node)); + }); + + it('should return false if element has + +

+ `); + const node = document.getElementById('target'); + assert.isFalse(rule.matches(node)); + }); + + it('should return false if element has + +

+ `); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); - it('should return false if element is hidden', function () { + it('should return false if element is hidden', () => { fixtureSetup( '

Some paragraph with text

' ); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); - it('should return false if link is not in text block', function () { + it('should return false if link is not in text block', () => { fixtureSetup('hello'); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); - it('should return false if link is only text in block', function () { + it('should return false if link is only text in block', () => { fixtureSetup('

world

'); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); - it('should return false if link is display block', function () { + it('should return false if link is display block', () => { fixtureSetup( '

Some paragraph with text world

' ); - var node = document.getElementById('target'); + const node = document.getElementById('target'); assert.isFalse(rule.matches(node)); }); });