Skip to content

Commit

Permalink
refactor(presentation-role-conflict): use virtual node (#3596)
Browse files Browse the repository at this point in the history
- use virtual node

references: #3473
  • Loading branch information
dbowling authored Aug 16, 2022
1 parent 13d537a commit e4de11f
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 52 deletions.
4 changes: 1 addition & 3 deletions lib/checks/shared/presentational-role-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getExplicitRole, getRole } from '../../commons/aria';
import { getGlobalAriaAttrs } from '../../commons/standards';
import { isFocusable } from '../../commons/dom';

function presentationalRoleEvaluate(node, options, virtualNode) {
export default function presentationalRoleEvaluate(node, options, virtualNode) {
const role = getRole(virtualNode);
const explicitRole = getExplicitRole(virtualNode);

Expand Down Expand Up @@ -38,5 +38,3 @@ function presentationalRoleEvaluate(node, options, virtualNode) {
});
return false;
}

export default presentationalRoleEvaluate;
30 changes: 11 additions & 19 deletions test/checks/aria/has-global-aria-attribute.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
describe('has-global-aria-attribute', function() {
describe('has-global-aria-attribute', function () {
'use strict';

var fixture = document.getElementById('fixture');
var checkSetup = axe.testUtils.checkSetup;

var checkContext = axe.testUtils.MockCheckContext();
var evaluate = axe.testUtils.getCheckEvaluate('has-global-aria-attribute');
var hasGlobalAriaAttribute = axe.testUtils.getCheckEvaluate(
'has-global-aria-attribute'
);

afterEach(function() {
fixture.innerHTML = '';
axe._tree = undefined;
afterEach(function () {
checkContext.reset();
});

it('should return true if any global ARIA attributes are found', function() {
var node = document.createElement('div');
node.id = 'test';
node.setAttribute('aria-label', 'hello');
var params = checkSetup(node);
assert.isTrue(evaluate.apply(checkContext, params));
it('should return true if any global ARIA attributes are found', function () {
var params = checkSetup('<div aria-label="hello" id="target"></div>');
assert.isTrue(hasGlobalAriaAttribute.apply(checkContext, params));
});

it('should return false if no valid ARIA attributes are found', function() {
var node = document.createElement('div');
node.id = 'test';
node.setAttribute('aria-random', 'hello');
var params = checkSetup(node);
assert.isFalse(evaluate.apply(checkContext, params));
it('should return false if no valid ARIA attributes are found', function () {
var params = checkSetup('<div aria-random="hello" id="target"></div>');
assert.isFalse(hasGlobalAriaAttribute.apply(checkContext, params));
});
});
40 changes: 10 additions & 30 deletions test/checks/aria/is-element-focusable.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
describe('is-element-focusable', function() {
describe('is-element-focusable', function () {
'use strict';

var fixture = document.getElementById('fixture');
var checkSetup = axe.testUtils.checkSetup;
var checkContext = axe.testUtils.MockCheckContext();
var isFocusable = axe.testUtils.getCheckEvaluate('is-element-focusable');

afterEach(function() {
fixture.innerHTML = '';
afterEach(function () {
checkContext.reset();
});

it('should return true for div with a tabindex', function() {
var node = document.createElement('div');
node.id = 'target';
node.tabIndex = 1;
fixture.appendChild(node);
axe._tree = axe.utils.getFlattenedTree(fixture);
var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);

assert.isTrue(
axe.testUtils
.getCheckEvaluate('is-element-focusable')
.call(checkContext, node, {}, virtualNode)
);
it('should return true for div with a tabindex', function () {
var params = checkSetup('<div tabIndex="1" id="target"></div>');
assert.isTrue(isFocusable.apply(checkContext, params));
});

it('should return false for natively unfocusable element', function() {
var node = document.createElement('span');
node.id = 'target';
node.role = 'link';
node.href = '#';
fixture.appendChild(node);
axe._tree = axe.utils.getFlattenedTree(fixture);
var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
assert.isFalse(
axe.testUtils
.getCheckEvaluate('is-element-focusable')
.call(checkContext, node, {}, virtualNode)
);
it('should return false for natively unfocusable element', function () {
var params = checkSetup('<span role="link" href="#" id="target"></span>');
assert.isFalse(isFocusable.apply(checkContext, params));
});
});
128 changes: 128 additions & 0 deletions test/integration/virtual-rules/presentation-role-conflict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
describe('presentation-role-conflict virtual-rule', function () {
it('should fail when role is presentation and aria-label is present', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'li',
attributes: {
role: 'presentation',
'aria-label': 'foobar'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 1);
assert.lengthOf(results.incomplete, 0);
});

it('should fail when role is none and aria-label is present', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'li',
attributes: {
role: 'none',
'aria-label': 'foobar'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 1);
assert.lengthOf(results.incomplete, 0);
});

it('should be inapplicable when explicit role is presentation for element without conflict', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'div',
attributes: {
role: 'presentation'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.inapplicable, 1);
assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 0);
assert.lengthOf(results.incomplete, 0);
});

it('should be inapplicable when explicit role is none for element without conflict', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'div',
attributes: {
role: 'none'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.inapplicable, 1);
assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 0);
assert.lengthOf(results.incomplete, 0);
});

it('should pass for element with implicit role in chromium', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'svg',
attributes: {
role: 'presentation'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 1);
assert.lengthOf(results.violations, 0);
assert.lengthOf(results.incomplete, 0);
});

it('should fail if element has native focusability', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'a',
attributes: {
role: 'presentation',
href: '#'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 1);
assert.lengthOf(results.incomplete, 0);
});

it('should pass if element has native focusability but is disabled', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'button',
attributes: {
role: 'presentation',
disabled: 'disabled'
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 1);
assert.lengthOf(results.violations, 0);
assert.lengthOf(results.incomplete, 0);
});

it('should fail if element is focusable with tabIndex', function () {
var node = new axe.SerialVirtualNode({
nodeName: 'svg',
attributes: {
role: 'presentation',
tabindex: 1
}
});

var results = axe.runVirtualRule('presentation-role-conflict', node);

assert.lengthOf(results.passes, 0);
assert.lengthOf(results.violations, 1);
assert.lengthOf(results.incomplete, 0);
});
});

0 comments on commit e4de11f

Please sign in to comment.