Skip to content

Commit

Permalink
fix(link-in-text-block): set links with pseudo-content for review (#4005
Browse files Browse the repository at this point in the history
)

* fix(link-in-text-block): set links with pseudo-content for review

* 🤖 Automated formatting fixes

* fix typo
  • Loading branch information
WilcoFiers authored May 15, 2023
1 parent 4f18976 commit 949f4f8
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 33 deletions.
31 changes: 24 additions & 7 deletions lib/checks/color/link-in-text-block-style-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ const blockLike = [
'grid',
'inline-block'
];
function isBlock(elm) {
var display = window.getComputedStyle(elm).getPropertyValue('display');
return blockLike.indexOf(display) !== -1 || display.substr(0, 6) === 'table-';
}

function linkInTextBlockStyleEvaluate(node) {
export default function linkInTextBlockStyleEvaluate(node) {
if (isBlock(node)) {
return false;
}
Expand All @@ -30,7 +26,28 @@ function linkInTextBlockStyleEvaluate(node) {

this.relatedNodes([parentBlock]);

return elementIsDistinct(node, parentBlock);
if (elementIsDistinct(node, parentBlock)) {
return true;
}
if (hasPseudoContent(node)) {
this.data({ messageKey: 'pseudoContent' });
return undefined;
}
return false;
}

function isBlock(elm) {
var display = window.getComputedStyle(elm).getPropertyValue('display');
return blockLike.indexOf(display) !== -1 || display.substr(0, 6) === 'table-';
}

export default linkInTextBlockStyleEvaluate;
function hasPseudoContent(node) {
for (const pseudo of ['before', 'after']) {
const style = window.getComputedStyle(node, `:${pseudo}`);
const content = style.getPropertyValue('content');
if (content !== 'none') {
return true;
}
}
return false;
}
4 changes: 4 additions & 0 deletions lib/checks/color/link-in-text-block-style.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"impact": "serious",
"messages": {
"pass": "Links can be distinguished from surrounding text by visual styling",
"incomplete": {
"default": "Check if the link needs styling to distinguish it from nearby text",
"pseudoContent": "Check if the link's pseudo style is sufficient to distinguish it from the surrounding text"
},
"fail": "The link has no styling (such as underline) to distinguish it from the surrounding text"
}
}
Expand Down
4 changes: 4 additions & 0 deletions locales/_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,10 @@
},
"link-in-text-block-style": {
"pass": "Links can be distinguished from surrounding text by visual styling",
"incomplete": {
"default": "Check if the link needs styling to distinguish it from nearby text",
"pseudoContent": "Check if the link's pseudo style is sufficient to distinguish it from the surrounding text"
},
"fail": "The link has no styling (such as underline) to distinguish it from the surrounding text"
},
"link-in-text-block": {
Expand Down
77 changes: 52 additions & 25 deletions test/checks/color/link-in-text-block-style.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ describe('link-in-text-block-style', function () {

var checkContext = axe.testUtils.MockCheckContext();

const { queryFixture } = axe.testUtils;
const linkInBlockStyleCheck = axe.testUtils.getCheckEvaluate(
'link-in-text-block-style'
);

before(function () {
styleElm = document.createElement('style');
document.head.appendChild(styleElm);
Expand Down Expand Up @@ -107,11 +112,7 @@ describe('link-in-text-block-style', function () {
axe.testUtils.flatTreeSetup(fixture);
var linkElm = document.getElementById('link');

assert.isFalse(
axe.testUtils
.getCheckEvaluate('link-in-text-block-style')
.call(checkContext, linkElm)
);
assert.isFalse(linkInBlockStyleCheck.call(checkContext, linkElm));
});

(shadowSupport.v1 ? it : xit)(
Expand All @@ -126,11 +127,7 @@ describe('link-in-text-block-style', function () {

axe.testUtils.flatTreeSetup(fixture);

assert.isTrue(
axe.testUtils
.getCheckEvaluate('link-in-text-block-style')
.call(checkContext, linkElm)
);
assert.isTrue(linkInBlockStyleCheck.call(checkContext, linkElm));
}
);

Expand All @@ -148,36 +145,66 @@ describe('link-in-text-block-style', function () {
axe.testUtils.flatTreeSetup(fixture);
var linkElm = div.querySelector('a');

assert.isTrue(
axe.testUtils
.getCheckEvaluate('link-in-text-block-style')
.call(checkContext, linkElm)
);
assert.isTrue(linkInBlockStyleCheck.call(checkContext, linkElm));
}
);
});

describe('links distinguished through style', function () {
it('returns false if link style matches parent', function () {
var linkElm = getLinkElm({});
assert.isFalse(
axe.testUtils
.getCheckEvaluate('link-in-text-block-style')
.call(checkContext, linkElm)
);
assert.isFalse(linkInBlockStyleCheck.call(checkContext, linkElm));
assert.equal(checkContext._relatedNodes[0], linkElm.parentNode);
assert.isNull(checkContext._data);
});

it('returns true if link has underline', function () {
var linkElm = getLinkElm({
textDecoration: 'underline'
});
assert.isTrue(
axe.testUtils
.getCheckEvaluate('link-in-text-block-style')
.call(checkContext, linkElm)
);
assert.isTrue(linkInBlockStyleCheck.call(checkContext, linkElm));
assert.equal(checkContext._relatedNodes[0], linkElm.parentNode);
assert.isNull(checkContext._data);
});

it('returns undefined when the link has a :before pseudo element', function () {
const link = queryFixture(`
<style>
a:before { content: '🔗'; }
a { text-decoration: none; }
</style>
<p>A <a href="#" id="target">link</a> inside a block of text</p>
`).actualNode;
const result = linkInBlockStyleCheck.call(checkContext, link);
assert.isUndefined(result);
assert.deepEqual(checkContext._data, { messageKey: 'pseudoContent' });
assert.equal(checkContext._relatedNodes[0], link.parentNode);
});

it('returns undefined when the link has a :after pseudo element', function () {
const link = queryFixture(`
<style>
a:after { content: ""; }
a { text-decoration: none; }
</style>
<p>A <a href="#" id="target">link</a> inside a block of text</p>
`).actualNode;
const result = linkInBlockStyleCheck.call(checkContext, link);
assert.isUndefined(result);
assert.deepEqual(checkContext._data, { messageKey: 'pseudoContent' });
assert.equal(checkContext._relatedNodes[0], link.parentNode);
});

it('does not return undefined when the pseudo element content is none', function () {
const link = queryFixture(`
<style>
a:after { content: none; position: absolute; }
a { text-decoration: none; }
</style>
<p>A <a href="#" id="target">link</a> inside a block of text</p>
`).actualNode;
const result = linkInBlockStyleCheck.call(checkContext, link);
assert.isFalse(result);
});
});
});
18 changes: 18 additions & 0 deletions test/integration/rules/link-in-text-block/link-in-text-block.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,21 @@ <h1>Incomplete tests</h1>
Link test</a
>
</p>

<style>
#incomplete-pseudo-before {
text-decoration: none;
position: relative;
}
#incomplete-pseudo-before:before {
content: '';
position: absolute;
width: 100%;
height: 1px;
background: purple;
bottom: 2px;
}
</style>
<p id="pseudo">
Lorem <a href="#" id="incomplete-pseudo-before">ipsum</a> dolor sit.
</p>
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
["#pass-text-color"],
["#pass-same-colors"]
],
"incomplete": [["#incomplete-low-contrast-parent-has-gradient"]]
"incomplete": [
["#incomplete-low-contrast-parent-has-gradient"],
["#incomplete-pseudo-before"]
]
}

0 comments on commit 949f4f8

Please sign in to comment.