axe-core
Version:
Accessibility engine for automated Web UI testing
116 lines (99 loc) • 3.24 kB
JavaScript
function err(message, node) {
'use strict';
var selector;
if (axe._tree) {
selector = axe.utils.getSelector(node);
}
return new Error(message + ': ' + (selector || node));
}
/**
* Sends a command to an instance of axe in the specified frame
* @param {Element} node The frame element to send the message to
* @param {Object} parameters Parameters to pass to the frame
* @param {Function} callback Function to call when results from the frame has returned
*/
axe.utils.sendCommandToFrame = function(node, parameters, resolve, reject) {
'use strict';
var win = node.contentWindow;
if (!win) {
axe.log('Frame does not have a content window', node);
resolve(null);
return;
}
// give the frame .5s to respond to 'axe.ping', else log failed response
var timeout = setTimeout(function() {
// This double timeout is important for allowing iframes to respond
// DO NOT REMOVE
timeout = setTimeout(function() {
if (!parameters.debug) {
resolve(null);
} else {
reject(err('No response from frame', node));
}
}, 0);
}, 500);
// send 'axe.ping' to the frame
axe.utils.respondable(win, 'axe.ping', null, undefined, function() {
clearTimeout(timeout);
// Give aXe 60s (or user-supplied value) to respond to 'axe.start'
var frameWaitTime = (parameters.options && parameters.options.frameWaitTime) || 60000;
timeout = setTimeout(function() {
reject(err('Axe in frame timed out', node));
}, frameWaitTime);
// send 'axe.start' and send the callback if it responded
axe.utils.respondable(win, 'axe.start', parameters, undefined, function(data) {
clearTimeout(timeout);
if (data instanceof Error === false) {
resolve(data);
} else {
reject(data);
}
});
});
};
/**
* Sends a message to axe running in frames to start analysis and collate results (via `mergeResults`)
* @private
* @param {Context} context The resolved Context object
* @param {Object} options Options object (as passed to `runRules`)
* @param {string} command Command sent to all frames
* @param {Array} parameter Array of values to be passed along side the command
* @param {Function} callback Function to call when results from all frames have returned
*/
function collectResultsFromFrames(context, options, command, parameter, resolve, reject) {
'use strict';
var q = axe.utils.queue();
var frames = context.frames;
// Tell each axe running in each frame to collect results
frames.forEach(function (frame) {
var params = {
options: options,
command: command,
parameter: parameter,
context: {
initiator: false,
page: context.page,
include: frame.include || [],
exclude: frame.exclude || []
}
};
q.defer(function(res, rej) {
var node = frame.node;
axe.utils.sendCommandToFrame(node, params, function(data) {
if (data) {
return res({
results: data,
frameElement: node,
frame: axe.utils.getSelector(node)
});
}
res(null);
}, rej);
});
});
// Combine results from all frames and give it back
q.then(function(data) {
resolve(axe.utils.mergeResults(data, options));
}).catch(reject);
}
axe.utils.collectResultsFromFrames = collectResultsFromFrames;