nl.hsac.fitnesse.fixture.util.selenium.NgClientSideScripts Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hsac-fitnesse-fixtures Show documentation
Show all versions of hsac-fitnesse-fixtures Show documentation
Fixtures to assist in testing via FitNesse
package nl.hsac.fitnesse.fixture.util.selenium;
/**
* Javascript scripts to perform against AngularJs sites when using Selenium
* (copied from @link https://github.com/bbaia/protractor-net/blob/master/src/Protractor/ClientSideScripts.cs
* and updated using @link https://github.com/angular/protractor/blob/master/lib/clientsidescripts.js).
*/
public class NgClientSideScripts {
/**
* Waits (asynchronously) until Angular has finished rendering and has
* no outstanding $http calls before continuing.
*
* arguments[0] {string} The selector housing an ng-app
* arguments[1] {function} callback
*/
public final static String WaitForAngular =
"var rootSelector = arguments[0];\n" +
"var el = document.querySelector(rootSelector);\n" +
"\n" +
" try {\n" +
" if (!window.angular) {\n" +
" throw new Error('angular could not be found on the window');\n" +
" }\n" +
" if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(callback);\n" +
" } else {\n" +
" if (!angular.element(el).injector()) {\n" +
" throw new Error('root element (' + rootSelector + ') has no injector.' +\n" +
" ' this may mean it is not inside ng-app.');\n" +
" }\n" +
" angular.element(el).injector().get('$browser').\n" +
" notifyWhenNoOutstandingRequests(callback);\n" +
" }\n" +
" } catch (err) {\n" +
" callback(err.message);\n" +
" }";
/**
* Tests whether the angular global variable is present on a page. Retries
* in case the page is just loading slowly.
*
* Asynchronous.
*
* @param {number} attempts Number of times to retry.
* @param {function} asyncCallback callback
*/
public final static String TestForAngular =
"var asyncCallback = arguments[1];\n" +
"var attempts = arguments[0];\n" +
" var callback = function(args) {\n" +
" setTimeout(function() {\n" +
" asyncCallback(args);\n" +
" }, 0);\n" +
" };\n" +
" var check = function(n) {\n" +
" try {\n" +
" if (window.angular && window.angular.resumeBootstrap) {\n" +
" callback([true, null]);\n" +
" } else if (n < 1) {\n" +
" if (window.angular) {\n" +
" callback([false, 'angular never provided resumeBootstrap']);\n" +
" } else {\n" +
" callback([false, 'retries looking for angular exceeded']);\n" +
" }\n" +
" } else {\n" +
" window.setTimeout(function() {check(n - 1);}, 1000);\n" +
" }\n" +
" } catch (e) {\n" +
" callback([false, e]);\n" +
" }\n" +
" };\n" +
" check(attempts);";
/**
* Continue to bootstrap Angular.
*
* arguments[0] {array} The module names to load.
*/
public final static String ResumeAngularBootstrap =
"angular.resumeBootstrap(arguments[0].length ? arguments[0].split(',') : []);";
/**
* Return the current url using $location.absUrl().
*
* arguments[0] {string} The selector housing an ng-app
*/
public final static String GetLocationAbsUrl =
"var selector = arguments[0];\n" +
" var el = document.querySelector(selector);\n" +
" if (angular.getTestability) {\n" +
" return angular.getTestability(el).\n" +
" getLocation();\n" +
" }\n" +
" return angular.element(el).injector().get('$location').absUrl();\n";
/**
* Evaluate an Angular expression in the context of a given element.
*
* arguments[0] {Element} The element in whose scope to evaluate.
* arguments[1] {string} The expression to evaluate.
*
* @return {?Object} The result of the evaluation.
*/
public final static String Evaluate =
"var element = arguments[1];\n" +
"var expression = arguments[0];\n" +
"return angular.element(element).scope().$eval(expression);";
/**
* Find a list of elements in the page by their angular binding.
*
* @param {string} binding The binding, e.g. {{cat.name}}.
* @param {boolean} exactMatch Whether the binding needs to be matched exactly
* @param {Element} using The scope of the search.
* @param {string} rootSelector The selector to use for the root app element.
*
* @return {Array.} The elements containing the binding.
*/
public final static String FindBindings =
"var rootSelector = arguments[3];\n" +
"var using = arguments[2];\n" +
"var exactMatch = arguments[1];\n" +
"var binding = arguments[0];\n" +
" var root = document.querySelector(rootSelector || 'body');\n" +
" using = using || document;\n" +
" if (angular.getTestability) {\n" +
" return angular.getTestability(root).\n" +
" findBindings(using, binding, exactMatch);\n" +
" }\n" +
" var bindings = using.getElementsByClassName('ng-binding');\n" +
" var matches = [];\n" +
" for (var i = 0; i < bindings.length; ++i) {\n" +
" var dataBinding = angular.element(bindings[i]).data('$binding');\n" +
" if (dataBinding) {\n" +
" var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;\n" +
" if (exactMatch) {\n" +
" var matcher = new RegExp('({|\\\\s|^|\\\\|)' + binding + '(}|\\\\s|$|\\\\|)');\n" +
" if (matcher.test(bindingName)) {\n" +
" matches.push(bindings[i]);\n" +
" }\n" +
" } else {\n" +
" if (bindingName.indexOf(binding) != -1) {\n" +
" matches.push(bindings[i]);\n" +
" }\n" +
" }\n" +
"\n" +
" }\n" +
" }\n" +
" return matches; /* Return the whole array for webdriver.findElements. */\n";
/**
* Find select elements by model name.
*
* arguments[0] {Element} The scope of the search.
* arguments[1] {string} The model name.
*
* @return {Array.WebElement} The matching select elements.
*/
public final static String FindSelects =
"var using = arguments[1] || document;\n" +
"var model = arguments[0];\n" +
"var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];\n" +
"for (var p = 0; p < prefixes.length; ++p) {\n" +
" var selector = 'select[' + prefixes[p] + 'model=\"' + model + '\"]';\n" +
" var inputs = using.querySelectorAll(selector);\n" +
" if (inputs.length) {\n" +
" return inputs;\n" +
" }\n" +
"}";
/**
* Find elements by model name.
*
* @param {string} model The model name.
* @param {Element} using The scope of the search.
* @param {string} rootSelector The selector to use for the root app element.
*
* @return {Array.} The matching elements.
*/
public final static String FindElements =
"var using = arguments[1] || document;\n" +
"var model = arguments[0];\n" +
"var rootSelector = arguments[2];\n" +
"var root = document.querySelector(rootSelector || 'body');\n" +
" using = using || document;\n" +
"\n" +
" if (angular.getTestability) {\n" +
" return angular.getTestability(root).\n" +
" findModels(using, model, true);\n" +
" }\n" +
" var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];\n" +
" for (var p = 0; p < prefixes.length; ++p) {\n" +
" var selector = '[' + prefixes[p] + 'model=\"' + model + '\"]';\n" +
" var elements = using.querySelectorAll(selector);\n" +
" if (elements.length) {\n" +
" return elements;\n" +
" }\n" +
" }";
/**
* Find all rows of an ng-repeat.
*
* @param {string} repeater The text of the repeater, e.g. 'cat in cats'.
* @param {boolean} exact Whether the repeater needs to be matched exactly
* @param {Element} using The scope of the search.
*
* @return {Array.} All rows of the repeater.
*/
public final static String FindAllRepeaterRows =
"var using = arguments[2] || document;\n" +
"var exact = arguments[1];\n" +
"var repeater = arguments[0];\n" +
" function repeaterMatch(ngRepeat, repeater, exact) {\n" +
" if (exact) {\n" +
" return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].\n" +
" trim() == repeater;\n" +
" } else {\n" +
" return ngRepeat.indexOf(repeater) != -1;\n" +
" }\n" +
" }\n" +
"\n" +
" using = using || document;\n" +
"\n" +
" var rows = [];\n" +
" var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];\n" +
" for (var p = 0; p < prefixes.length; ++p) {\n" +
" var attr = prefixes[p] + 'repeat';\n" +
" var repeatElems = using.querySelectorAll('[' + attr + ']');\n" +
" attr = attr.replace(/\\\\/g, '');\n" +
" for (var i = 0; i < repeatElems.length; ++i) {\n" +
" if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {\n" +
" rows.push(repeatElems[i]);\n" +
" }\n" +
" }\n" +
" }\n" +
" for (var p = 0; p < prefixes.length; ++p) {\n" +
" var attr = prefixes[p] + 'repeat-start';\n" +
" var repeatElems = using.querySelectorAll('[' + attr + ']');\n" +
" attr = attr.replace(/\\\\/g, '');\n" +
" for (var i = 0; i < repeatElems.length; ++i) {\n" +
" if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {\n" +
" var elem = repeatElems[i];\n" +
" while (elem.nodeType != 8 ||\n" +
" !repeaterMatch(elem.nodeValue, repeater, exact)) {\n" +
" if (elem.nodeType == 1) {\n" +
" rows.push(elem);\n" +
" }\n" +
" elem = elem.nextSibling;\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" return rows;";
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy