diff --git a/doc/examples/jsdom/test/a11y.js b/doc/examples/jsdom/test/a11y.js index cfa4688a07..a3c8b4119d 100644 --- a/doc/examples/jsdom/test/a11y.js +++ b/doc/examples/jsdom/test/a11y.js @@ -20,20 +20,6 @@ describe('axe', () => { `); - global.document = window.document; - global.window = window; - - // needed by axios lib/helpers/isURLSameOrigin.js - global.navigator = window.navigator; - - // needed by axe /lib/core/public/run.js - global.Node = window.Node; - global.NodeList = window.NodeList; - - // needed by axe /lib/core/base/context.js - global.Element = window.Element; - global.Document = window.Document; - const axe = require('axe-core'); const config = { rules: { diff --git a/lib/commons/dom/is-node.js b/lib/commons/dom/is-node.js index f832b7f8c1..d4f7c96062 100644 --- a/lib/commons/dom/is-node.js +++ b/lib/commons/dom/is-node.js @@ -9,7 +9,7 @@ */ function isNode(element) { 'use strict'; - return element instanceof Node; + return element instanceof window.Node; } export default isNode; diff --git a/lib/commons/dom/visually-contains.js b/lib/commons/dom/visually-contains.js index f4c52cd50f..47f5c651be 100644 --- a/lib/commons/dom/visually-contains.js +++ b/lib/commons/dom/visually-contains.js @@ -68,8 +68,8 @@ function contains(node, parent) { style.overflow === 'scroll' || style.overflow === 'auto' || style.overflow === 'hidden' || - parent instanceof HTMLBodyElement || - parent instanceof HTMLHtmlElement + parent instanceof window.HTMLBodyElement || + parent instanceof window.HTMLHtmlElement ); } diff --git a/lib/commons/dom/visually-overlaps.js b/lib/commons/dom/visually-overlaps.js index bc8ba9089d..76dc4b4e52 100644 --- a/lib/commons/dom/visually-overlaps.js +++ b/lib/commons/dom/visually-overlaps.js @@ -35,8 +35,8 @@ function visuallyOverlaps(rect, parent) { return ( style.overflow === 'scroll' || style.overflow === 'auto' || - parent instanceof HTMLBodyElement || - parent instanceof HTMLHtmlElement + parent instanceof window.HTMLBodyElement || + parent instanceof window.HTMLHtmlElement ); } diff --git a/lib/commons/table/get-scope.js b/lib/commons/table/get-scope.js index ad70a46688..5fe9fc108e 100644 --- a/lib/commons/table/get-scope.js +++ b/lib/commons/table/get-scope.js @@ -15,7 +15,7 @@ function getScope(cell) { var role = cell.getAttribute('role'); if ( - cell instanceof Element === false || + cell instanceof window.Element === false || ['TD', 'TH'].indexOf(cell.nodeName.toUpperCase()) === -1 ) { throw new TypeError('Expected TD or TH element'); diff --git a/lib/core/base/context.js b/lib/core/base/context.js index 21fb603d4a..ac8f3899a3 100644 --- a/lib/core/base/context.js +++ b/lib/core/base/context.js @@ -75,8 +75,11 @@ function pushUniqueFrameSelector(context, type, selectorArray) { */ function normalizeContext(context) { // typeof NodeList.length in PhantomJS === function - if ((context && typeof context === 'object') || context instanceof NodeList) { - if (context instanceof Node) { + if ( + (context && typeof context === 'object') || + context instanceof window.NodeList + ) { + if (context instanceof window.Node) { return { include: [context], exclude: [] @@ -140,7 +143,7 @@ function parseSelectorArray(context, type) { }) ); break; - } else if (item && item.length && !(item instanceof Node)) { + } else if (item && item.length && !(item instanceof window.Node)) { if (item.length > 1) { pushUniqueFrameSelector(context, type, item); } else { @@ -152,8 +155,8 @@ function parseSelectorArray(context, type) { }) ); } - } else if (item instanceof Node) { - if (item.documentElement instanceof Node) { + } else if (item instanceof window.Node) { + if (item.documentElement instanceof window.Node) { result.push(context.flatTree[0]); } else { result.push(getNodeFromTree(item)); @@ -198,11 +201,11 @@ function getRootNode({ include, exclude }) { for (var i = 0; i < selectors.length; ++i) { var item = selectors[i]; - if (item instanceof Element) { + if (item instanceof window.Element) { return item.ownerDocument.documentElement; } - if (item instanceof Document) { + if (item instanceof window.Document) { return item.documentElement; } } diff --git a/lib/core/public/run.js b/lib/core/public/run.js index 5ea64fceb2..3560aa5cfa 100644 --- a/lib/core/public/run.js +++ b/lib/core/public/run.js @@ -5,8 +5,8 @@ function isContext(potential) { switch (true) { case typeof potential === 'string': case Array.isArray(potential): - case Node && potential instanceof Node: - case NodeList && potential instanceof NodeList: + case window.Node && potential instanceof window.Node: + case window.NodeList && potential instanceof window.NodeList: return true; case typeof potential !== 'object': @@ -87,6 +87,29 @@ function run(context, options, callback) { throw new Error('No audit configured'); } + // if window or document are not defined and context was passed in + // we can use it to configure them + // NOTE: because our polyfills run first, the global window object + // always exists but may not have things we expect + const hasWindow = window && 'Node' in window && 'NodeList' in window; + const hasDoc = !!document; + if (!hasWindow || !hasDoc) { + if (!context || !context.ownerDocument) { + throw new Error( + 'Required "window" or "document" globals not defined and cannot be deduced from the context. ' + + 'Either set the globals before running or pass in a valid Element.' + ); + } + + if (!hasDoc) { + document = context.ownerDocument; + } + + if (!hasWindow) { + window = document.defaultView; + } + } + let args = normalizeRunParams(context, options, callback); context = args.context; options = args.options; diff --git a/lib/core/utils/check-helper.js b/lib/core/utils/check-helper.js index 5353ea0b17..88e283d05c 100644 --- a/lib/core/utils/check-helper.js +++ b/lib/core/utils/check-helper.js @@ -25,7 +25,7 @@ function checkHelper(checkResult, options, resolve, reject) { checkResult.data = data; }, relatedNodes: function(nodes) { - nodes = nodes instanceof Node ? [nodes] : toArray(nodes); + nodes = nodes instanceof window.Node ? [nodes] : toArray(nodes); checkResult.relatedNodes = nodes.map(function(element) { return new DqElement(element, options); });