Best JavaScript code snippet using protractor
clientsidescripts.js
Source:clientsidescripts.js
...65 * @param {boolean=} injectorPlease Prioritize finding an injector66 * @return {$$testability?: Testability, $injector?: Injector} Returns whatever67 * ng1 app hooks it finds68 */69function getNg1Hooks(selector, injectorPlease) {70 function tryEl(el) {71 try {72 if (!injectorPlease && angular.getTestability) {73 var $$testability = angular.getTestability(el);74 if ($$testability) {75 return {$$testability: $$testability};76 }77 } else {78 var $injector = angular.element(el).injector();79 if ($injector) {80 return {$injector: $injector};81 }82 }83 } catch(err) {}84 }85 function trySelector(selector) {86 var els = document.querySelectorAll(selector);87 for (var i = 0; i < els.length; i++) {88 var elHooks = tryEl(els[i]);89 if (elHooks) {90 return elHooks;91 }92 }93 }94 if (selector) {95 return trySelector(selector);96 } else if (window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__) {97 var $injector = window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__;98 var $$testability = null;99 try {100 $$testability = $injector.get('$$testability');101 } catch (e) {}102 return {$injector: $injector, $$testability: $$testability};103 } else {104 return tryEl(document.body) ||105 trySelector('[ng-app]') || trySelector('[ng\\:app]') ||106 trySelector('[ng-controller]') || trySelector('[ng\\:controller]');107 }108}109///////////////////////////////////////////////////////110//// ////111//// SCRIPTS ////112//// ////113///////////////////////////////////////////////////////114/**115 * Wait until Angular has finished rendering and has116 * no outstanding $http calls before continuing. The specific Angular app117 * is determined by the rootSelector.118 *119 * Asynchronous.120 *121 * @param {string} rootSelector The selector housing an ng-app122 * @param {function(string)} callback callback. If a failure occurs, it will123 * be passed as a parameter.124 */125functions.waitForAngular = function(rootSelector, callback) {126 try {127 // Wait for both angular1 testability and angular2 testability.128 var testCallback = callback;129 // Wait for angular1 testability first and run waitForAngular2 as a callback130 var waitForAngular1 = function(callback) {131 if (window.angular) {132 var hooks = getNg1Hooks(rootSelector);133 if (!hooks){134 callback(); // not an angular1 app135 }136 else{137 if (hooks.$$testability) {138 hooks.$$testability.whenStable(callback);139 } else if (hooks.$injector) {140 hooks.$injector.get('$browser')141 .notifyWhenNoOutstandingRequests(callback);142 } else if (!rootSelector) {143 throw new Error(144 'Could not automatically find injector on page: "' +145 window.location.toString() + '". Consider using config.rootEl');146 } else {147 throw new Error(148 'root element (' + rootSelector + ') has no injector.' +149 ' this may mean it is not inside ng-app.');150 }151 }152 }153 else {callback();} // not an angular1 app154 };155 // Wait for Angular2 testability and then run test callback156 var waitForAngular2 = function() {157 if (window.getAngularTestability) {158 if (rootSelector) {159 var testability = null;160 var el = document.querySelector(rootSelector);161 try{162 testability = window.getAngularTestability(el);163 }164 catch(e){}165 if (testability) {166 testability.whenStable(testCallback);167 return;168 }169 }170 // Didn't specify root element or testability could not be found171 // by rootSelector. This may happen in a hybrid app, which could have172 // more than one root.173 var testabilities = window.getAllAngularTestabilities();174 var count = testabilities.length;175 // No angular2 testability, this happens when176 // going to a hybrid page and going back to a pure angular1 page177 if (count === 0) {178 testCallback();179 return;180 }181 var decrement = function() {182 count--;183 if (count === 0) {184 testCallback();185 }186 };187 testabilities.forEach(function(testability) {188 testability.whenStable(decrement);189 });190 }191 else {testCallback();} // not an angular2 app192 };193 if (!(window.angular) && !(window.getAngularTestability)) {194 // no testability hook195 throw new Error(196 'both angularJS testability and angular testability are undefined.' +197 ' This could be either ' +198 'because this is a non-angular page or because your test involves ' +199 'client-side navigation, which can interfere with Protractor\'s ' +200 'bootstrapping. See http://git.io/v4gXM for details');201 } else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2202 // Testability hooks sequentially203 } catch (err) {204 callback(err.message);205 }206};207/**208 * Find a list of elements in the page by their angular binding.209 *210 * @param {string} binding The binding, e.g. {{cat.name}}.211 * @param {boolean} exactMatch Whether the binding needs to be matched exactly212 * @param {Element} using The scope of the search.213 * @param {string} rootSelector The selector to use for the root app element.214 *215 * @return {Array.<Element>} The elements containing the binding.216 */217functions.findBindings = function(binding, exactMatch, using, rootSelector) {218 using = using || document;219 if (angular.getTestability) {220 return getNg1Hooks(rootSelector).$$testability.221 findBindings(using, binding, exactMatch);222 }223 var bindings = using.getElementsByClassName('ng-binding');224 var matches = [];225 for (var i = 0; i < bindings.length; ++i) {226 var dataBinding = angular.element(bindings[i]).data('$binding');227 if (dataBinding) {228 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;229 if (exactMatch) {230 var matcher = new RegExp('({|\\s|^|\\|)' +231 /* See http://stackoverflow.com/q/3561711 */232 binding.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') +233 '(}|\\s|$|\\|)');234 if (matcher.test(bindingName)) {235 matches.push(bindings[i]);236 }237 } else {238 if (bindingName.indexOf(binding) != -1) {239 matches.push(bindings[i]);240 }241 }242 }243 }244 return matches; /* Return the whole array for webdriver.findElements. */245};246/**247 * Find an array of elements matching a row within an ng-repeat.248 * Always returns an array of only one element for plain old ng-repeat.249 * Returns an array of all the elements in one segment for ng-repeat-start.250 *251 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.252 * @param {boolean} exact Whether the repeater needs to be matched exactly253 * @param {number} index The row index.254 * @param {Element} using The scope of the search.255 *256 * @return {Array.<Element>} The row of the repeater, or an array of elements257 * in the first row in the case of ng-repeat-start.258 */259function findRepeaterRows(repeater, exact, index, using) {260 using = using || document;261 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];262 var rows = [];263 for (var p = 0; p < prefixes.length; ++p) {264 var attr = prefixes[p] + 'repeat';265 var repeatElems = using.querySelectorAll('[' + attr + ']');266 attr = attr.replace(/\\/g, '');267 for (var i = 0; i < repeatElems.length; ++i) {268 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {269 rows.push(repeatElems[i]);270 }271 }272 }273 /* multiRows is an array of arrays, where each inner array contains274 one row of elements. */275 var multiRows = [];276 for (var p = 0; p < prefixes.length; ++p) {277 var attr = prefixes[p] + 'repeat-start';278 var repeatElems = using.querySelectorAll('[' + attr + ']');279 attr = attr.replace(/\\/g, '');280 for (var i = 0; i < repeatElems.length; ++i) {281 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {282 var elem = repeatElems[i];283 var row = [];284 while (elem.nodeType != 8 ||285 !repeaterMatch(elem.nodeValue, repeater)) {286 if (elem.nodeType == 1) {287 row.push(elem);288 }289 elem = elem.nextSibling;290 }291 multiRows.push(row);292 }293 }294 }295 var row = rows[index] || [], multiRow = multiRows[index] || [];296 return [].concat(row, multiRow);297}298functions.findRepeaterRows = wrapWithHelpers(findRepeaterRows, repeaterMatch);299 /**300 * Find all rows of an ng-repeat.301 *302 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.303 * @param {boolean} exact Whether the repeater needs to be matched exactly304 * @param {Element} using The scope of the search.305 *306 * @return {Array.<Element>} All rows of the repeater.307 */308function findAllRepeaterRows(repeater, exact, using) {309 using = using || document;310 var rows = [];311 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];312 for (var p = 0; p < prefixes.length; ++p) {313 var attr = prefixes[p] + 'repeat';314 var repeatElems = using.querySelectorAll('[' + attr + ']');315 attr = attr.replace(/\\/g, '');316 for (var i = 0; i < repeatElems.length; ++i) {317 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {318 rows.push(repeatElems[i]);319 }320 }321 }322 for (var p = 0; p < prefixes.length; ++p) {323 var attr = prefixes[p] + 'repeat-start';324 var repeatElems = using.querySelectorAll('[' + attr + ']');325 attr = attr.replace(/\\/g, '');326 for (var i = 0; i < repeatElems.length; ++i) {327 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {328 var elem = repeatElems[i];329 while (elem.nodeType != 8 ||330 !repeaterMatch(elem.nodeValue, repeater)) {331 if (elem.nodeType == 1) {332 rows.push(elem);333 }334 elem = elem.nextSibling;335 }336 }337 }338 }339 return rows;340}341functions.findAllRepeaterRows = wrapWithHelpers(findAllRepeaterRows, repeaterMatch);342/**343 * Find an element within an ng-repeat by its row and column.344 *345 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.346 * @param {boolean} exact Whether the repeater needs to be matched exactly347 * @param {number} index The row index.348 * @param {string} binding The column binding, e.g. '{{cat.name}}'.349 * @param {Element} using The scope of the search.350 * @param {string} rootSelector The selector to use for the root app element.351 *352 * @return {Array.<Element>} The element in an array.353 */354function findRepeaterElement(repeater, exact, index, binding, using, rootSelector) {355 var matches = [];356 using = using || document;357 var rows = [];358 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];359 for (var p = 0; p < prefixes.length; ++p) {360 var attr = prefixes[p] + 'repeat';361 var repeatElems = using.querySelectorAll('[' + attr + ']');362 attr = attr.replace(/\\/g, '');363 for (var i = 0; i < repeatElems.length; ++i) {364 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {365 rows.push(repeatElems[i]);366 }367 }368 }369 /* multiRows is an array of arrays, where each inner array contains370 one row of elements. */371 var multiRows = [];372 for (var p = 0; p < prefixes.length; ++p) {373 var attr = prefixes[p] + 'repeat-start';374 var repeatElems = using.querySelectorAll('[' + attr + ']');375 attr = attr.replace(/\\/g, '');376 for (var i = 0; i < repeatElems.length; ++i) {377 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {378 var elem = repeatElems[i];379 var row = [];380 while (elem.nodeType != 8 || (elem.nodeValue &&381 !repeaterMatch(elem.nodeValue, repeater))) {382 if (elem.nodeType == 1) {383 row.push(elem);384 }385 elem = elem.nextSibling;386 }387 multiRows.push(row);388 }389 }390 }391 var row = rows[index];392 var multiRow = multiRows[index];393 var bindings = [];394 if (row) {395 if (angular.getTestability) {396 matches.push.apply(397 matches,398 getNg1Hooks(rootSelector).$$testability.findBindings(row, binding));399 } else {400 if (row.className.indexOf('ng-binding') != -1) {401 bindings.push(row);402 }403 var childBindings = row.getElementsByClassName('ng-binding');404 for (var i = 0; i < childBindings.length; ++i) {405 bindings.push(childBindings[i]);406 }407 }408 }409 if (multiRow) {410 for (var i = 0; i < multiRow.length; ++i) {411 var rowElem = multiRow[i];412 if (angular.getTestability) {413 matches.push.apply(414 matches,415 getNg1Hooks(rootSelector).$$testability.findBindings(rowElem,416 binding));417 } else {418 if (rowElem.className.indexOf('ng-binding') != -1) {419 bindings.push(rowElem);420 }421 var childBindings = rowElem.getElementsByClassName('ng-binding');422 for (var j = 0; j < childBindings.length; ++j) {423 bindings.push(childBindings[j]);424 }425 }426 }427 }428 for (var i = 0; i < bindings.length; ++i) {429 var dataBinding = angular.element(bindings[i]).data('$binding');430 if (dataBinding) {431 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;432 if (bindingName.indexOf(binding) != -1) {433 matches.push(bindings[i]);434 }435 }436 }437 return matches;438}439functions.findRepeaterElement =440 wrapWithHelpers(findRepeaterElement, repeaterMatch, getNg1Hooks);441/**442 * Find the elements in a column of an ng-repeat.443 *444 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.445 * @param {boolean} exact Whether the repeater needs to be matched exactly446 * @param {string} binding The column binding, e.g. '{{cat.name}}'.447 * @param {Element} using The scope of the search.448 * @param {string} rootSelector The selector to use for the root app element.449 *450 * @return {Array.<Element>} The elements in the column.451 */452function findRepeaterColumn(repeater, exact, binding, using, rootSelector) {453 var matches = [];454 using = using || document;455 var rows = [];456 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];457 for (var p = 0; p < prefixes.length; ++p) {458 var attr = prefixes[p] + 'repeat';459 var repeatElems = using.querySelectorAll('[' + attr + ']');460 attr = attr.replace(/\\/g, '');461 for (var i = 0; i < repeatElems.length; ++i) {462 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {463 rows.push(repeatElems[i]);464 }465 }466 }467 /* multiRows is an array of arrays, where each inner array contains468 one row of elements. */469 var multiRows = [];470 for (var p = 0; p < prefixes.length; ++p) {471 var attr = prefixes[p] + 'repeat-start';472 var repeatElems = using.querySelectorAll('[' + attr + ']');473 attr = attr.replace(/\\/g, '');474 for (var i = 0; i < repeatElems.length; ++i) {475 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {476 var elem = repeatElems[i];477 var row = [];478 while (elem.nodeType != 8 || (elem.nodeValue &&479 !repeaterMatch(elem.nodeValue, repeater))) {480 if (elem.nodeType == 1) {481 row.push(elem);482 }483 elem = elem.nextSibling;484 }485 multiRows.push(row);486 }487 }488 }489 var bindings = [];490 for (var i = 0; i < rows.length; ++i) {491 if (angular.getTestability) {492 matches.push.apply(493 matches,494 getNg1Hooks(rootSelector).$$testability.findBindings(rows[i],495 binding));496 } else {497 if (rows[i].className.indexOf('ng-binding') != -1) {498 bindings.push(rows[i]);499 }500 var childBindings = rows[i].getElementsByClassName('ng-binding');501 for (var k = 0; k < childBindings.length; ++k) {502 bindings.push(childBindings[k]);503 }504 }505 }506 for (var i = 0; i < multiRows.length; ++i) {507 for (var j = 0; j < multiRows[i].length; ++j) {508 if (angular.getTestability) {509 matches.push.apply(510 matches,511 getNg1Hooks(rootSelector).$$testability.findBindings(512 multiRows[i][j], binding));513 } else {514 var elem = multiRows[i][j];515 if (elem.className.indexOf('ng-binding') != -1) {516 bindings.push(elem);517 }518 var childBindings = elem.getElementsByClassName('ng-binding');519 for (var k = 0; k < childBindings.length; ++k) {520 bindings.push(childBindings[k]);521 }522 }523 }524 }525 for (var j = 0; j < bindings.length; ++j) {526 var dataBinding = angular.element(bindings[j]).data('$binding');527 if (dataBinding) {528 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;529 if (bindingName.indexOf(binding) != -1) {530 matches.push(bindings[j]);531 }532 }533 }534 return matches;535}536functions.findRepeaterColumn =537 wrapWithHelpers(findRepeaterColumn, repeaterMatch, getNg1Hooks);538/**539 * Find elements by model name.540 *541 * @param {string} model The model name.542 * @param {Element} using The scope of the search.543 * @param {string} rootSelector The selector to use for the root app element.544 *545 * @return {Array.<Element>} The matching elements.546 */547functions.findByModel = function(model, using, rootSelector) {548 using = using || document;549 if (angular.getTestability) {550 return getNg1Hooks(rootSelector).$$testability.551 findModels(using, model, true);552 }553 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];554 for (var p = 0; p < prefixes.length; ++p) {555 var selector = '[' + prefixes[p] + 'model="' + model + '"]';556 var elements = using.querySelectorAll(selector);557 if (elements.length) {558 return elements;559 }560 }561};562/**563 * Find elements by options.564 *565 * @param {string} optionsDescriptor The descriptor for the option566 * (i.e. fruit for fruit in fruits).567 * @param {Element} using The scope of the search.568 *569 * @return {Array.<Element>} The matching elements.570 */571functions.findByOptions = function(optionsDescriptor, using) {572 using = using || document;573 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];574 for (var p = 0; p < prefixes.length; ++p) {575 var selector = '[' + prefixes[p] + 'options="' + optionsDescriptor + '"] option';576 var elements = using.querySelectorAll(selector);577 if (elements.length) {578 return elements;579 }580 }581};582/**583 * Find buttons by textual content.584 *585 * @param {string} searchText The exact text to match.586 * @param {Element} using The scope of the search.587 *588 * @return {Array.<Element>} The matching elements.589 */590functions.findByButtonText = function(searchText, using) {591 using = using || document;592 var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');593 var matches = [];594 for (var i = 0; i < elements.length; ++i) {595 var element = elements[i];596 var elementText;597 if (element.tagName.toLowerCase() == 'button') {598 elementText = element.textContent || element.innerText || '';599 } else {600 elementText = element.value;601 }602 if (elementText.trim() === searchText) {603 matches.push(element);604 }605 }606 return matches;607};608/**609 * Find buttons by textual content.610 *611 * @param {string} searchText The exact text to match.612 * @param {Element} using The scope of the search.613 *614 * @return {Array.<Element>} The matching elements.615 */616functions.findByPartialButtonText = function(searchText, using) {617 using = using || document;618 var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');619 var matches = [];620 for (var i = 0; i < elements.length; ++i) {621 var element = elements[i];622 var elementText;623 if (element.tagName.toLowerCase() == 'button') {624 elementText = element.textContent || element.innerText || '';625 } else {626 elementText = element.value;627 }628 if (elementText.indexOf(searchText) > -1) {629 matches.push(element);630 }631 }632 return matches;633};634/**635 * Find elements by css selector and textual content.636 *637 * @param {string} cssSelector The css selector to match.638 * @param {string} searchText The exact text to match or a serialized regex.639 * @param {Element} using The scope of the search.640 *641 * @return {Array.<Element>} An array of matching elements.642 */643functions.findByCssContainingText = function(cssSelector, searchText, using) {644 using = using || document;645 if (searchText.indexOf('__REGEXP__') === 0) {646 var match = searchText.split('__REGEXP__')[1].match(/\/(.*)\/(.*)?/);647 searchText = new RegExp(match[1], match[2] || '');648 }649 var elements = using.querySelectorAll(cssSelector);650 var matches = [];651 for (var i = 0; i < elements.length; ++i) {652 var element = elements[i];653 var elementText = element.textContent || element.innerText || '';654 var elementMatches = searchText instanceof RegExp ?655 searchText.test(elementText) :656 elementText.indexOf(searchText) > -1;657 if (elementMatches) {658 matches.push(element);659 }660 }661 return matches;662};663/**664 * Tests whether the angular global variable is present on a page. Retries665 * in case the page is just loading slowly.666 *667 * Asynchronous.668 *669 * @param {number} attempts Number of times to retry.670 * @param {boolean} ng12Hybrid Flag set if app is a hybrid of angular 1 and 2671 * @param {function({version: ?number, message: ?string})} asyncCallback callback672 *673 */674functions.testForAngular = function(attempts, ng12Hybrid, asyncCallback) {675 var callback = function(args) {676 setTimeout(function() {677 asyncCallback(args);678 }, 0);679 };680 var definitelyNg1 = !!ng12Hybrid;681 var definitelyNg2OrNewer = false;682 var check = function(n) {683 try {684 /* Figure out which version of angular we're waiting on */685 if (!definitelyNg1 && !definitelyNg2OrNewer) {686 if (window.angular && !(window.angular.version && window.angular.version.major > 1)) {687 definitelyNg1 = true;688 } else if (window.getAllAngularTestabilities) {689 definitelyNg2OrNewer = true;690 }691 }692 /* See if our version of angular is ready */693 if (definitelyNg1) {694 if (window.angular && window.angular.resumeBootstrap) {695 return callback({ver: 1});696 }697 } else if (definitelyNg2OrNewer) {698 if (true /* ng2 has no resumeBootstrap() */) {699 return callback({ver: 2});700 }701 }702 /* Try again (or fail) */703 if (n < 1) {704 if (definitelyNg1 && window.angular) {705 callback({message: 'angular never provided resumeBootstrap'});706 } else if (ng12Hybrid && !window.angular) {707 callback({message: 'angular 1 never loaded' +708 window.getAllAngularTestabilities ? ' (are you sure this app ' +709 'uses ngUpgrade? Try un-setting ng12Hybrid)' : ''});710 } else {711 callback({message: 'retries looking for angular exceeded'});712 }713 } else {714 window.setTimeout(function() {check(n - 1);}, 1000);715 }716 } catch (e) {717 callback({message: e});718 }719 };720 check(attempts);721};722/**723 * Evalute an Angular expression in the context of a given element.724 *725 * @param {Element} element The element in whose scope to evaluate.726 * @param {string} expression The expression to evaluate.727 *728 * @return {?Object} The result of the evaluation.729 */730functions.evaluate = function(element, expression) {731 return angular.element(element).scope().$eval(expression);732};733functions.allowAnimations = function(element, value) {734 var ngElement = angular.element(element);735 if (ngElement.allowAnimations) {736 // AngularDart: $testability API.737 return ngElement.allowAnimations(value);738 } else {739 // AngularJS740 var enabledFn = ngElement.injector().get('$animate').enabled;741 return (value == null) ? enabledFn() : enabledFn(value);742 }743};744/**745 * Return the current url using $location.absUrl().746 *747 * @param {string} selector The selector housing an ng-app748 */749functions.getLocationAbsUrl = function(selector) {750 var hooks = getNg1Hooks(selector);751 if (angular.getTestability) {752 return hooks.$$testability.getLocation();753 }754 return hooks.$injector.get('$location').absUrl();755};756/**757 * Browse to another page using in-page navigation.758 *759 * @param {string} selector The selector housing an ng-app760 * @param {string} url In page URL using the same syntax as $location.url(),761 * /path?search=a&b=c#hash762 */763functions.setLocation = function(selector, url) {764 var hooks = getNg1Hooks(selector);765 if (angular.getTestability) {766 return hooks.$$testability.setLocation(url);767 }768 var $injector = hooks.$injector;769 var $location = $injector.get('$location');770 var $rootScope = $injector.get('$rootScope');771 if (url !== $location.url()) {772 $location.url(url);773 $rootScope.$digest();774 }775};776/**777 * Retrieve the pending $http requests.778 *779 * @param {string} selector The selector housing an ng-app780 * @return {!Array<!Object>} An array of pending http requests.781 */782functions.getPendingHttpRequests = function(selector) {783 var hooks = getNg1Hooks(selector, true);784 var $http = hooks.$injector.get('$http');785 return $http.pendingRequests;786};787['waitForAngular', 'findBindings', 'findByModel', 'getLocationAbsUrl',788 'setLocation', 'getPendingHttpRequests'].forEach(function(funName) {789 functions[funName] = wrapWithHelpers(functions[funName], getNg1Hooks);790});791/* Publish all the functions as strings to pass to WebDriver's792 * exec[Async]Script. In addition, also include a script that will793 * install all the functions on window (for debugging.)794 *795 * We also wrap any exceptions thrown by a clientSideScripts function796 * that is not an instance of the Error type into an Error type. If we797 * don't do so, then the resulting stack trace is completely unhelpful...
clientsidescripts (1).js
Source:clientsidescripts (1).js
...65 * @param {boolean=} injectorPlease Prioritize finding an injector66 * @return {$$testability?: Testability, $injector?: Injector} Returns whatever67 * ng1 app hooks it finds68 */69function getNg1Hooks(selector, injectorPlease) {70 function tryEl(el) {71 try {72 if (!injectorPlease && angular.getTestability) {73 var $$testability = angular.getTestability(el);74 if ($$testability) {75 return {$$testability: $$testability};76 }77 } else {78 var $injector = angular.element(el).injector();79 if ($injector) {80 return {$injector: $injector};81 }82 }83 } catch(err) {}84 }85 function trySelector(selector) {86 var els = document.querySelectorAll(selector);87 for (var i = 0; i < els.length; i++) {88 var elHooks = tryEl(els[i]);89 if (elHooks) {90 return elHooks;91 }92 }93 }94 if (selector) {95 return trySelector(selector);96 } else if (window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__) {97 var $injector = window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__;98 var $$testability = null;99 try {100 $$testability = $injector.get('$$testability');101 } catch (e) {}102 return {$injector: $injector, $$testability: $$testability};103 } else {104 return tryEl(document.body) ||105 trySelector('[ng-app]') || trySelector('[ng\\:app]') ||106 trySelector('[ng-controller]') || trySelector('[ng\\:controller]');107 }108}109///////////////////////////////////////////////////////110//// ////111//// SCRIPTS ////112//// ////113///////////////////////////////////////////////////////114/**115 * Wait until Angular has finished rendering and has116 * no outstanding $http calls before continuing. The specific Angular app117 * is determined by the rootSelector.118 *119 * Asynchronous.120 *121 * @param {string} rootSelector The selector housing an ng-app122 * @param {function(string)} callback callback. If a failure occurs, it will123 * be passed as a parameter.124 */125functions.waitForAngular = function(rootSelector, callback) {126 try {127 // Wait for both angular1 testability and angular2 testability.128 var testCallback = callback;129 // Wait for angular1 testability first and run waitForAngular2 as a callback130 var waitForAngular1 = function(callback) {131 if (window.angular) {132 var hooks = getNg1Hooks(rootSelector);133 if (!hooks){134 callback(); // not an angular1 app135 }136 else{137 if (hooks.$$testability) {138 hooks.$$testability.whenStable(callback);139 } else if (hooks.$injector) {140 hooks.$injector.get('$browser')141 .notifyWhenNoOutstandingRequests(callback);142 } else if (!rootSelector) {143 throw new Error(144 'Could not automatically find injector on page: "' +145 window.location.toString() + '". Consider using config.rootEl');146 } else {147 throw new Error(148 'root element (' + rootSelector + ') has no injector.' +149 ' this may mean it is not inside ng-app.');150 }151 }152 }153 else {callback();} // not an angular1 app154 };155 // Wait for Angular2 testability and then run test callback156 var waitForAngular2 = function() {157 if (window.getAngularTestability) {158 if (rootSelector) {159 var testability = null;160 var el = document.querySelector(rootSelector);161 try{162 testability = window.getAngularTestability(el);163 }164 catch(e){}165 if (testability) {166 testability.whenStable(testCallback);167 return;168 }169 }170 // Didn't specify root element or testability could not be found171 // by rootSelector. This may happen in a hybrid app, which could have172 // more than one root.173 var testabilities = window.getAllAngularTestabilities();174 var count = testabilities.length;175 // No angular2 testability, this happens when176 // going to a hybrid page and going back to a pure angular1 page177 if (count === 0) {178 testCallback();179 return;180 }181 var decrement = function() {182 count--;183 if (count === 0) {184 testCallback();185 }186 };187 testabilities.forEach(function(testability) {188 testability.whenStable(decrement);189 });190 }191 else {testCallback();} // not an angular2 app192 };193 if (!(window.angular) && !(window.getAngularTestability)) {194 // no testability hook195 throw new Error(196 'both angularJS testability and angular testability are undefined.' +197 ' This could be either ' +198 'because this is a non-angular page or because your test involves ' +199 'client-side navigation, which can interfere with Protractor\'s ' +200 'bootstrapping. See http://git.io/v4gXM for details');201 } else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2202 // Testability hooks sequentially203 } catch (err) {204 callback(err.message);205 }206};207/**208 * Find a list of elements in the page by their angular binding.209 *210 * @param {string} binding The binding, e.g. {{cat.name}}.211 * @param {boolean} exactMatch Whether the binding needs to be matched exactly212 * @param {Element} using The scope of the search.213 * @param {string} rootSelector The selector to use for the root app element.214 *215 * @return {Array.<Element>} The elements containing the binding.216 */217functions.findBindings = function(binding, exactMatch, using, rootSelector) {218 using = using || document;219 if (angular.getTestability) {220 return getNg1Hooks(rootSelector).$$testability.221 findBindings(using, binding, exactMatch);222 }223 var bindings = using.getElementsByClassName('ng-binding');224 var matches = [];225 for (var i = 0; i < bindings.length; ++i) {226 var dataBinding = angular.element(bindings[i]).data('$binding');227 if (dataBinding) {228 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;229 if (exactMatch) {230 var matcher = new RegExp('({|\\s|^|\\|)' +231 /* See http://stackoverflow.com/q/3561711 */232 binding.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') +233 '(}|\\s|$|\\|)');234 if (matcher.test(bindingName)) {235 matches.push(bindings[i]);236 }237 } else {238 if (bindingName.indexOf(binding) != -1) {239 matches.push(bindings[i]);240 }241 }242 }243 }244 return matches; /* Return the whole array for webdriver.findElements. */245};246/**247 * Find an array of elements matching a row within an ng-repeat.248 * Always returns an array of only one element for plain old ng-repeat.249 * Returns an array of all the elements in one segment for ng-repeat-start.250 *251 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.252 * @param {boolean} exact Whether the repeater needs to be matched exactly253 * @param {number} index The row index.254 * @param {Element} using The scope of the search.255 *256 * @return {Array.<Element>} The row of the repeater, or an array of elements257 * in the first row in the case of ng-repeat-start.258 */259function findRepeaterRows(repeater, exact, index, using) {260 using = using || document;261 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];262 var rows = [];263 for (var p = 0; p < prefixes.length; ++p) {264 var attr = prefixes[p] + 'repeat';265 var repeatElems = using.querySelectorAll('[' + attr + ']');266 attr = attr.replace(/\\/g, '');267 for (var i = 0; i < repeatElems.length; ++i) {268 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {269 rows.push(repeatElems[i]);270 }271 }272 }273 /* multiRows is an array of arrays, where each inner array contains274 one row of elements. */275 var multiRows = [];276 for (var p = 0; p < prefixes.length; ++p) {277 var attr = prefixes[p] + 'repeat-start';278 var repeatElems = using.querySelectorAll('[' + attr + ']');279 attr = attr.replace(/\\/g, '');280 for (var i = 0; i < repeatElems.length; ++i) {281 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {282 var elem = repeatElems[i];283 var row = [];284 while (elem.nodeType != 8 ||285 !repeaterMatch(elem.nodeValue, repeater)) {286 if (elem.nodeType == 1) {287 row.push(elem);288 }289 elem = elem.nextSibling;290 }291 multiRows.push(row);292 }293 }294 }295 var row = rows[index] || [], multiRow = multiRows[index] || [];296 return [].concat(row, multiRow);297}298functions.findRepeaterRows = wrapWithHelpers(findRepeaterRows, repeaterMatch);299 /**300 * Find all rows of an ng-repeat.301 *302 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.303 * @param {boolean} exact Whether the repeater needs to be matched exactly304 * @param {Element} using The scope of the search.305 *306 * @return {Array.<Element>} All rows of the repeater.307 */308function findAllRepeaterRows(repeater, exact, using) {309 using = using || document;310 var rows = [];311 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];312 for (var p = 0; p < prefixes.length; ++p) {313 var attr = prefixes[p] + 'repeat';314 var repeatElems = using.querySelectorAll('[' + attr + ']');315 attr = attr.replace(/\\/g, '');316 for (var i = 0; i < repeatElems.length; ++i) {317 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {318 rows.push(repeatElems[i]);319 }320 }321 }322 for (var p = 0; p < prefixes.length; ++p) {323 var attr = prefixes[p] + 'repeat-start';324 var repeatElems = using.querySelectorAll('[' + attr + ']');325 attr = attr.replace(/\\/g, '');326 for (var i = 0; i < repeatElems.length; ++i) {327 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {328 var elem = repeatElems[i];329 while (elem.nodeType != 8 ||330 !repeaterMatch(elem.nodeValue, repeater)) {331 if (elem.nodeType == 1) {332 rows.push(elem);333 }334 elem = elem.nextSibling;335 }336 }337 }338 }339 return rows;340}341functions.findAllRepeaterRows = wrapWithHelpers(findAllRepeaterRows, repeaterMatch);342/**343 * Find an element within an ng-repeat by its row and column.344 *345 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.346 * @param {boolean} exact Whether the repeater needs to be matched exactly347 * @param {number} index The row index.348 * @param {string} binding The column binding, e.g. '{{cat.name}}'.349 * @param {Element} using The scope of the search.350 * @param {string} rootSelector The selector to use for the root app element.351 *352 * @return {Array.<Element>} The element in an array.353 */354function findRepeaterElement(repeater, exact, index, binding, using, rootSelector) {355 var matches = [];356 using = using || document;357 var rows = [];358 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];359 for (var p = 0; p < prefixes.length; ++p) {360 var attr = prefixes[p] + 'repeat';361 var repeatElems = using.querySelectorAll('[' + attr + ']');362 attr = attr.replace(/\\/g, '');363 for (var i = 0; i < repeatElems.length; ++i) {364 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {365 rows.push(repeatElems[i]);366 }367 }368 }369 /* multiRows is an array of arrays, where each inner array contains370 one row of elements. */371 var multiRows = [];372 for (var p = 0; p < prefixes.length; ++p) {373 var attr = prefixes[p] + 'repeat-start';374 var repeatElems = using.querySelectorAll('[' + attr + ']');375 attr = attr.replace(/\\/g, '');376 for (var i = 0; i < repeatElems.length; ++i) {377 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {378 var elem = repeatElems[i];379 var row = [];380 while (elem.nodeType != 8 || (elem.nodeValue &&381 !repeaterMatch(elem.nodeValue, repeater))) {382 if (elem.nodeType == 1) {383 row.push(elem);384 }385 elem = elem.nextSibling;386 }387 multiRows.push(row);388 }389 }390 }391 var row = rows[index];392 var multiRow = multiRows[index];393 var bindings = [];394 if (row) {395 if (angular.getTestability) {396 matches.push.apply(397 matches,398 getNg1Hooks(rootSelector).$$testability.findBindings(row, binding));399 } else {400 if (row.className.indexOf('ng-binding') != -1) {401 bindings.push(row);402 }403 var childBindings = row.getElementsByClassName('ng-binding');404 for (var i = 0; i < childBindings.length; ++i) {405 bindings.push(childBindings[i]);406 }407 }408 }409 if (multiRow) {410 for (var i = 0; i < multiRow.length; ++i) {411 var rowElem = multiRow[i];412 if (angular.getTestability) {413 matches.push.apply(414 matches,415 getNg1Hooks(rootSelector).$$testability.findBindings(rowElem,416 binding));417 } else {418 if (rowElem.className.indexOf('ng-binding') != -1) {419 bindings.push(rowElem);420 }421 var childBindings = rowElem.getElementsByClassName('ng-binding');422 for (var j = 0; j < childBindings.length; ++j) {423 bindings.push(childBindings[j]);424 }425 }426 }427 }428 for (var i = 0; i < bindings.length; ++i) {429 var dataBinding = angular.element(bindings[i]).data('$binding');430 if (dataBinding) {431 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;432 if (bindingName.indexOf(binding) != -1) {433 matches.push(bindings[i]);434 }435 }436 }437 return matches;438}439functions.findRepeaterElement =440 wrapWithHelpers(findRepeaterElement, repeaterMatch, getNg1Hooks);441/**442 * Find the elements in a column of an ng-repeat.443 *444 * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.445 * @param {boolean} exact Whether the repeater needs to be matched exactly446 * @param {string} binding The column binding, e.g. '{{cat.name}}'.447 * @param {Element} using The scope of the search.448 * @param {string} rootSelector The selector to use for the root app element.449 *450 * @return {Array.<Element>} The elements in the column.451 */452function findRepeaterColumn(repeater, exact, binding, using, rootSelector) {453 var matches = [];454 using = using || document;455 var rows = [];456 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];457 for (var p = 0; p < prefixes.length; ++p) {458 var attr = prefixes[p] + 'repeat';459 var repeatElems = using.querySelectorAll('[' + attr + ']');460 attr = attr.replace(/\\/g, '');461 for (var i = 0; i < repeatElems.length; ++i) {462 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {463 rows.push(repeatElems[i]);464 }465 }466 }467 /* multiRows is an array of arrays, where each inner array contains468 one row of elements. */469 var multiRows = [];470 for (var p = 0; p < prefixes.length; ++p) {471 var attr = prefixes[p] + 'repeat-start';472 var repeatElems = using.querySelectorAll('[' + attr + ']');473 attr = attr.replace(/\\/g, '');474 for (var i = 0; i < repeatElems.length; ++i) {475 if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {476 var elem = repeatElems[i];477 var row = [];478 while (elem.nodeType != 8 || (elem.nodeValue &&479 !repeaterMatch(elem.nodeValue, repeater))) {480 if (elem.nodeType == 1) {481 row.push(elem);482 }483 elem = elem.nextSibling;484 }485 multiRows.push(row);486 }487 }488 }489 var bindings = [];490 for (var i = 0; i < rows.length; ++i) {491 if (angular.getTestability) {492 matches.push.apply(493 matches,494 getNg1Hooks(rootSelector).$$testability.findBindings(rows[i],495 binding));496 } else {497 if (rows[i].className.indexOf('ng-binding') != -1) {498 bindings.push(rows[i]);499 }500 var childBindings = rows[i].getElementsByClassName('ng-binding');501 for (var k = 0; k < childBindings.length; ++k) {502 bindings.push(childBindings[k]);503 }504 }505 }506 for (var i = 0; i < multiRows.length; ++i) {507 for (var j = 0; j < multiRows[i].length; ++j) {508 if (angular.getTestability) {509 matches.push.apply(510 matches,511 getNg1Hooks(rootSelector).$$testability.findBindings(512 multiRows[i][j], binding));513 } else {514 var elem = multiRows[i][j];515 if (elem.className.indexOf('ng-binding') != -1) {516 bindings.push(elem);517 }518 var childBindings = elem.getElementsByClassName('ng-binding');519 for (var k = 0; k < childBindings.length; ++k) {520 bindings.push(childBindings[k]);521 }522 }523 }524 }525 for (var j = 0; j < bindings.length; ++j) {526 var dataBinding = angular.element(bindings[j]).data('$binding');527 if (dataBinding) {528 var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;529 if (bindingName.indexOf(binding) != -1) {530 matches.push(bindings[j]);531 }532 }533 }534 return matches;535}536functions.findRepeaterColumn =537 wrapWithHelpers(findRepeaterColumn, repeaterMatch, getNg1Hooks);538/**539 * Find elements by model name.540 *541 * @param {string} model The model name.542 * @param {Element} using The scope of the search.543 * @param {string} rootSelector The selector to use for the root app element.544 *545 * @return {Array.<Element>} The matching elements.546 */547functions.findByModel = function(model, using, rootSelector) {548 using = using || document;549 if (angular.getTestability) {550 return getNg1Hooks(rootSelector).$$testability.551 findModels(using, model, true);552 }553 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];554 for (var p = 0; p < prefixes.length; ++p) {555 var selector = '[' + prefixes[p] + 'model="' + model + '"]';556 var elements = using.querySelectorAll(selector);557 if (elements.length) {558 return elements;559 }560 }561};562/**563 * Find elements by options.564 *565 * @param {string} optionsDescriptor The descriptor for the option566 * (i.e. fruit for fruit in fruits).567 * @param {Element} using The scope of the search.568 *569 * @return {Array.<Element>} The matching elements.570 */571functions.findByOptions = function(optionsDescriptor, using) {572 using = using || document;573 var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];574 for (var p = 0; p < prefixes.length; ++p) {575 var selector = '[' + prefixes[p] + 'options="' + optionsDescriptor + '"] option';576 var elements = using.querySelectorAll(selector);577 if (elements.length) {578 return elements;579 }580 }581};582/**583 * Find buttons by textual content.584 *585 * @param {string} searchText The exact text to match.586 * @param {Element} using The scope of the search.587 *588 * @return {Array.<Element>} The matching elements.589 */590functions.findByButtonText = function(searchText, using) {591 using = using || document;592 var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');593 var matches = [];594 for (var i = 0; i < elements.length; ++i) {595 var element = elements[i];596 var elementText;597 if (element.tagName.toLowerCase() == 'button') {598 elementText = element.textContent || element.innerText || '';599 } else {600 elementText = element.value;601 }602 if (elementText.trim() === searchText) {603 matches.push(element);604 }605 }606 return matches;607};608/**609 * Find buttons by textual content.610 *611 * @param {string} searchText The exact text to match.612 * @param {Element} using The scope of the search.613 *614 * @return {Array.<Element>} The matching elements.615 */616functions.findByPartialButtonText = function(searchText, using) {617 using = using || document;618 var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');619 var matches = [];620 for (var i = 0; i < elements.length; ++i) {621 var element = elements[i];622 var elementText;623 if (element.tagName.toLowerCase() == 'button') {624 elementText = element.textContent || element.innerText || '';625 } else {626 elementText = element.value;627 }628 if (elementText.indexOf(searchText) > -1) {629 matches.push(element);630 }631 }632 return matches;633};634/**635 * Find elements by css selector and textual content.636 *637 * @param {string} cssSelector The css selector to match.638 * @param {string} searchText The exact text to match or a serialized regex.639 * @param {Element} using The scope of the search.640 *641 * @return {Array.<Element>} An array of matching elements.642 */643functions.findByCssContainingText = function(cssSelector, searchText, using) {644 using = using || document;645 if (searchText.indexOf('__REGEXP__') === 0) {646 var match = searchText.split('__REGEXP__')[1].match(/\/(.*)\/(.*)?/);647 searchText = new RegExp(match[1], match[2] || '');648 }649 var elements = using.querySelectorAll(cssSelector);650 var matches = [];651 for (var i = 0; i < elements.length; ++i) {652 var element = elements[i];653 var elementText = element.textContent || element.innerText || '';654 var elementMatches = searchText instanceof RegExp ?655 searchText.test(elementText) :656 elementText.indexOf(searchText) > -1;657 if (elementMatches) {658 matches.push(element);659 }660 }661 return matches;662};663/**664 * Tests whether the angular global variable is present on a page. Retries665 * in case the page is just loading slowly.666 *667 * Asynchronous.668 *669 * @param {number} attempts Number of times to retry.670 * @param {boolean} ng12Hybrid Flag set if app is a hybrid of angular 1 and 2671 * @param {function({version: ?number, message: ?string})} asyncCallback callback672 *673 */674functions.testForAngular = function(attempts, ng12Hybrid, asyncCallback) {675 var callback = function(args) {676 setTimeout(function() {677 asyncCallback(args);678 }, 0);679 };680 var definitelyNg1 = !!ng12Hybrid;681 var definitelyNg2OrNewer = false;682 var check = function(n) {683 try {684 /* Figure out which version of angular we're waiting on */685 if (!definitelyNg1 && !definitelyNg2OrNewer) {686 if (window.angular && !(window.angular.version && window.angular.version.major > 1)) {687 definitelyNg1 = true;688 } else if (window.getAllAngularTestabilities) {689 definitelyNg2OrNewer = true;690 }691 }692 /* See if our version of angular is ready */693 if (definitelyNg1) {694 if (window.angular && window.angular.resumeBootstrap) {695 return callback({ver: 1});696 }697 } else if (definitelyNg2OrNewer) {698 if (true /* ng2 has no resumeBootstrap() */) {699 return callback({ver: 2});700 }701 }702 /* Try again (or fail) */703 if (n < 1) {704 if (definitelyNg1 && window.angular) {705 callback({message: 'angular never provided resumeBootstrap'});706 } else if (ng12Hybrid && !window.angular) {707 callback({message: 'angular 1 never loaded' +708 window.getAllAngularTestabilities ? ' (are you sure this app ' +709 'uses ngUpgrade? Try un-setting ng12Hybrid)' : ''});710 } else {711 callback({message: 'retries looking for angular exceeded'});712 }713 } else {714 window.setTimeout(function() {check(n - 1);}, 1000);715 }716 } catch (e) {717 callback({message: e});718 }719 };720 check(attempts);721};722/**723 * Evalute an Angular expression in the context of a given element.724 *725 * @param {Element} element The element in whose scope to evaluate.726 * @param {string} expression The expression to evaluate.727 *728 * @return {?Object} The result of the evaluation.729 */730functions.evaluate = function(element, expression) {731 return angular.element(element).scope().$eval(expression);732};733functions.allowAnimations = function(element, value) {734 var ngElement = angular.element(element);735 if (ngElement.allowAnimations) {736 // AngularDart: $testability API.737 return ngElement.allowAnimations(value);738 } else {739 // AngularJS740 var enabledFn = ngElement.injector().get('$animate').enabled;741 return (value == null) ? enabledFn() : enabledFn(value);742 }743};744/**745 * Return the current url using $location.absUrl().746 *747 * @param {string} selector The selector housing an ng-app748 */749functions.getLocationAbsUrl = function(selector) {750 var hooks = getNg1Hooks(selector);751 if (angular.getTestability) {752 return hooks.$$testability.getLocation();753 }754 return hooks.$injector.get('$location').absUrl();755};756/**757 * Browse to another page using in-page navigation.758 *759 * @param {string} selector The selector housing an ng-app760 * @param {string} url In page URL using the same syntax as $location.url(),761 * /path?search=a&b=c#hash762 */763functions.setLocation = function(selector, url) {764 var hooks = getNg1Hooks(selector);765 if (angular.getTestability) {766 return hooks.$$testability.setLocation(url);767 }768 var $injector = hooks.$injector;769 var $location = $injector.get('$location');770 var $rootScope = $injector.get('$rootScope');771 if (url !== $location.url()) {772 $location.url(url);773 $rootScope.$digest();774 }775};776/**777 * Retrieve the pending $http requests.778 *779 * @param {string} selector The selector housing an ng-app780 * @return {!Array<!Object>} An array of pending http requests.781 */782functions.getPendingHttpRequests = function(selector) {783 var hooks = getNg1Hooks(selector, true);784 var $http = hooks.$injector.get('$http');785 return $http.pendingRequests;786};787['waitForAngular', 'findBindings', 'findByModel', 'getLocationAbsUrl',788 'setLocation', 'getPendingHttpRequests'].forEach(function(funName) {789 functions[funName] = wrapWithHelpers(functions[funName], getNg1Hooks);790});791/* Publish all the functions as strings to pass to WebDriver's792 * exec[Async]Script. In addition, also include a script that will793 * install all the functions on window (for debugging.)794 *795 * We also wrap any exceptions thrown by a clientSideScripts function796 * that is not an instance of the Error type into an Error type. If we797 * don't do so, then the resulting stack trace is completely unhelpful...
Using AI Code Generation
1const { getNg1Hooks } = require('protractor-helper');2const { getNg2Hooks } = require('protractor-helper');3const { getNg4Hooks } = require('protractor-helper');4const { getNg5Hooks } = require('protractor-helper');5const { getNg6Hooks } = require('protractor-helper');6const { getNg7Hooks } = require('protractor-helper');7const { getNg8Hooks } = require('protractor-helper');8const { getNg9Hooks } = require('protractor-helper');9const { getNg10Hooks } = require('protractor-helper');10const { getNg11Hooks } = require('protractor-helper');11const { getNg12Hooks } = require('protractor-helper');12const { getNg13Hooks } = require('protractor-helper');13const { getNg14Hooks } = require('protractor-helper');14const { getNg15Hooks } = require('protractor-helper');15const { getNg16Hooks } = require('protractor-helper');16const { getNg17Hooks } = require('protractor-helper');17const { getNg18Hooks } = require('protractor-helper');18const { getNg19Hooks } = require('protractor-helper');
Using AI Code Generation
1const protractorHelper = require('protractor-helper');2const ng1Hooks = protractorHelper.getNg1Hooks();3const ng2Hooks = protractorHelper.getNg2Hooks();4const protractorHelper = require('protractor-helper');5const ng1Hooks = protractorHelper.getNg1Hooks();6describe('foo', () => {7 beforeEach(ng1Hooks.beforeEach);8 afterEach(ng1Hooks.afterEach);9});10const protractorHelper = require('protractor-helper');11const ng2Hooks = protractorHelper.getNg2Hooks();12describe('foo', () => {13 beforeEach(ng2Hooks.beforeEach);14 afterEach(ng2Hooks.afterEach);15});16- **It's easy to use** - The idea behind this library is to help you write more readable and maintainable end-to-end tests. The methods provided by this library are very easy to use and follow the [Protractor Style Guide](
Using AI Code Generation
1const { getNg1Hooks } = require('protractor-helper');2const { browser, element, by } = require('protractor');3const { getNg1Hooks } = require('protractor-helper');4const { browser, element, by } = require('protractor');5describe('ng1 test', () => {6 const { whenStable } = getNg1Hooks(browser);7 it('should work', async () => {8 const todoInput = element(by.model('todoList.todoText'));9 const addButton = element(by.css('[value="add"]'));10 await whenStable(() => {11 todoInput.sendKeys('write first protractor test');12 addButton.click();13 });14 const todoList = element.all(by.repeater('todo in todoList.todos'));15 expect(await todoList.count()).toBe(3);16 });17});
Using AI Code Generation
1const {ProtractorUtils} = require('protractor-utils');2const protractorUtils = new ProtractorUtils(browser);3const {getNg1Hooks} = protractorUtils;4describe('Sample test', () => {5 const {beforeEach, afterEach} = getNg1Hooks();6 beforeEach(() => {7 });8 afterEach(() => {9 });10});11#### `getNg1Hooks()`12#### `getNg1Hooks()`13#### `getNg1Hooks()`14#### `getNg1Hooks()`15#### `getNg1Hooks()`16#### `getNg1Hooks()`17#### `getNg1Hooks()`18#### `getNg1Hooks()`19#### `getNg1Hooks()`20Contributions are welcome. Please read [CONTRIBUTING.md](
Using AI Code Generation
1var protractorUtils = require('protractor-utils');2var ng1Hooks = protractorUtils.getNg1Hooks();3var ng2Hooks = protractorUtils.getNg2Hooks();4#### ProtractorUtils.getNg1Hooks()5var protractorUtils = require('protractor-utils');6var ng1Hooks = protractorUtils.getNg1Hooks();7#### ProtractorUtils.getNg2Hooks()8var protractorUtils = require('protractor-utils');9var ng2Hooks = protractorUtils.getNg2Hooks();10#### Hooks.beforeEach()11beforeEach(function() {12 Hooks.beforeEach();13});14#### Hooks.afterEach()15afterEach(function() {16 Hooks.afterEach();17});18#### Ng1Hooks.beforeEach()19beforeEach(function() {20 Ng1Hooks.beforeEach();21});22#### Ng1Hooks.afterEach()
Protractor is developed by Google Developers to test Angular and AngularJS code. Today, it is used to test non-Angular applications as well. It performs a real-world user-like test against your application in a real browser. It comes under an end-to-end testing framework. As of now, Selenium Protractor has proved to be a popular framework for end-to-end automation for AngularJS.
Let’s talk about what it does:
Protractor is a JavaScript framework, end-to-end test automation framework for Angular and AngularJS applications.
Protractor Selenium provides new locator methods that actually make it easier to find elements in the DOM.
Two files are required to execute Protractor Selenium tests for end-to-end automation: Specs & Config. Go through the link above to understand in a better way.
To carry out extensive, automated cross browser testing, you can't imagine installing thousands of the available browsers on your own workstation. The only way to increase browser usage is through remote execution on the cloud. To execute your automation test scripts across a variety of platforms and browser versions, LambdaTest offers more than 3000 browsers.
We recommend Selenium for end-to-end automation for AngularJS because both are maintained and owned by Google, and they build JavaScript test automation framework to handle AngularJS components in a way that better matches how developers use it.
For scripting, selenium locators are essential since if they're off, your automation scripts won't run. Therefore, in any testing framework, these Selenium locators are the foundation of your Selenium test automation efforts.
To make sure that your Selenium automation tests function as intended, debugging can be an effective option. Check the blog to know more.
If you are not familiar with writing Selenium test automation on Protractor, here is a blog for you to get you understand in depth.
Selenium tests are asynchronous and there are various reasons for a timeout to occur in a Protractor test. Find out how to handle timeouts in this Protractor tutorial.
In this Protractor tutorial, learn how to handle frames or iframes in Selenium with Protractor for automated browser testing.
Handle alerts and popups in Protractor more efficiently. It can be confusing. Here's a simple guide to understand how to handle alerts and popups in Selenium.
Get 100 minutes of automation test minutes FREE!!