diff --git a/lib/core/base/virtual-node.js b/lib/core/base/virtual-node.js index bed4fa4b06..b41209d823 100644 --- a/lib/core/base/virtual-node.js +++ b/lib/core/base/virtual-node.js @@ -1,8 +1,34 @@ const whitespaceRegex = /[\t\r\n\f]/g; +class AbstractVirtualNode { + constructor() { + this.children = []; + this.parent = null; + } + + get props() { + throw new Error( + 'VirtualNode class must have a "props" object consisting ' + + 'of "nodeType" and "nodeName" properties' + ); + } + + hasClass() { + throw new Error('VirtualNode class must have a "hasClass" function'); + } + + attr() { + throw new Error('VirtualNode class must have a "attr" function'); + } + + hasAttr() { + throw new Error('VirtualNode class must have a "hasAttr" function'); + } +} + // class is unused in the file... // eslint-disable-next-line no-unused-vars -class VirtualNode { +class VirtualNode extends AbstractVirtualNode { /** * Wrap the real node and provide list of the flattened children * @param {Node} node the node in question @@ -10,6 +36,7 @@ class VirtualNode { * @param {String} shadowId the ID of the shadow DOM to which this node belongs */ constructor(node, parent, shadowId) { + super(); this.shadowId = shadowId; this.children = []; this.actualNode = node; @@ -105,3 +132,5 @@ class VirtualNode { return this._cache.tabbableElements; } } + +axe.AbstractVirtualNode = AbstractVirtualNode; diff --git a/test/core/base/virtual-node.js b/test/core/base/virtual-node.js index 1dd27d6f03..e1d13287ed 100644 --- a/test/core/base/virtual-node.js +++ b/test/core/base/virtual-node.js @@ -7,6 +7,56 @@ describe('VirtualNode', function() { node = document.createElement('div'); }); + describe('AbstractVirtualNode', function() { + it('should be a function', function() { + assert.isFunction(axe.AbstractVirtualNode); + }); + + it('should throw an error when accessing props', function() { + function fn() { + var abstractNode = new axe.AbstractVirtualNode(); + if (abstractNode.props.nodeType === 1) { + return; + } + } + + assert.throws(fn); + }); + + it('should throw an error when accessing hasClass', function() { + function fn() { + var abstractNode = new axe.AbstractVirtualNode(); + if (abstractNode.hasClass('foo')) { + return; + } + } + + assert.throws(fn); + }); + + it('should throw an error when accessing attr', function() { + function fn() { + var abstractNode = new axe.AbstractVirtualNode(); + if (abstractNode.attr('foo') === 'bar') { + return; + } + } + + assert.throws(fn); + }); + + it('should throw an error when accessing hasAttr', function() { + function fn() { + var abstractNode = new axe.AbstractVirtualNode(); + if (abstractNode.hasAttr('foo')) { + return; + } + } + + assert.throws(fn); + }); + }); + it('should be a function', function() { assert.isFunction(VirtualNode); });