Skip to content

Commit ab877f9

Browse files
authored
fix(link-in-text-block): don't match style or script text (dequelabs#3775)
* fix(link-in-text-block): don't match style or script text * fake img
1 parent d11aed8 commit ab877f9

File tree

5 files changed

+120
-32
lines changed

5 files changed

+120
-32
lines changed

lib/checks/color/link-in-text-block-evaluate.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ function linkInTextBlockEvaluate(node, options) {
5151
// Compute contrasts, giving preference to foreground color and doing as little work as possible
5252
var textContrast =
5353
nodeColor && parentColor ? getContrast(nodeColor, parentColor) : undefined;
54+
if (textContrast) {
55+
textContrast = Math.floor(textContrast * 100) / 100;
56+
}
5457

5558
if (textContrast && textContrast >= requiredContrastRatio) {
5659
return true;
@@ -61,6 +64,10 @@ function linkInTextBlockEvaluate(node, options) {
6164
? getContrast(nodeBackgroundColor, parentBackgroundColor)
6265
: undefined;
6366

67+
if (backgroundContrast) {
68+
backgroundContrast = Math.floor(backgroundContrast * 100) / 100;
69+
}
70+
6471
if (backgroundContrast && backgroundContrast >= requiredContrastRatio) {
6572
return true;
6673
}
@@ -80,13 +87,17 @@ function linkInTextBlockEvaluate(node, options) {
8087
}
8188

8289
// Report bgContrast only if the background changes but text color stays the same
83-
if (textContrast === 1.0 && backgroundContrast > 1.0) {
90+
if (textContrast === 1 && backgroundContrast > 1) {
8491
this.data({
8592
messageKey: 'bgContrast',
8693
contrastRatio: backgroundContrast,
8794
requiredContrastRatio,
88-
nodeBackgroundColor,
89-
parentBackgroundColor
95+
nodeBackgroundColor: nodeBackgroundColor
96+
? nodeBackgroundColor.toHexString()
97+
: undefined,
98+
parentBackgroundColor: parentBackgroundColor
99+
? parentBackgroundColor.toHexString()
100+
: undefined
90101
});
91102
return false;
92103
}
@@ -95,8 +106,8 @@ function linkInTextBlockEvaluate(node, options) {
95106
messageKey: 'fgContrast',
96107
contrastRatio: textContrast,
97108
requiredContrastRatio,
98-
nodeColor,
99-
parentColor
109+
nodeColor: nodeColor ? nodeColor.toHexString() : undefined,
110+
parentColor: parentColor ? parentColor.toHexString() : undefined
100111
});
101112
return false;
102113
}

lib/rules/link-in-text-block-matches.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { sanitize } from '../commons/text';
22
import { isVisibleOnScreen, isInTextBlock } from '../commons/dom';
33

44
function linkInTextBlockMatches(node) {
5-
var text = sanitize(node.textContent);
5+
var text = sanitize(node.innerText);
66
var role = node.getAttribute('role');
77

88
if (role && role !== 'link') {

test/checks/color/link-in-text-block.js

+50
Original file line numberDiff line numberDiff line change
@@ -303,5 +303,55 @@ describe('link-in-text-block', function () {
303303
);
304304
assert.equal(checkContext._relatedNodes[0], linkElm.parentNode);
305305
});
306+
307+
it('should return the proper values stored in data (fgContrast)', function () {
308+
fixture.innerHTML =
309+
'<div> <span style="display:block; color: #100" id="parent">' +
310+
' <p style="display:inline"><a href="" id="link">' +
311+
' link text ' +
312+
' </a> inside block </p> inside block' +
313+
'</span> outside block </div>';
314+
315+
axe.testUtils.flatTreeSetup(fixture);
316+
var linkElm = document.getElementById('link');
317+
318+
axe.testUtils
319+
.getCheckEvaluate('link-in-text-block')
320+
.call(checkContext, linkElm);
321+
322+
assert.deepEqual(checkContext._data, {
323+
messageKey: 'fgContrast',
324+
contrastRatio: 2.18,
325+
requiredContrastRatio: 3,
326+
nodeColor: '#0000ee',
327+
parentColor: '#110000'
328+
});
329+
});
330+
331+
it('should return the proper values stored in data (bgContrast)', function () {
332+
var linkElm = getLinkElm(
333+
{
334+
color: 'black',
335+
backgroundColor: 'white'
336+
},
337+
{
338+
color: 'black',
339+
backgroundColor: '#F0F0F0'
340+
}
341+
);
342+
assert.isFalse(
343+
axe.testUtils
344+
.getCheckEvaluate('link-in-text-block')
345+
.call(checkContext, linkElm)
346+
);
347+
348+
assert.deepEqual(checkContext._data, {
349+
messageKey: 'bgContrast',
350+
contrastRatio: 1.13,
351+
requiredContrastRatio: 3,
352+
nodeBackgroundColor: '#ffffff',
353+
parentBackgroundColor: '#f0f0f0'
354+
});
355+
});
306356
});
307357
});

test/integration/rules/link-in-text-block/link-in-text-block.html

+12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ <h1>General applicability tests</h1>
2626
<a href="#" id="ignore9">Link text</a>
2727
</p>
2828

29+
<p>
30+
hello world, goodbye world
31+
<a href="#" id="ignore10" style="text-decoration: none; background: #eee">
32+
<style>
33+
a {
34+
color: #333;
35+
}
36+
</style>
37+
<img width="50px" height="50px" src="some-img.png" alt="" />
38+
</a>
39+
</p>
40+
2941
<h1>Default styling tests</h1>
3042

3143
<p style="color: black">
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,82 @@
1-
describe('link-in-text-block-matches', function () {
1+
describe('link-in-text-block-matches', () => {
22
'use strict';
33

4-
var fixture = document.getElementById('fixture');
5-
var fixtureSetup = axe.testUtils.fixtureSetup;
6-
var rule;
4+
const { fixtureSetup } = axe.testUtils;
5+
const rule = axe.utils.getRule('link-in-text-block');
76

8-
beforeEach(function () {
9-
rule = axe.utils.getRule('link-in-text-block');
10-
});
11-
12-
afterEach(function () {
13-
fixture.innerHTML = '';
14-
});
15-
16-
it('should return true if link is in text block', function () {
7+
it('should return true if link is in text block', () => {
178
fixtureSetup(
189
'<p>Some paragraph with text <a id="target" href="#">world</a></p>'
1910
);
20-
var node = document.getElementById('target');
11+
const node = document.getElementById('target');
2112
assert.isTrue(rule.matches(node));
2213
});
2314

24-
it('should return false if element has a non-link role', function () {
15+
it('should return false if element has a non-link role', () => {
2516
fixtureSetup(
2617
'<p>Some paragraph with text <a id="target" href="#" role="button">hello</a></p>'
2718
);
28-
var node = document.getElementById('target');
19+
const node = document.getElementById('target');
2920
assert.isFalse(rule.matches(node));
3021
});
3122

32-
it('should should return false if element does not have text', function () {
23+
it('should should return false if element does not have text', () => {
3324
fixtureSetup(
3425
'<p>Some paragraph with text <a id="target" href="#"></a></p>'
3526
);
36-
var node = document.getElementById('target');
27+
const node = document.getElementById('target');
28+
assert.isFalse(rule.matches(node));
29+
});
30+
31+
it('should return false if element has <style>', () => {
32+
fixtureSetup(`
33+
<p>Some paragraph with text
34+
<a id="target" href="#">
35+
<style>a { color: #333 }</style>
36+
</a>
37+
</p>
38+
`);
39+
const node = document.getElementById('target');
40+
assert.isFalse(rule.matches(node));
41+
});
42+
43+
it('should return false if element has <script>', () => {
44+
fixtureSetup(`
45+
<p>Some paragraph with text
46+
<a id="target" href="#">
47+
<script>console.log('foo')</script>
48+
</a>
49+
</p>
50+
`);
51+
const node = document.getElementById('target');
3752
assert.isFalse(rule.matches(node));
3853
});
3954

40-
it('should return false if element is hidden', function () {
55+
it('should return false if element is hidden', () => {
4156
fixtureSetup(
4257
'<p>Some paragraph with text <a id="target" href="#"" style="display: none">hello</a></p>'
4358
);
44-
var node = document.getElementById('target');
59+
const node = document.getElementById('target');
4560
assert.isFalse(rule.matches(node));
4661
});
4762

48-
it('should return false if link is not in text block', function () {
63+
it('should return false if link is not in text block', () => {
4964
fixtureSetup('<a id="target" href="#">hello</a>');
50-
var node = document.getElementById('target');
65+
const node = document.getElementById('target');
5166
assert.isFalse(rule.matches(node));
5267
});
5368

54-
it('should return false if link is only text in block', function () {
69+
it('should return false if link is only text in block', () => {
5570
fixtureSetup('<p><a id="target" href="#">world</a></p>');
56-
var node = document.getElementById('target');
71+
const node = document.getElementById('target');
5772
assert.isFalse(rule.matches(node));
5873
});
5974

60-
it('should return false if link is display block', function () {
75+
it('should return false if link is display block', () => {
6176
fixtureSetup(
6277
'<p>Some paragraph with text <a id="target" href="#" style="display: block">world</a></p>'
6378
);
64-
var node = document.getElementById('target');
79+
const node = document.getElementById('target');
6580
assert.isFalse(rule.matches(node));
6681
});
6782
});

0 commit comments

Comments
 (0)