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

feat(virtual-node): add attrNames property which returns list of attribute names #2741

Merged
merged 4 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(virtual-node): add attrNames property which returns list of attr…
…ibute names
  • Loading branch information
straker committed Jan 7, 2021
commit 2e43e6dffb0abadb3c141b80a186e174d4949f40
6 changes: 5 additions & 1 deletion lib/core/base/virtual-node/abstract-virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ class AbstractVirtualNode {
}

attr() {
throw new Error('VirtualNode class must have a "attr" function');
throw new Error('VirtualNode class must have an "attr" function');
}

hasAttr() {
throw new Error('VirtualNode class must have a "hasAttr" function');
}

attrNames() {
throw new Error('VirtualNode class must have an "attrNames" function');
}

hasClass(className) {
// get the value of the class attribute as svgs return a SVGAnimatedString
// if you access the className property
Expand Down
4 changes: 4 additions & 0 deletions lib/core/base/virtual-node/serial-virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class SerialVirtualNode extends AbstractVirtualNode {
hasAttr(attrName) {
return this._attrs[attrName] !== undefined;
}

get attrNames() {
return Object.keys(this._attrs);
}
}

/**
Expand Down
26 changes: 26 additions & 0 deletions lib/core/base/virtual-node/virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,32 @@ class VirtualNode extends AbstractVirtualNode {
return this.actualNode.hasAttribute(attrName);
}

/**
* Return a list of attributes names for the element.
* @return {String[]}
*/
get attrNames() {
if (!this._cache.hasOwnProperty('attrNames')) {
let attrs;

// eslint-disable-next-line no-restricted-syntax
if (this.actualNode.attributes instanceof window.NamedNodeMap) {
// eslint-disable-next-line no-restricted-syntax
attrs = this.actualNode.attributes;
}
// if the attributes property is not of type NamedNodeMap
// then the DOM has been clobbered. E.g. <form><input name="attributes"></form>.
// We can clone the node to isolate it and then return
// the attributes
else {
attrs = this.actualNode.cloneNode(false).attributes;
}

this._cache.attrNames = Array.from(attrs).map(attr => attr.name);
}
return this._cache.attrNames;
}

/**
* Return a property of the computed style for this element and cache the result. This is much faster than called `getPropteryValue` every time.
* @see https://jsperf.com/get-property-value
Expand Down
1 change: 1 addition & 0 deletions lib/core/utils/get-node-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @method getNodeAttributes
* @memberof axe.utils
* @param {Element} node
* @deprecated
* @returns {NamedNodeMap}
*/
function getNodeAttributes(node) {
Expand Down
11 changes: 11 additions & 0 deletions test/core/base/virtual-node/abstract-virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ describe('AbstractVirtualNode', function() {
assert.throws(fn);
});

it('should throw an error when accessing attrNames', function() {
function fn() {
var abstractNode = new axe.AbstractVirtualNode();
if (abstractNode.attrNames()) {
return;
}
}

assert.throws(fn);
});

it('should throw an error when accessing hasAttr', function() {
function fn() {
var abstractNode = new axe.AbstractVirtualNode();
Expand Down
18 changes: 18 additions & 0 deletions test/core/base/virtual-node/serial-virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,22 @@ describe('SerialVirtualNode', function() {
assert.isTrue(nodeWithClass.hasAttr('class'));
});
});

describe('attrNames', function() {
it('should return a list of attribute names', function() {
var vNode = new SerialVirtualNode({
nodeName: 'div',
attributes: { foo: 'bar' }
});

assert.deepEqual(vNode.attrNames, ['foo']);
});

it('should return an empty array if there are no attributes', function() {
var vNode = new SerialVirtualNode({
nodeName: 'div'
});
assert.deepEqual(vNode.attrNames, []);
});
});
});
23 changes: 23 additions & 0 deletions test/core/base/virtual-node/virtual-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ describe('VirtualNode', function() {
});
});

describe('attrNames', function() {
it('should return a list of attribute names', function() {
node.setAttribute('foo', 'bar');
var vNode = new VirtualNode(node);

assert.deepEqual(vNode.attrNames, ['foo']);
});

it('should work with clobbered attributes', function() {
var node = document.createElement('form');
node.setAttribute('id', '123');
node.innerHTML = '<select name="attributes"></select>';
var vNode = new VirtualNode(node);

assert.deepEqual(vNode.attrNames, ['id']);
});

it('should return an empty array if there are no attributes', function() {
var vNode = new VirtualNode(node);
assert.deepEqual(vNode.attrNames, []);
});
});

describe.skip('isFocusable', function() {
var commons;

Expand Down