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!!
