diff --git a/doc/API.md b/doc/API.md
index f095677653..c94453f7b0 100644
--- a/doc/API.md
+++ b/doc/API.md
@@ -24,7 +24,8 @@
1. [Virtual DOM Utilities](#virtual-dom-utilities)
1. [API Name: axe.utils.querySelectorAll](#api-name-axeutilsqueryselectorall)
1. [Common Functions](#common-functions)
-1. [Section 3: Example Reference](#section-5-example-reference)
+1. [Section 3: Example Reference](#section-3-example-reference)
+1. [Section 4: Performance](#section-4-performance)
## Section 1: Introduction
@@ -716,3 +717,37 @@ Either the matching HTMLElement or `null` if there was no match.
## Section 3: Example Reference
This package contains examples for [jasmine](examples/jasmine), [mocha](examples/mocha), [phantomjs](examples/phantomjs), [qunit](examples/qunit), [selenium using javascript](examples/selenium), and [generating HTML from the violations array](examples/html-handlebars.md). Each of these examples is in the [doc/examples](examples) folder. In each folder, there is a README.md file which contains specific information about each example.
+
+## Section 4: Performance
+
+Axe-core performs very well in general and if you are analyzing average complexity pages with the default settings, you should not need to worry about performance at all. There are some scenarios that can cause performance issues. This is the list of known issues and what you can do to mitigate and/or avoid them.
+
+### Very large pages
+
+Certain rules (like the color-contrast rule) look at almost every element on a page and some of these rules also perform somewhat expensive operations on these elements including looking up the hierarchy, looking at overlapping elements, calculating the computed styles etc. It also calculates a unique selector for each element in the results and also de-duplicates elements so that you do not get duplicate items in your results.
+
+If your page is very large (in terms of the number of Elements on the page) i.e. >50K elements on the page, then you will see analysis times that run over 10s on a relatively decent CPU.
+
+#### Use resultTypes
+
+An approach you can take to reducing the time is use the `resultTypes` option. By calling `axe.run` with the following options, axe-core will only return the full details of the `violations` array and will only return one instance of each of the `inapplicable`, `incomplete` and `pass` array for each rule that has at least one of those entries. This will reduce the amount of computation that axe-core does for the unique selectors.
+
+```
+{
+ resultTypes: ['violations']
+}
+```
+
+### Multiple include regions
+
+If you tell axe-core to only analyze a section of the page and you have multiple selectors for pages to include, then axe-core must select within each region (which could be overlapping) and de-duplicate the matching elements. This is expensive and becomes more expensive, the more regions you supply and the larger the page.
+
+#### Analyze each region separately
+
+If you find yourself doing this with regions that contain a lot of elements, it might be faster to analyze each region separately and then merge the results outside of axe-core. Especially if you know that the regions are not overlapping, you can easily just concat the results.
+
+### Other strategies
+
+#### Targeted color-contrast analysis
+
+If you are analyzing multiple pages on a single Web site or application, chances are these pages all contain the same styles. It is therefore not adding any additional information to your analysis to analyze every page for color-contrast. Choose a small number of pages that represent the totality of you styles and analyze these with color-contrast and analyze all others without it.
diff --git a/lib/checks/aria/required-parent.js b/lib/checks/aria/required-parent.js
index 5a4ef3614f..15e042dc46 100644
--- a/lib/checks/aria/required-parent.js
+++ b/lib/checks/aria/required-parent.js
@@ -3,9 +3,9 @@ function getSelector(role) {
return impliedNative.concat('[role="' + role + '"]').join(',');
}
-function getMissingContext(element, requiredContext, includeElement) {
+function getMissingContext(virtualNode, requiredContext, includeElement) {
var index, length,
- role = element.getAttribute('role'),
+ role = virtualNode.actualNode.getAttribute('role'),
missing = [];
if (!requiredContext) {
@@ -15,10 +15,10 @@ function getMissingContext(element, requiredContext, includeElement) {
if (!requiredContext) { return null; }
for (index = 0, length = requiredContext.length; index < length; index++) {
- if (includeElement && axe.utils.matchesSelector(element, getSelector(requiredContext[index]))) {
+ if (includeElement && axe.utils.matchesSelector(virtualNode.actualNode, getSelector(requiredContext[index]))) {
return null;
}
- if (axe.commons.dom.findUp(element, getSelector(requiredContext[index]))) {
+ if (axe.commons.dom.findUpVirtual(virtualNode, getSelector(requiredContext[index]))) {
//if one matches, it passes
return null;
} else {
@@ -46,7 +46,7 @@ function getAriaOwners(element) {
return owners.length ? owners : null;
}
-var missingParents = getMissingContext(node);
+var missingParents = getMissingContext(virtualNode);
if (!missingParents) { return true; }
@@ -54,7 +54,7 @@ var owners = getAriaOwners(node);
if (owners) {
for (var i = 0, l = owners.length; i < l; i++) {
- missingParents = getMissingContext(owners[i], missingParents, true);
+ missingParents = getMissingContext(axe.utils.getNodeFromTree(axe._tree[0], owners[i]), missingParents, true);
if (!missingParents) { return true; }
}
}
diff --git a/lib/checks/forms/fieldset.js b/lib/checks/forms/fieldset.js
index 4eaaedfb12..ab38faa3d6 100644
--- a/lib/checks/forms/fieldset.js
+++ b/lib/checks/forms/fieldset.js
@@ -56,22 +56,22 @@ function spliceCurrentNode(nodes, current) {
});
}
-function runCheck(element) {
- const name = axe.commons.utils.escapeSelector(node.name);
- const root = axe.commons.dom.getRootNode(node);
+function runCheck(virtualNode) {
+ const name = axe.commons.utils.escapeSelector(virtualNode.actualNode.name);
+ const root = axe.commons.dom.getRootNode(virtualNode.actualNode);
const matchingNodes = root.querySelectorAll('input[type="' +
- axe.commons.utils.escapeSelector(node.type) + '"][name="' + name + '"]');
+ axe.commons.utils.escapeSelector(virtualNode.actualNode.type) + '"][name="' + name + '"]');
if (matchingNodes.length < 2) {
return true;
}
- const fieldset = axe.commons.dom.findUp(element, 'fieldset');
- const group = axe.commons.dom.findUp(element, '[role="group"]' +
- (node.type === 'radio' ? ',[role="radiogroup"]' : ''));
+ const fieldset = axe.commons.dom.findUpVirtual(virtualNode, 'fieldset');
+ const group = axe.commons.dom.findUpVirtual(virtualNode, '[role="group"]' +
+ (virtualNode.actualNode.type === 'radio' ? ',[role="radiogroup"]' : ''));
if (!group && !fieldset) {
failureCode = 'no-group';
- self.relatedNodes(spliceCurrentNode(matchingNodes, element));
+ self.relatedNodes(spliceCurrentNode(matchingNodes, virtualNode.actualNode));
return false;
} else if (fieldset) {
@@ -86,7 +86,7 @@ var data = {
type: node.getAttribute('type')
};
-var result = runCheck(node);
+var result = runCheck(virtualNode);
if (!result) {
data.failureCode = failureCode;
}
diff --git a/lib/checks/label/implicit.js b/lib/checks/label/implicit.js
index f5df7ccf2b..f57f653d35 100644
--- a/lib/checks/label/implicit.js
+++ b/lib/checks/label/implicit.js
@@ -1,5 +1,5 @@
-var label = axe.commons.dom.findUp(node, 'label');
+var label = axe.commons.dom.findUpVirtual(virtualNode, 'label');
if (label) {
return !!axe.commons.text.accessibleText(label);
}
diff --git a/lib/checks/navigation/p-as-heading.js b/lib/checks/navigation/p-as-heading.js
index 9f08de59f1..7c5d3dec93 100644
--- a/lib/checks/navigation/p-as-heading.js
+++ b/lib/checks/navigation/p-as-heading.js
@@ -70,7 +70,7 @@ if (!nextStyle || !isHeaderStyle(currStyle, nextStyle, margins)) {
return true;
}
-let blockquote = axe.commons.dom.findUp(node, 'blockquote');
+let blockquote = axe.commons.dom.findUpVirtual(virtualNode, 'blockquote');
if (blockquote && blockquote.nodeName.toUpperCase() === 'BLOCKQUOTE') {
return undefined;
}
diff --git a/lib/commons/dom/find-up.js b/lib/commons/dom/find-up.js
index 589c899dd7..5d5a2056a2 100644
--- a/lib/commons/dom/find-up.js
+++ b/lib/commons/dom/find-up.js
@@ -1,34 +1,54 @@
/* global dom, axe */
/**
- * recusively walk up the DOM, checking for a node which matches a selector
+ * Find the virtual node and call dom.fundUpVirtual
*
* **WARNING:** this should be used sparingly, as it's not even close to being performant
* @method findUp
* @memberof axe.commons.dom
* @instance
- * @param {HTMLElement|String} element The starting HTMLElement
+ * @param {HTMLElement} element The starting HTMLElement
* @param {String} target The selector for the HTMLElement
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
*/
dom.findUp = function (element, target) {
- let doc, matches,
- parent = element;
+ return dom.findUpVirtual(axe.utils.getNodeFromTree(axe._tree[0], element), target);
+};
+
+/**
+ * recusively walk up the DOM, checking for a node which matches a selector
+ *
+ * **WARNING:** this should be used sparingly, as it's not even close to being performant
+ * @method findUpVirtual
+ * @memberof axe.commons.dom
+ * @instance
+ * @param {VirtualNode} element The starting virtualNode
+ * @param {String} target The selector for the HTMLElement
+ * @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
+ */
+dom.findUpVirtual = function (element, target) {
+ let parent;
+ parent = element.actualNode;
+ // virtualNode will have a shadowId if the element lives inside a shadow DOM or is
+ // slotted into a shadow DOM
+ if (!element.shadowId && typeof element.actualNode.closest === 'function') {
+ // non-shadow DOM elements
+ let match = element.actualNode.closest(target);
+ if (match) {
+ return match;
+ }
+ return null;
+ }
+ // handle shadow DOM elements and older browsers
do {// recursively walk up the DOM, checking each parent node
parent = (parent.assignedSlot ? parent.assignedSlot : parent.parentNode);
if (parent && parent.nodeType === 11) {
- matches = null;
parent = parent.host;
}
- if (!matches) {
- doc = axe.commons.dom.getRootNode(parent);
- matches = doc.querySelectorAll(target);
- matches = axe.utils.toArray(matches);
- if (doc === document && !matches.length) {
- return null;
- }
- }
- } while (parent && !matches.includes(parent));
+ } while (parent && !axe.utils.matchesSelector(parent, target) && parent !== document.documentElement);
+ if (!axe.utils.matchesSelector(parent, target)) {
+ return null;
+ }
return parent;
};
diff --git a/lib/commons/text/accessible-text-virtual.js b/lib/commons/text/accessible-text-virtual.js
index d5401d8a1b..8b68dc2bc8 100644
--- a/lib/commons/text/accessible-text-virtual.js
+++ b/lib/commons/text/accessible-text-virtual.js
@@ -16,17 +16,17 @@ var phrasingElements = ['A', 'EM', 'STRONG', 'SMALL', 'MARK', 'ABBR', 'DFN', 'I'
/**
* Find a non-ARIA label for an element
* @private
- * @param {HTMLElement} element The HTMLElement
+ * @param {VirtualNode} element The VirtualNode instance whose label we are seeking
* @return {HTMLElement} The label element, or null if none is found
*/
-function findLabel({ actualNode }) {
+function findLabel(virtualNode) {
let label;
- if (actualNode.id) {
+ if (virtualNode.actualNode.id) {
label = dom.findElmsInContext({
- elm: 'label', attr: 'for', value: actualNode.id, context: actualNode
+ elm: 'label', attr: 'for', value: virtualNode.actualNode.id, context: virtualNode.actualNode
})[0];
} else {
- label = dom.findUp(actualNode, 'label');
+ label = dom.findUpVirtual(virtualNode, 'label');
}
return axe.utils.getNodeFromTree(axe._tree[0], label);
}
@@ -52,7 +52,7 @@ function shouldNeverCheckSubtree({ actualNode }) {
/**
* Calculate value of a form element when treated as a value
* @private
- * @param {HTMLElement} element The HTMLElement
+ * @param {VirtualNode} element The VirtualNode instance whose value we want
* @return {string} The calculated value
*/
function formValueText({ actualNode }) {
@@ -103,7 +103,7 @@ function checkDescendant({ actualNode }, nodeName) {
/**
* Determine whether an element can be an embedded control
* @private
- * @param {HTMLElement} element The HTMLElement
+ * @param {VirtualNode} element The VirtualNode instance of the element
* @return {boolean} True if embedded control
*/
function isEmbeddedControl(elm) {
@@ -273,7 +273,7 @@ text.accessibleTextVirtual = function accessibleTextVirtual(element, inLabelledB
* Determine the accessible text of an element, using logic from ARIA:
* http://www.w3.org/TR/accname-aam-1.1/#mapping_additional_nd_name
*
- * @param {HTMLElement} element The HTMLElement
+ * @param {VirtualNode} element The VirtualNode instance of the HTMLElement
* @param {Boolean} inLabelledByContext True when in the context of resolving a labelledBy
* @param {Boolean} inControlContext True when in the context of textifying a widget
* @return {string}
diff --git a/lib/commons/text/label-virtual.js b/lib/commons/text/label-virtual.js
index 7ab7393770..af79136ece 100644
--- a/lib/commons/text/label-virtual.js
+++ b/lib/commons/text/label-virtual.js
@@ -28,7 +28,7 @@ text.labelVirtual = function (node) {
}
}
- ref = dom.findUp(node.actualNode, 'label');
+ ref = dom.findUpVirtual(node, 'label');
candidate = ref && text.visible(ref, true);
if (candidate) {
return candidate;
diff --git a/lib/core/utils/select.js b/lib/core/utils/select.js
index 43389ca208..029db974cf 100644
--- a/lib/core/utils/select.js
+++ b/lib/core/utils/select.js
@@ -48,14 +48,29 @@ function isNodeInContext(node, context) {
function pushNode(result, nodes, context) {
'use strict';
+ var temp;
+ var curried = (function (context) {
+ return function (node) {
+ return isNodeInContext(node, context);
+ };
+ })(context);
+ nodes = nodes.filter(curried);
+
+ if (result.length === 0) {
+ return nodes;
+ }
+ if (result.length < nodes.length) {
+ // switch so the comparison is shortest
+ temp = result;
+ result = nodes;
+ nodes = temp;
+ }
for (var i = 0, l = nodes.length; i < l; i++) {
- //jshint loopfunc:true
- if (!result.find(function (item) {
- return item.actualNode === nodes[i].actualNode;
- }) && isNodeInContext(nodes[i], context)) {
+ if (!result.includes(nodes[i])) {
result.push(nodes[i]);
}
}
+ return result;
}
/**
@@ -72,9 +87,9 @@ axe.utils.select = function select(selector, context) {
candidate = context.include[i];
if (candidate.actualNode.nodeType === candidate.actualNode.ELEMENT_NODE &&
axe.utils.matchesSelector(candidate.actualNode, selector)) {
- pushNode(result, [candidate], context);
+ result = pushNode(result, [candidate], context);
}
- pushNode(result, axe.utils.querySelectorAll(candidate, selector), context);
+ result = pushNode(result, axe.utils.querySelectorAll(candidate, selector), context);
}
return result.sort(axe.utils.nodeSorter);
diff --git a/lib/rules/color-contrast-matches.js b/lib/rules/color-contrast-matches.js
index 7fbf47be76..51f633ca82 100644
--- a/lib/rules/color-contrast-matches.js
+++ b/lib/rules/color-contrast-matches.js
@@ -3,7 +3,8 @@
var nodeName = node.nodeName.toUpperCase(),
nodeType = node.type;
-if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.findUp(node, '[aria-disabled="true"]')) {
+if (node.getAttribute('aria-disabled') === 'true' ||
+ axe.commons.dom.findUpVirtual(virtualNode, '[aria-disabled="true"]')) {
return false;
}
@@ -23,16 +24,18 @@ if (nodeName === 'OPTION') {
return false;
}
-if (nodeName === 'BUTTON' && node.disabled || axe.commons.dom.findUp(node, 'button[disabled]')) {
+if (nodeName === 'BUTTON' && node.disabled ||
+ axe.commons.dom.findUpVirtual(virtualNode, 'button[disabled]')) {
return false;
}
-if (nodeName === 'FIELDSET' && node.disabled || axe.commons.dom.findUp(node, 'fieldset[disabled]')) {
+if (nodeName === 'FIELDSET' && node.disabled ||
+ axe.commons.dom.findUpVirtual(virtualNode, 'fieldset[disabled]')) {
return false;
}
// check if the element is a label or label descendant for a disabled control
-var nodeParentLabel = axe.commons.dom.findUp(node, 'label');
+var nodeParentLabel = axe.commons.dom.findUpVirtual(virtualNode, 'label');
if (nodeName === 'LABEL' || nodeParentLabel) {
var relevantNode = node;
var relevantVirtualNode = virtualNode;
diff --git a/test/checks/aria/required-parent.js b/test/checks/aria/required-parent.js
index e105231c9f..c6c4c8cfd8 100644
--- a/test/checks/aria/required-parent.js
+++ b/test/checks/aria/required-parent.js
@@ -16,6 +16,7 @@ describe('aria-required-parent', function () {
afterEach(function () {
fixture.innerHTML = '';
checkContext._data = null;
+ axe._tree = undefined;
});
it('should detect missing required parent', function () {
diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js
index fc848c3c3c..625842a616 100644
--- a/test/checks/color/color-contrast.js
+++ b/test/checks/color/color-contrast.js
@@ -2,6 +2,7 @@ describe('color-contrast', function () {
'use strict';
var fixture = document.getElementById('fixture');
+ var fixtureSetup = axe.testUtils.fixtureSetup;
var checkContext = {
_relatedNodes: [],
@@ -18,6 +19,7 @@ describe('color-contrast', function () {
fixture.innerHTML = '';
checkContext._relatedNodes = [];
checkContext._data = null;
+ axe._tree = undefined;
});
it('should return the proper values stored in data', function () {
@@ -206,13 +208,14 @@ describe('color-contrast', function () {
});
it('should return true when a label wraps a text input', function () {
- fixture.innerHTML = '';
+ fixtureSetup('');
var target = fixture.querySelector('#target');
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], target);
if (window.PHANTOMJS) {
assert.ok('PhantomJS is a liar');
} else {
- var result = checks['color-contrast'].evaluate.call(checkContext, target);
+ var result = checks['color-contrast'].evaluate.call(checkContext, target, {}, virtualNode);
assert.isTrue(result);
}
});
@@ -228,6 +231,7 @@ describe('color-contrast', function () {
it('should return true when there is sufficient contrast based on thead', function () {
fixture.innerHTML = '
Col 1
';
var target = fixture.querySelector('#target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.isTrue(checks['color-contrast'].evaluate.call(checkContext, target));
assert.deepEqual(checkContext._relatedNodes, []);
});
@@ -235,6 +239,7 @@ describe('color-contrast', function () {
it('should return true when there is sufficient contrast based on tbody', function () {
fixture.innerHTML = '
Col 1
';
var target = fixture.querySelector('#target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.isTrue(checks['color-contrast'].evaluate.call(checkContext, target));
assert.deepEqual(checkContext._relatedNodes, []);
});
diff --git a/test/checks/forms/fieldset.js b/test/checks/forms/fieldset.js
index 35fb506153..b63169ca55 100644
--- a/test/checks/forms/fieldset.js
+++ b/test/checks/forms/fieldset.js
@@ -26,7 +26,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
it('should return false if there are two ungrouped ' + type + ' elements with the same name', function () {
@@ -34,7 +35,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'no-group',
type: type,
@@ -48,7 +50,8 @@ describe('fieldset', function () {
fixtureSetup('');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'no-legend',
type: type,
@@ -63,7 +66,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'empty-legend',
type: type,
@@ -79,7 +83,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'mixed-inputs',
type: type,
@@ -94,7 +99,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
it('should return false if an unlabelled ARIA group contains only the right elements', function () {
@@ -103,7 +109,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'no-group-label',
type: type,
@@ -120,7 +127,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'no-group-label',
type: type,
@@ -136,7 +144,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
failureCode: 'group-mixed-inputs',
type: type,
@@ -153,7 +162,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
type: type,
name: 'uniqueyname'
@@ -167,7 +177,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
assert.deepEqual(checkContext._data, {
type: type,
@@ -180,7 +191,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
it('should ignore hidden inputs', function () {
@@ -189,7 +201,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
it('should allow elements to be contained in 2 or more fieldsets', function () {
@@ -202,7 +215,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
it('should allow elements to be contained in 2 or more groups', function () {
@@ -215,7 +229,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
(shadowSupport ? it : xit)('should find fieldsets outside a shadow tree', function () {
@@ -230,7 +245,8 @@ describe('fieldset', function () {
fixtureSetup(fieldset);
var node = shadow.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
(shadowSupport ? it : xit)('should find fieldsets inside a shadow tree', function () {
@@ -245,7 +261,8 @@ describe('fieldset', function () {
fixtureSetup(div);
var node = div.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
}
@@ -261,7 +278,8 @@ describe('fieldset', function () {
'');
var node = fixture.querySelector('#target');
- assert.isTrue(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
});
@@ -275,7 +293,8 @@ describe('fieldset', function () {
'' +
'');
var node = fixture.querySelector('#target');
- assert.isFalse(checks.fieldset.evaluate.call(checkContext, node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks.fieldset.evaluate.call(checkContext, node, {}, virtualNode));
});
});
diff --git a/test/checks/label/implicit.js b/test/checks/label/implicit.js
index bcc04c8983..981a6d9365 100644
--- a/test/checks/label/implicit.js
+++ b/test/checks/label/implicit.js
@@ -6,24 +6,28 @@ describe('implicit-label', function () {
afterEach(function () {
fixture.innerHTML = '';
+ axe._tree = undefined;
});
it('should return false if an empty label is present', function () {
fixtureSetup('');
var node = fixture.querySelector('#target');
- assert.isFalse(checks['implicit-label'].evaluate(node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['implicit-label'].evaluate(node, {}, virtualNode));
});
it('should return false if an invisible non-empty label is present', function () {
fixtureSetup('');
var node = fixture.querySelector('#target');
- assert.isFalse(checks['implicit-label'].evaluate(node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['implicit-label'].evaluate(node, {}, virtualNode));
});
it('should return true if a non-empty label is present', function () {
fixtureSetup('');
var node = fixture.querySelector('#target');
- assert.isTrue(checks['implicit-label'].evaluate(node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['implicit-label'].evaluate(node, {}, virtualNode));
});
it('should return false if a label is not present', function () {
@@ -31,7 +35,8 @@ describe('implicit-label', function () {
node.type = 'text';
fixtureSetup(node);
- assert.isFalse(checks['implicit-label'].evaluate(node));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['implicit-label'].evaluate(node, {}, virtualNode));
});
});
diff --git a/test/checks/navigation/p-as-heading.js b/test/checks/navigation/p-as-heading.js
index daf7c39da5..a485512a5e 100644
--- a/test/checks/navigation/p-as-heading.js
+++ b/test/checks/navigation/p-as-heading.js
@@ -1,6 +1,8 @@
describe('p-as-heading', function () {
'use strict';
var fixture = document.getElementById('fixture');
+ var fixtureSetup = axe.testUtils.fixtureSetup;
+
var checkContext = {
_data: null,
data: function (d) {
@@ -19,87 +21,98 @@ describe('p-as-heading', function () {
afterEach(function () {
fixture.innerHTML = '';
checkContext._data = null;
+ axe._tree = undefined;
});
it('returns true if the styles are identical', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns true if there is no p element following it', function () {
- fixture.innerHTML = '
lone elm
';
+ fixtureSetup('
lone elm
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns false if the font-weight is heavier', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns false if the font-size is bigger', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns false if the fake heading is italic and the text is not', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns true if both texts are bold, italic and larger', function () {
- fixture.innerHTML =
- '
elm 1
' +
- '
elm 2
';
+ fixtureSetup('
elm 1
' +
+ '
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('considers styles of elements inside the paragraph', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('ignores empty child element for style', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('considers styles of elements that do not contain all the text', function () {
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns undefined instead of false if the element is inside a blockquote', function () {
- fixture.innerHTML = '
' +
+ fixtureSetup('
' +
'
elm 1
elm 2
' +
- '
';
+ '
');
var node = fixture.querySelector('p');
- assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns true over undefined from within a blockquote', function () {
- fixture.innerHTML = '
' +
+ fixtureSetup('
' +
'
elm 1
elm 2
' +
- '
';
+ '
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
it('returns undefined if a previous sibling has a similar font-weight', function () {
- fixture.innerHTML =
- '
elm 1
'+
+ fixtureSetup('
elm 1
'+
'
elm 2
'+
- '
elm 3
';
+ '
elm 3
');
var node = fixture.querySelector('#target');
- assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isUndefined(checks['p-as-heading'].evaluate.call(checkContext, node, testOptions, virtualNode));
});
describe('option.margin', function () {
@@ -107,9 +120,10 @@ describe('p-as-heading', function () {
it('passes if no margins are set', function () {
var options = {};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
it('takes an array of margins', function () {
@@ -117,9 +131,10 @@ describe('p-as-heading', function () {
margins: [{ size: 1.2 }]
};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
it('returns false if all values in the margin are passed', function () {
@@ -127,9 +142,10 @@ describe('p-as-heading', function () {
margins: [{ size: 1.2, weight: 100 }]
};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
it('returns true if any of the values is not passed', function () {
@@ -137,9 +153,10 @@ describe('p-as-heading', function () {
margins: [{ size: 1.2, weight: 100 }]
};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
it('returns false if any of the margins is passed', function () {
@@ -151,9 +168,10 @@ describe('p-as-heading', function () {
],
};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isFalse(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
it('returns true if none of the set margins is passed', function () {
@@ -165,9 +183,10 @@ describe('p-as-heading', function () {
]
};
- fixture.innerHTML = '
elm 1
elm 2
';
+ fixtureSetup('
elm 1
elm 2
');
var node = fixture.querySelector('p');
- assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options));
+ var virtualNode = axe.utils.getNodeFromTree(axe._tree[0], node);
+ assert.isTrue(checks['p-as-heading'].evaluate.call(checkContext, node, options, virtualNode));
});
});
diff --git a/test/commons/color/get-background-color.js b/test/commons/color/get-background-color.js
index f6f1c6aad4..a98e5786b0 100644
--- a/test/commons/color/get-background-color.js
+++ b/test/commons/color/get-background-color.js
@@ -7,6 +7,7 @@ describe('color.getBackgroundColor', function () {
document.getElementById('fixture').innerHTML = '';
axe.commons.color.incompleteData.clear();
document.body.scrollTop = 0;
+ axe._tree = undefined;
});
it('should return the blended color if it has no background set', function () {
@@ -16,6 +17,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(128, 0, 0, 1);
assert.closeTo(actual.red, expected.red, 0.5);
@@ -38,6 +40,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var pos = fixture.querySelector('#pos');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(64, 64, 0, 1);
@@ -56,6 +59,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var under = fixture.querySelector('#under');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(64, 64, 0, 1);
assert.closeTo(actual.red, expected.red, 0.5);
@@ -80,6 +84,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var under = fixture.querySelector('#under');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(64, 64, 0, 1);
@@ -97,6 +102,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(64, 64, 0, 1);
assert.closeTo(actual.red, expected.red, 0.5);
@@ -113,6 +119,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(64, 64, 0, 1);
assert.equal(actual.red, expected.red);
@@ -130,6 +137,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
assert.isNull(actual);
assert.deepEqual(bgNodes, [target, parent]);
@@ -139,6 +147,7 @@ describe('color.getBackgroundColor', function () {
it('should return white if transparency goes all the way up to document', function () {
fixture.innerHTML = '
';
var target = fixture.querySelector('#target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
assert.equal(actual.red, expected.red);
@@ -153,6 +162,7 @@ describe('color.getBackgroundColor', function () {
'
';
var target = fixture.querySelector('#target');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
assert.isNull(actual);
assert.deepEqual(bgNodes, [target]);
@@ -162,6 +172,7 @@ describe('color.getBackgroundColor', function () {
it('should return null if something opaque is obscuring it', function () {
fixture.innerHTML = '' +
'
Hello
';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
assert.equal(axe.commons.color.incompleteData.get('bgColor'), 'bgOverlap');
assert.isNull(actual);
@@ -170,6 +181,7 @@ describe('color.getBackgroundColor', function () {
it('should return an actual if something non-opaque is obscuring it', function () {
fixture.innerHTML = '' +
'
Hello
';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
assert.isNotNull(actual);
assert.equal(Math.round(actual.blue), 128);
@@ -183,6 +195,7 @@ describe('color.getBackgroundColor', function () {
'';
var target = fixture.querySelector('#target');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(0, 128, 0, 1);
assert.equal(actual.red, expected.red);
@@ -197,6 +210,7 @@ describe('color.getBackgroundColor', function () {
'' +
'
' +
'';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
if (window.PHANTOMJS) {
assert.ok('PhantomJS is a liar');
@@ -213,6 +227,7 @@ describe('color.getBackgroundColor', function () {
'' +
'
' +
'';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
assert.isNull(actual);
assert.equal(axe.commons.color.incompleteData.get('bgColor'), 'elmPartiallyObscuring');
@@ -229,6 +244,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target'),
parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(243, 243, 243, 1);
assert.equal(actual.red, expected.red);
@@ -249,6 +265,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target'),
parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(243, 243, 243, 1);
assert.equal(actual.red, expected.red);
@@ -269,6 +286,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target'),
parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(243, 243, 243, 1);
assert.equal(actual.red, expected.red);
@@ -286,6 +304,7 @@ describe('color.getBackgroundColor', function () {
var bgNodes = [];
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
assert.equal(actual.red, expected.red);
@@ -301,6 +320,7 @@ describe('color.getBackgroundColor', function () {
'';
var target = fixture.querySelector('#target');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
assert.equal(actual.red, expected.red);
@@ -317,6 +337,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
assert.equal(actual.red, expected.red);
@@ -341,6 +362,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target'),
parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(243, 243, 243, 1);
assert.equal(actual.red, expected.red);
@@ -362,6 +384,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
@@ -382,6 +405,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var parent = fixture.querySelector('#parent');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes);
var expected = new axe.commons.color.Color(255, 255, 255, 1);
@@ -405,6 +429,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var shifted = fixture.querySelector('#shifted');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(target, bgNodes, false);
var expected = new axe.commons.color.Color(0, 0, 0, 1);
@@ -430,6 +455,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var outcome = axe.commons.color.getBackgroundColor(target, bgNodes, false);
assert.isNull(outcome);
assert.equal(axe.commons.color.incompleteData.get('bgColor'), 'bgImage');
@@ -449,6 +475,7 @@ describe('color.getBackgroundColor', function () {
var target = fixture.querySelector('#target');
var bgNodes = [];
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var outcome = axe.commons.color.getBackgroundColor(target, bgNodes, false);
assert.isNull(outcome);
assert.equal(axe.commons.color.incompleteData.get('bgColor'), 'imgNode');
@@ -463,6 +490,7 @@ describe('color.getBackgroundColor', function () {
var bgNodes = [];
window.scroll(0, 0);
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
axe.commons.color.getBackgroundColor(targetEl, bgNodes, true);
assert.equal(window.pageYOffset, 0);
@@ -477,6 +505,7 @@ describe('color.getBackgroundColor', function () {
var bgNodes = [];
window.scroll(0, 0);
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
axe.commons.color.getBackgroundColor(targetEl, bgNodes, false);
assert.notEqual(window.pageYOffset, 0);
@@ -487,6 +516,7 @@ describe('color.getBackgroundColor', function () {
'style="z-index:-1; position:absolute; width:100%; height:2em; background: #000">' +
'
Some text
';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
var expected = new axe.commons.color.Color(0, 0, 0, 1);
@@ -504,6 +534,7 @@ describe('color.getBackgroundColor', function () {
var orig = document.body.style.background;
document.body.style.background = '#FFF';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
var expected = new axe.commons.color.Color(0, 0, 0, 1);
@@ -521,6 +552,7 @@ describe('color.getBackgroundColor', function () {
var orig = document.body.style.background;
document.body.style.background = '#F00';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
var expected = new axe.commons.color.Color(255, 0, 0, 1);
document.body.style.background = orig;
@@ -537,6 +569,7 @@ describe('color.getBackgroundColor', function () {
var orig = document.body.style.background;
document.body.style.background = '#F00';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
var expected = new axe.commons.color.Color(255, 0, 0, 1);
document.body.style.background = orig;
@@ -553,6 +586,7 @@ describe('color.getBackgroundColor', function () {
var orig = document.documentElement.style.background;
document.documentElement.style.background = '#0F0';
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var actual = axe.commons.color.getBackgroundColor(document.getElementById('target'), []);
var expected = new axe.commons.color.Color(0, 255, 0, 1);
document.documentElement.style.background = orig;
@@ -579,6 +613,7 @@ describe('color.getBackgroundColor', function () {
// This shouldn't cause a scroll
var target1 = document.getElementById('tgt1');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
axe.commons.color.getBackgroundColor(target1, []);
// Otherwise this would not be on the black bg anymore:
diff --git a/test/commons/dom/find-up.js b/test/commons/dom/find-up.js
index 2463d30537..8c1abf315d 100644
--- a/test/commons/dom/find-up.js
+++ b/test/commons/dom/find-up.js
@@ -7,6 +7,7 @@ describe('dom.findUp', function () {
afterEach(function () {
fixture.innerHTML = '';
+ axe._tree = undefined;
});
it('should find parents based on selector', function () {
@@ -16,6 +17,7 @@ describe('dom.findUp', function () {
var start = document.getElementById('start'),
target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.dom.findUp(start, '.target'), target, 'Should find it!');
});
@@ -23,6 +25,7 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
var start = document.getElementById('start');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.isNull(axe.commons.dom.findUp(start, '.nomatchyplzkthx'));
});
@@ -31,6 +34,7 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
var start = document.getElementById('start');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.isNull(axe.commons.dom.findUp(start, '.target'));
});
@@ -49,7 +53,7 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var tree = axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var el = axe.utils.querySelectorAll(tree, 'a')[0];
assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
@@ -69,7 +73,7 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var tree = axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var el = axe.utils.querySelectorAll(tree, 'a')[0];
assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
@@ -81,6 +85,7 @@ describe('dom.findUp', function () {
shadow.innerHTML = '
item 1
';
var listItem = shadow.querySelector('[role=listitem]');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.dom.findUp(listItem, '[role=list]'),
fixture.firstChild);
});
@@ -100,11 +105,34 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var tree = axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var el = axe.utils.querySelectorAll(tree, 'a')[0];
assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
+ (shadowSupport.v1 ? it : xit)('should find element in assigned slot, not in the host document', function () {
+ function createContentSlotted() {
+ var group = document.createElement('div');
+ group.className = 'target';
+ var slot = document.createElement('slot');
+ group.appendChild(slot);
+ return group;
+ }
+ function makeShadowTree(node) {
+ var root = node.attachShadow({mode: 'open'});
+ var div = document.createElement('div');
+ root.appendChild(div);
+ div.appendChild(createContentSlotted());
+ }
+
+ fixture.innerHTML = '';
+ makeShadowTree(fixture.querySelector('div'));
+ var tree = axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var el = axe.utils.querySelectorAll(tree, 'a')[0];
+ var target = axe.utils.querySelectorAll(tree, '.target')[0];
+ assert.equal(axe.commons.dom.findUp(el.actualNode, 'div'), target.actualNode);
+ });
+
(shadowSupport.v1 ? it : xit)('should walk up the shadow DOM', function () {
function createContent() {
var group = document.createElement('div');
@@ -120,7 +148,7 @@ describe('dom.findUp', function () {
fixture.innerHTML = '';
makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var tree = axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
var el = axe.utils.querySelectorAll(tree, 'a')[0];
assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
@@ -132,6 +160,7 @@ describe('dom.findUp', function () {
shadow.innerHTML = '
item 1
';
var listItem = shadow.querySelector('[role=listitem]');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.dom.findUp(listItem, '[role=list]'),
fixture.firstChild);
});
diff --git a/test/commons/table/get-cell-position.js b/test/commons/table/get-cell-position.js
index 647411142c..026fd6fe63 100644
--- a/test/commons/table/get-cell-position.js
+++ b/test/commons/table/get-cell-position.js
@@ -4,6 +4,7 @@ describe('table.getCellPosition', function () {
afterEach(function () {
fixture.innerHTML = '';
+ axe._tree = undefined;
});
it('should get x, y coordinates given a cell', function () {
@@ -15,6 +16,7 @@ describe('table.getCellPosition', function () {
var target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getCellPosition(target), {
x: 1,
y: 1
@@ -30,6 +32,7 @@ describe('table.getCellPosition', function () {
var target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getCellPosition(target), {
x: 2,
y: 1
@@ -45,6 +48,7 @@ describe('table.getCellPosition', function () {
var target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getCellPosition(target), {
x: 2,
y: 1
@@ -61,6 +65,7 @@ describe('table.getCellPosition', function () {
var target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getCellPosition(target), {
x: 2,
y: 1
@@ -78,6 +83,7 @@ describe('table.getCellPosition', function () {
var target = document.getElementById('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getCellPosition(target), {
x: 1,
y: 2
diff --git a/test/commons/table/get-headers.js b/test/commons/table/get-headers.js
index e7e2d0961c..c7129c5b1a 100644
--- a/test/commons/table/get-headers.js
+++ b/test/commons/table/get-headers.js
@@ -8,6 +8,7 @@ describe('table.getHeaders', function () {
afterEach(function () {
fixture.innerHTML = '';
+ axe._tree = undefined;
});
it('should work with scope=auto', function () {
@@ -18,6 +19,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2')]);
});
@@ -30,6 +32,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2')]);
});
@@ -43,6 +46,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2'), $id('t3')]);
});
@@ -55,6 +59,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2'), $id('t3')]);
});
@@ -66,6 +71,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1')]);
});
@@ -77,6 +83,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2')]);
});
@@ -88,6 +95,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), [$id('t1'), $id('t2'), $id('t3')]);
});
@@ -100,6 +108,7 @@ describe('table.getHeaders', function () {
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.deepEqual(axe.commons.table.getHeaders(target), []);
});
diff --git a/test/commons/table/get-scope.js b/test/commons/table/get-scope.js
index adb12c0481..cf35b7fee5 100644
--- a/test/commons/table/get-scope.js
+++ b/test/commons/table/get-scope.js
@@ -9,6 +9,7 @@ describe('table.getScope', function () {
afterEach(function () {
fixture.innerHTML = '';
+ axe._tree = undefined;
});
@@ -45,6 +46,7 @@ describe('table.getScope', function () {
'';
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.table.getScope(target), 'auto');
});
@@ -55,6 +57,7 @@ describe('table.getScope', function () {
'';
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.table.getScope(target), 'auto');
});
@@ -65,6 +68,7 @@ describe('table.getScope', function () {
'';
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.table.getScope(target), 'auto');
});
});
@@ -108,6 +112,7 @@ describe('table.getScope', function () {
'';
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.table.getScope(target), 'col');
});
@@ -118,6 +123,7 @@ describe('table.getScope', function () {
'';
var target = $id('target');
+ axe._tree = axe.utils.getFlattenedTree(fixture.firstChild);
assert.equal(axe.commons.table.getScope(target), 'col');
});
@@ -128,6 +134,7 @@ describe('table.getScope', function () {
'