Skip to content

Commit

Permalink
fix(svg-image-alt): work with serial virtual nodes (#2397)
Browse files Browse the repository at this point in the history
* fix(svg-image-alt): work with serial virtual nodes

* fixes

* more fixes

* fix tests
  • Loading branch information
straker committed Jul 20, 2020
1 parent d5b6931 commit e2537ef
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 12 deletions.
8 changes: 7 additions & 1 deletion lib/checks/shared/svg-non-empty-title-evaluate.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import visibleVirtual from '../../commons/text/visible-virtual';

function svgNonEmptyTitleEvaluate(node, options, virtualNode) {
if (!virtualNode.children) {
return undefined;
}

const titleNode = virtualNode.children.find(({ props }) => {
return props.nodeName === 'title';
});
return !!titleNode && titleNode.actualNode.textContent.trim() !== '';
return !!titleNode && visibleVirtual(titleNode) !== '';
}

export default svgNonEmptyTitleEvaluate;
3 changes: 2 additions & 1 deletion lib/checks/shared/svg-non-empty-title.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"impact": "serious",
"messages": {
"pass": "element has a child that is a title",
"fail": "element has no child that is a title"
"fail": "element has no child that is a title",
"incomplete": "Unable to determine element has a child that is a title"
}
}
}
17 changes: 15 additions & 2 deletions lib/rules/svg-namespace-matches.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
function svgNamespaceMatches(node) {
return node.namespaceURI === 'http://www.w3.org/2000/svg';
import { closest } from '../core/utils';

function svgNamespaceMatches(node, virtualNode) {
try {
const nodeName = virtualNode.props.nodeName;

if (nodeName === 'svg') {
return true;
}

// element is svg namespace if its parent is an svg element
return !!closest(virtualNode, 'svg');
} catch (e) {
return false;
}
}

export default svgNamespaceMatches;
54 changes: 46 additions & 8 deletions test/checks/shared/svg-non-empty-title.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('svg-non-empty-title tests', function() {

var fixture = document.getElementById('fixture');
var checkSetup = axe.testUtils.checkSetup;
var check = checks['svg-non-empty-title'];
var checkEvaluate = axe.testUtils.getCheckEvaluate('svg-non-empty-title');

afterEach(function() {
fixture.innerHTML = '';
Expand All @@ -13,44 +13,82 @@ describe('svg-non-empty-title tests', function() {
var checkArgs = checkSetup(
'<svg id="target"><title>Time II: Party</title></svg>'
);
assert.isTrue(check.evaluate.apply(null, checkArgs));
assert.isTrue(checkEvaluate.apply(null, checkArgs));
});

it('returns true if the `title` child has text nested in another element', function() {
var checkArgs = checkSetup(
'<svg id="target"><title><g>Time II: Party</g></title></svg>'
);
assert.isTrue(check.evaluate.apply(null, checkArgs));
assert.isTrue(checkEvaluate.apply(null, checkArgs));
});

it('returns false if the element has no `title` child', function() {
var checkArgs = checkSetup('<svg id="target"></svg>');
assert.isFalse(check.evaluate.apply(null, checkArgs));
assert.isFalse(checkEvaluate.apply(null, checkArgs));
});

it('returns false if the `title` child is empty', function() {
var checkArgs = checkSetup('<svg id="target"><title></title></svg>');
assert.isFalse(check.evaluate.apply(null, checkArgs));
assert.isFalse(checkEvaluate.apply(null, checkArgs));
});

it('returns false if the `title` is a grandchild', function() {
var checkArgs = checkSetup(
'<svg id="target"><circle><title>Time II: Party</title></circle></svg>'
);
assert.isFalse(check.evaluate.apply(null, checkArgs));
assert.isFalse(checkEvaluate.apply(null, checkArgs));
});

it('returns false if the `title` child has only whitespace', function() {
var checkArgs = checkSetup(
'<svg id="target"><title> \t\r\n </title></svg>'
);
assert.isFalse(check.evaluate.apply(null, checkArgs));
assert.isFalse(checkEvaluate.apply(null, checkArgs));
});

it('returns false if there are multiple titles, and the first is empty', function() {
var checkArgs = checkSetup(
'<svg id="target"><title></title><title>Time II: Party</title></svg>'
);
assert.isFalse(check.evaluate.apply(null, checkArgs));
assert.isFalse(checkEvaluate.apply(null, checkArgs));
});

describe('Serial Virtual Node', function() {
it('returns true if the element has a `title` child', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'svg'
});
var child = new axe.SerialVirtualNode({
nodeName: 'title'
});
var text = new axe.SerialVirtualNode({
nodeName: '#text',
nodeType: 3,
nodeValue: 'Time II: Party'
});
child.parent = serialNode;
child.children = [text];
serialNode.children = [child];

assert.isTrue(checkEvaluate(null, {}, serialNode));
});

it('returns false if the element has no `title` child', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'svg'
});
serialNode.children = [];

assert.isFalse(checkEvaluate(null, {}, serialNode));
});

it('returns undefined if the element has empty children', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'svg'
});

assert.isUndefined(checkEvaluate(null, {}, serialNode));
});
});
});
51 changes: 51 additions & 0 deletions test/rule-matches/svg-namespace-matches.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,55 @@ describe('svg-namespace-matches', function() {
var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
assert.isFalse(rule.matches(node, virtualNode));
});

describe('Serial Virtual Node', function() {
it('should return true when passed an SVG element', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'svg'
});
var child = new axe.SerialVirtualNode({
nodeName: 'title',
nodeValue: 'Pretty picture'
});
child.parent = serialNode;
serialNode.children = [child];

assert.isTrue(rule.matches(null, serialNode));
});

it('returns true when passed an SVG circle element', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'svg'
});
var child = new axe.SerialVirtualNode({
nodeName: 'circle'
});
child.parent = serialNode;
serialNode.children = [child];

assert.isTrue(rule.matches(null, child));
});

it('returns false when passed an HTML element', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'h1',
nodeValue: 'Hello world'
});

assert.isFalse(rule.matches(null, serialNode));
});

it('should return false when passed an svg element without a parent', function() {
var serialNode = new axe.SerialVirtualNode({
nodeName: 'circle'
});
var parent = new axe.SerialVirtualNode({
nodeName: 'svg'
});
parent.children = [serialNode];
serialNode.parent = parent;

assert.isTrue(rule.matches(null, serialNode));
});
});
});

0 comments on commit e2537ef

Please sign in to comment.