UNPKG

@testim/testim-cli

Version:

Command line interface for running Testing on you CI

143 lines (126 loc) 4.97 kB
/** * Returns the script to execute in the browser, in string format. * @param {Function|String} fn - function to execute in the browser * @param {Array.<String>} selectors - the selectors to resolve and pass to fn, each in its own array * @param {Array} args - the arguments to pass to fn (after resolved selectors) * @param {Function} callback * @returns {string} */ var findStrategy = require('./find-element-strategy'); module.exports = function(fn, selectors, args) { var strArgs = [], foundSel = [], val; if (typeof fn === 'function' || (this.inMultibrowserMode && fn.indexOf('function (') === 0)) { // Handle function script strArgs.push(fn.toString()); } else if (typeof fn === 'string') { // Handle string script strArgs.push('function(){' + fn + '}'); } for(var j = 0; j < selectors.length; ++j) { val = findStrategy(selectors[j]); foundSel.push(val.using, val.value); } strArgs.push(JSON.stringify(foundSel)); var i = -1; while (++i < args.length) { if (typeof args[i] === 'function' || (this.inMultibrowserMode && (typeof args[i] === 'string' && args[i].indexOf('function (') === 0))) { args[i] = args[i].toString(); } else { args[i] = JSON.stringify(args[i]); } } strArgs.push('[' + args.join(',') + ']'); return ('return (' + executeClientSide + ')(' + strArgs.join(',') + ', arguments[arguments.length - 1]);').replace(/(\s{4}|\t)+/g, ' '); }; /** * Helper that resolves selectors client side and returns the result in the given fn. * Every resolved selector is prepended to the function's arguments. * Each resolved selector yields a single array. * * @param {Function} fn - the function to execute client side that will receive the resolved selectors * @param {Array.<String>} sArr - a series of usage, value pairs from find-element-strategy * @param {Array} args - any other arguments to pass to fn * @returns {*} the return value of fn * @example * var helper = require('./executeClientSideSelector'); * // Execute in the browser * helper(fn, ['xpath', '//body', 'css', '[id="what"]'], [1, 2, 3]); * // Assuming fn is... * fn = function(xpathResult, cssResult, one, two, three) { * console.log(xpathResult.length); // 1 * console.log(xpathResult[0]); // <body.../> * console.log(cssResult.length); // 0 * console.log(one, two, three); // 1 2 3 * } */ var executeClientSide = function(fn, sArr, args) { var cb = arguments[arguments.length - 1], i = 0, sArgs = [], use, value, xp, cs, tn, res, j, arg; if (typeof document.querySelectorAll === 'undefined') { document.querySelectorAll = function(selector) { var doc = document, head = doc.documentElement.firstChild, styleTag = doc.createElement('STYLE'); head.appendChild(styleTag); doc.__qsaels = []; styleTag.styleSheet.cssText = selector + '{x:expression(document.__qsaels.push(this))}'; window.scrollBy(0, 0); return doc.__qsaels; }; } while ((use = sArr[i++]) && (value = sArr[i++])) { arg = []; xp = cs = tn = null; switch (use) { case 'partial link text': xp = '//a[contains(text(),"' + value + '")]'; break; case 'link text': xp = '//a[text()="' + value + '"]'; break; case 'xpath': xp = value; break; case 'id': cs = '#' + value; break; case 'name': cs = '[name="' + value + '"]'; break; case 'tag name': tn = value; break; case 'css selector': cs = value; break; default: throw new Error('Could not evaluate selector: Invalid strategy ' + use); } if (xp) { res = document.evaluate(xp, document, null, 0, null); value = res.iterateNext(); while (value) { arg.push(value); value = res.iterateNext(); } } else if (tn || cs) { res = tn ? document.getElementsByTagName(tn) : document.querySelectorAll(cs); for(j = 0; j < res.length; ++j) { arg.push(res[j]); } } sArgs.push(arg); } var parameter = args && sArgs.concat(args) || sArgs; if(parameter.length === 0 || (parameter.length === 1 && parameter[0].length === 0)) { if(typeof cb === 'function') { return cb('NoSuchElement') && new Error('NoSuchElement'); } return new Error('NoSuchElement'); } parameter.push(arguments[arguments.length - 1]); return fn.apply(window, parameter); };