Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
14 changes: 12 additions & 2 deletions lib/standards/aria-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,12 @@ const ariaRoles = {
type: 'widget',
requiredContext: ['menu', 'menubar', 'group'],
requiredAttrs: ['aria-checked'],
allowedAttrs: ['aria-expanded', 'aria-posinset', 'aria-readonly', 'aria-setsize'],
allowedAttrs: [
'aria-expanded',
'aria-posinset',
'aria-readonly',
'aria-setsize'
],
superclassRole: ['checkbox', 'menuitem'],
accessibleNameRequired: true,
nameFromContent: true,
Expand All @@ -388,7 +393,12 @@ const ariaRoles = {
type: 'widget',
requiredContext: ['menu', 'menubar', 'group'],
requiredAttrs: ['aria-checked'],
allowedAttrs: ['aria-expanded', 'aria-posinset', 'aria-readonly', 'aria-setsize'],
allowedAttrs: [
'aria-expanded',
'aria-posinset',
'aria-readonly',
'aria-setsize'
],
superclassRole: ['menuitemcheckbox', 'radio'],
accessibleNameRequired: true,
nameFromContent: true,
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);
});
});
});
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"]
]
}