{"version":3,"sources":["jsdelivr-header.js","/npm/protractor-redbox@2.5.1/lib/protractor.js"],"names":[],"mappings":"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","file":"/npm/protractor-redbox@2.5.1/lib/protractor.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/protractor-redbox@2.5.1/lib/protractor.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","var util = require('util');\nvar url = require('url');\nvar webdriver = require('selenium-webdriver');\nvar helper = require('./util');\nvar log = require('./logger.js');\nvar ElementArrayFinder = require('./element').ElementArrayFinder;\nvar ElementFinder = require('./element').ElementFinder;\nvar build$ = require('./element').build$;\nvar build$$ = require('./element').build$$;\nvar Plugins = require('./plugins');\n\nvar clientSideScripts = require('./clientsidescripts.js');\nvar ProtractorBy = require('./locators.js').ProtractorBy;\nvar ExpectedConditions = require('./expectedConditions.js');\n\n// jshint browser: true\n/* global angular */\n\nvar DEFER_LABEL = 'NG_DEFER_BOOTSTRAP!';\nvar DEFAULT_RESET_URL = 'data:text/html,<html></html>';\nvar DEFAULT_GET_PAGE_TIMEOUT = 10000;\n\n/*\n * Mix in other webdriver functionality to be accessible via protractor.\n */\nfor (var foo in webdriver) {\n  exports[foo] = webdriver[foo];\n}\n\n/**\n * @type {ProtractorBy}\n */\nexports.By = new ProtractorBy();\n\n/**\n * @type {ElementFinder}\n */\nexports.ElementFinder = ElementFinder;\n\n/**\n * @type {ElementArrayFinder}\n */\nexports.ElementArrayFinder = ElementArrayFinder;\n\n/**\n * @type {ExpectedConditions}\n */\nexports.ExpectedConditions = new ExpectedConditions();\n\n/**\n * Mix a function from one object onto another. The function will still be\n * called in the context of the original object.\n *\n * @private\n * @param {Object} to\n * @param {Object} from\n * @param {string} fnName\n * @param {function=} setupFn\n */\nvar mixin = function(to, from, fnName, setupFn) {\n  to[fnName] = function() {\n    if (setupFn) {\n      setupFn();\n    }\n    return from[fnName].apply(from, arguments);\n  };\n};\n\n/**\n * Build the helper 'element' function for a given instance of Protractor.\n *\n * @private\n * @param {Protractor} ptor\n * @return {function(webdriver.Locator): ElementFinder}\n */\nvar buildElementHelper = function(ptor) {\n  var element = function(locator) {\n    return new ElementArrayFinder(ptor).all(locator).toElementFinder_();\n  };\n\n  element.all = function(locator) {\n    return new ElementArrayFinder(ptor).all(locator);\n  };\n\n  return element;\n};\n\n/**\n * @alias browser\n * @constructor\n * @extends {webdriver.WebDriver}\n * @param {webdriver.WebDriver} webdriver\n * @param {string=} opt_baseUrl A base URL to run get requests against.\n * @param {string=} opt_rootElement  Selector element that has an ng-app in\n *     scope.\n */\nvar Protractor = function(webdriverInstance, opt_baseUrl, opt_rootElement) {\n  // These functions should delegate to the webdriver instance, but should\n  // wait for Angular to sync up before performing the action. This does not\n  // include functions which are overridden by protractor below.\n  var methodsToSync = ['getCurrentUrl', 'getPageSource', 'getTitle'];\n\n  // Mix all other driver functionality into Protractor.\n  for (var method in webdriverInstance) {\n    if (!this[method] && typeof webdriverInstance[method] == 'function') {\n      if (methodsToSync.indexOf(method) !== -1) {\n        mixin(this, webdriverInstance, method, this.waitForAngular.bind(this));\n      } else {\n        mixin(this, webdriverInstance, method);\n      }\n    }\n  }\n  var self = this;\n\n  /**\n   * The wrapped webdriver instance. Use this to interact with pages that do\n   * not contain Angular (such as a log-in screen).\n   *\n   * @type {webdriver.WebDriver}\n   */\n  this.driver = webdriverInstance;\n\n  /**\n   * Helper function for finding elements.\n   *\n   * @type {function(webdriver.Locator): ElementFinder}\n   */\n  this.element = buildElementHelper(this);\n\n  /**\n   * Shorthand function for finding elements by css.\n   *\n   * @type {function(string): ElementFinder}\n   */\n  this.$ = build$(this.element, webdriver.By);\n\n  /**\n   * Shorthand function for finding arrays of elements by css.\n   *\n   * @type {function(string): ElementArrayFinder}\n   */\n  this.$$ = build$$(this.element, webdriver.By);\n\n  /**\n   * All get methods will be resolved against this base URL. Relative URLs are =\n   * resolved the way anchor tags resolve.\n   *\n   * @type {string}\n   */\n  this.baseUrl = opt_baseUrl || '';\n\n  /**\n   * The css selector for an element on which to find Angular. This is usually\n   * 'body' but if your ng-app is on a subsection of the page it may be\n   * a subelement.\n   *\n   * @type {string}\n   */\n  this.rootEl = opt_rootElement || 'body';\n\n  /**\n   * If true, Protractor will not attempt to synchronize with the page before\n   * performing actions. This can be harmful because Protractor will not wait\n   * until $timeouts and $http calls have been processed, which can cause\n   * tests to become flaky. This should be used only when necessary, such as\n   * when a page continuously polls an API using $timeout.\n   *\n   * @type {boolean}\n   */\n  this.ignoreSynchronization = false;\n\n  /**\n   * Timeout in milliseconds to wait for pages to load when calling `get`.\n   *\n   * @type {number}\n   */\n  this.getPageTimeout = DEFAULT_GET_PAGE_TIMEOUT;\n\n  /**\n   * An object that holds custom test parameters.\n   *\n   * @type {Object}\n   */\n  this.params = {};\n\n  /**\n   * Set by the runner.\n   *\n   * @type {q.Promise} Done when the new browser is ready for use\n   */\n  this.ready = null;\n\n  /*\n   * Set by the runner.\n   *\n   * @type {Plugins} Object containing plugin funtions from config.\n   */\n  this.plugins_ = new Plugins({});\n\n  /**\n   * The reset URL to use between page loads.\n   *\n   * @type {string}\n   */\n  this.resetUrl = DEFAULT_RESET_URL;\n  this.driver.getCapabilities().then(function(caps) {\n    // Internet Explorer does not accept data URLs, which are the default\n    // reset URL for Protractor.\n    // Safari accepts data urls, but SafariDriver fails after one is used.\n    // PhantomJS produces a \"Detected a page unload event\" if we use data urls\n    var browserName = caps.get('browserName');\n    if (browserName === 'internet explorer' || \n        browserName === 'safari' || \n        browserName === 'phantomjs') {\n          self.resetUrl = 'about:blank';\n    }\n  });\n\n  /**\n   * Information about mock modules that will be installed during every\n   * get().\n   *\n   * @type {Array<{name: string, script: function|string, args: Array.<string>}>}\n   */\n  this.mockModules_ = [];\n\n  this.addBaseMockModules_();\n\n  /**\n   * If specified, start a debugger server at specified port instead of repl\n   * when running element explorer.\n   * @private {number}\n   */\n  this.debuggerServerPort_;\n};\n\n\n/**\n * Get the processed configuration object that is currently being run. This\n * will contain the specs and capabilities properties of the current runner\n * instance.\n *\n * Set by the runner.\n *\n * @return {q.Promise} A promise which resolves to the capabilities object.\n */\nProtractor.prototype.getProcessedConfig = null;\n\n/**\n * Fork another instance of protractor for use in interactive tests.\n *\n * Set by the runner.\n *\n * @param {boolean} opt_useSameUrl Whether to navigate to current url on creation\n * @param {boolean} opt_copyMockModules Whether to apply same mock modules on creation\n * @return {Protractor} a protractor instance.\n */\nProtractor.prototype.forkNewDriverInstance = null;\n\n\n/**\n * Instead of using a single root element, search through all angular apps\n * available on the page when finding elements or waiting for stability.\n * Only compatible with Angular2.\n */\nProtractor.prototype.useAllAngular2AppRoots = function() {\n  // The empty string is an invalid css selector, so we use it to easily\n  // signal to scripts to not find a root element.\n  this.rootEl = '';\n};\n\n/**\n * The same as {@code webdriver.WebDriver.prototype.executeScript},\n * but with a customized description for debugging.\n *\n * @private\n * @param {!(string|Function)} script The script to execute.\n * @param {string} description A description of the command for debugging.\n * @param {...*} var_args The arguments to pass to the script.\n * @return {!webdriver.promise.Promise.<T>} A promise that will resolve to the\n *    scripts return value.\n * @template T\n */\nProtractor.prototype.executeScript_ = function(script, description) {\n  if (typeof script === 'function') {\n    script = 'return (' + script + ').apply(null, arguments);';\n  }\n\n  return this.driver.schedule(\n      new webdriver.Command(webdriver.CommandName.EXECUTE_SCRIPT).\n          setParameter('script', script).\n          setParameter('args', Array.prototype.slice.call(arguments, 2)),\n      description);\n};\n\n/**\n * The same as {@code webdriver.WebDriver.prototype.executeAsyncScript},\n * but with a customized description for debugging.\n *\n * @private\n * @param {!(string|Function)} script The script to execute.\n * @param {string} description A description for debugging purposes.\n * @param {...*} var_args The arguments to pass to the script.\n * @return {!webdriver.promise.Promise.<T>} A promise that will resolve to the\n *    scripts return value.\n * @template T\n */\nProtractor.prototype.executeAsyncScript_ =\n    function(script, description) {\n      if (typeof script === 'function') {\n        script = 'return (' + script + ').apply(null, arguments);';\n      }\n      return this.driver.schedule(\n          new webdriver.Command(webdriver.CommandName.EXECUTE_ASYNC_SCRIPT).\n              setParameter('script', script).\n              setParameter('args', Array.prototype.slice.call(arguments, 2)),\n          description);\n    };\n\n/**\n * Instruct webdriver to wait until Angular has finished rendering and has\n * no outstanding $http or $timeout calls before continuing.\n * Note that Protractor automatically applies this command before every\n * WebDriver action.\n *\n * @param {string=} opt_description An optional description to be added\n *     to webdriver logs.\n * @return {!webdriver.promise.Promise} A promise that will resolve to the\n *    scripts return value.\n */\nProtractor.prototype.waitForAngular = function(opt_description) {\n  var description = opt_description ? ' - ' + opt_description : '';\n  var self = this;\n  if (this.ignoreSynchronization) {\n    return self.driver.controlFlow().execute(function() {\n      return true;\n    }, 'Ignore Synchronization Protractor.waitForAngular()');\n  }\n\n  function runWaitForAngularScript() {\n    if (self.rootEl) {\n      return self.executeAsyncScript_(\n          clientSideScripts.waitForAngular,\n          'Protractor.waitForAngular()' + description,\n          self.rootEl);\n    } else {\n      return self.executeAsyncScript_(\n          clientSideScripts.waitForAllAngular2,\n          'Protractor.waitForAngular()' + description);\n    }\n  }\n\n  return runWaitForAngularScript().\n      then(function(browserErr) {\n        if (browserErr) {\n          throw 'Error while waiting for Protractor to ' +\n                'sync with the page: ' + JSON.stringify(browserErr);\n        }\n    }).then(function() {\n      return self.driver.controlFlow().execute(function() {\n        return self.plugins_.waitForPromise();\n      }, 'Plugins.waitForPromise()').then(function() {\n        return self.driver.wait(function() {\n          return self.plugins_.waitForCondition().then(function(results) {\n            return results.reduce(function(x, y) { return x && y; }, true);\n          });\n        }, self.allScriptsTimeout, 'Plugins.waitForCondition()');\n      });\n    }, function(err) {\n      var timeout;\n      if (/asynchronous script timeout/.test(err.message)) {\n        // Timeout on Chrome\n        timeout = /-?[\\d\\.]*\\ seconds/.exec(err.message);\n      } else if (/Timed out waiting for async script/.test(err.message)) {\n        // Timeout on Firefox\n        timeout = /-?[\\d\\.]*ms/.exec(err.message);\n      } else if (/Timed out waiting for an asynchronous script/.test(err.message)) {\n        // Timeout on Safari\n        timeout = /-?[\\d\\.]*\\ ms/.exec(err.message);\n      }\n      if (timeout) {\n        var errMsg = 'Timed out waiting for Protractor to synchronize with ' +\n            'the page after ' + timeout + '. Please see ' +\n            'https://github.com/angular/protractor/blob/master/docs/faq.md';\n        var pendingTimeoutsPromise = self.executeScript_(\n          'return window.NG_PENDING_TIMEOUTS',\n          'Protractor.waitForAngular() - getting pending timeouts' + description\n        );\n        var pendingHttpsPromise = self.executeScript_(\n          clientSideScripts.getPendingHttpRequests, \n          'Protractor.waitForAngular() - getting pending https' + description,\n          self.rootEl\n        );\n        return webdriver.promise.all([\n            pendingTimeoutsPromise, pendingHttpsPromise]).\n              then(function(arr) {\n                var pendingTimeouts = arr[0] || [];\n                var pendingHttps = arr[1] || [];\n\n                var key, pendingTasks = [];\n                for (key in pendingTimeouts) {\n                  if (pendingTimeouts.hasOwnProperty(key)) {\n                    pendingTasks.push('- $timeout: ' + pendingTimeouts[key]);\n                  }\n                }\n                for (key in pendingHttps) {\n                  pendingTasks.push('- $http: ' + pendingHttps[key].url);\n                }\n                if (pendingTasks.length) {\n                  errMsg += '. The following tasks were pending:\\n';\n                  errMsg += pendingTasks.join('\\n');\n                }\n                throw errMsg;\n              }, function() {\n                throw errMsg;\n              });\n      } else {\n        throw err;\n      }\n    });\n};\n\n/**\n * Waits for Angular to finish rendering before searching for elements.\n * @see webdriver.WebDriver.findElement\n * @return {!webdriver.WebElement}\n */\nProtractor.prototype.findElement = function(locator) {\n  return this.element(locator).getWebElement();\n};\n\n/**\n * Waits for Angular to finish rendering before searching for elements.\n * @see webdriver.WebDriver.findElements\n * @return {!webdriver.promise.Promise} A promise that will be resolved to an\n *     array of the located {@link webdriver.WebElement}s.\n */\nProtractor.prototype.findElements = function(locator) {\n  return this.element.all(locator).getWebElements();\n};\n\n/**\n * Tests if an element is present on the page.\n * @see webdriver.WebDriver.isElementPresent\n * @return {!webdriver.promise.Promise} A promise that will resolve to whether\n *     the element is present on the page.\n */\nProtractor.prototype.isElementPresent = function(locatorOrElement) {\n  var element = (locatorOrElement.isPresent) ?\n      locatorOrElement : this.element(locatorOrElement);\n  return element.isPresent();\n};\n\n/**\n * Add a module to load before Angular whenever Protractor.get is called.\n * Modules will be registered after existing modules already on the page,\n * so any module registered here will override preexisting modules with the same\n * name.\n *\n * @example\n * browser.addMockModule('modName', function() {\n *   angular.module('modName', []).value('foo', 'bar');\n * });\n *\n * @param {!string} name The name of the module to load or override.\n * @param {!string|Function} script The JavaScript to load the module.\n * @param {...*} varArgs Any additional arguments will be provided to\n *     the script and may be referenced using the `arguments` object.\n */\nProtractor.prototype.addMockModule = function(name, script) {\n  var moduleArgs = Array.prototype.slice.call(arguments, 2);\n\n  this.mockModules_.push({\n    name: name,\n    script: script,\n    args: moduleArgs\n  });\n};\n\n/**\n * Clear the list of registered mock modules.\n */\nProtractor.prototype.clearMockModules = function() {\n  this.mockModules_ = [];\n  this.addBaseMockModules_();\n};\n\n/**\n * Remove a registered mock module.\n *\n * @example\n * browser.removeMockModule('modName');\n *\n * @param {!string} name The name of the module to remove.\n */\nProtractor.prototype.removeMockModule = function(name) {\n  for (var i = 0; i < this.mockModules_.length; ++i) {\n    if (this.mockModules_[i].name == name) {\n      this.mockModules_.splice(i--, 1);\n    }\n  }\n};\n\n/**\n * Get a list of the current mock modules.\n *\n * @return {Array.<!string|Function>}\n */\nProtractor.prototype.getRegisteredMockModules = function() {\n  return this.mockModules_.map(function(module) {\n    return module.script;\n  });\n};\n\n/**\n * Add the base mock modules used for all Protractor tests.\n *\n * @private\n */\nProtractor.prototype.addBaseMockModules_ = function() {\n  this.addMockModule('protractorBaseModule_', function() {\n    angular.module('protractorBaseModule_', []).\n        config(['$compileProvider', function($compileProvider) {\n          if ($compileProvider.debugInfoEnabled) {\n            $compileProvider.debugInfoEnabled(true);\n          }\n        }]).\n        config(['$provide', function($provide) {\n          $provide.decorator('$timeout', ['$delegate', function($delegate) {\n            var $timeout = $delegate;\n\n            var taskId = 0;\n            if (!window.NG_PENDING_TIMEOUTS) {\n              window.NG_PENDING_TIMEOUTS = {};\n            }\n              \n            var extendedTimeout = function() {\n              var args = Array.prototype.slice.call(arguments);\n              if (typeof(args[0]) !== 'function') {\n                return $timeout.apply(null, args);\n              }\n\n              taskId++;\n              var fn = args[0];\n              window.NG_PENDING_TIMEOUTS[taskId] = fn.toString();\n              var wrappedFn = (function(taskId_) {\n                return function() {\n                  delete window.NG_PENDING_TIMEOUTS[taskId_]; \n                  return fn.apply(null, arguments);\n                };\n              })(taskId);\n              args[0] = wrappedFn;\n              \n              var promise = $timeout.apply(null, args);\n              promise.ptorTaskId_ = taskId;\n              return promise;\n            };\n\n            extendedTimeout.cancel = function() {\n              var taskId_ = arguments[0] && arguments[0].ptorTaskId_;\n              if (taskId_) {\n                delete window.NG_PENDING_TIMEOUTS[taskId_]; \n              }\n              return $timeout.cancel.apply($timeout, arguments);\n            };\n             \n            return extendedTimeout;\n          }]);\n        }]);\n  });\n};\n\n/**\n * @see webdriver.WebDriver.get\n *\n * Navigate to the given destination and loads mock modules before\n * Angular. Assumes that the page being loaded uses Angular.\n * If you need to access a page which does not have Angular on load, use\n * the wrapped webdriver directly.\n *\n * @example\n * browser.get('https://angularjs.org/');\n * expect(browser.getCurrentUrl()).toBe('https://angularjs.org/');\n *\n * @param {string} destination Destination URL.\n * @param {number=} opt_timeout Number of milliseconds to wait for Angular to\n *     start.\n */\nProtractor.prototype.get = function(destination, opt_timeout) {\n  var timeout = opt_timeout ? opt_timeout : this.getPageTimeout;\n  var self = this;\n\n  destination = this.baseUrl.indexOf('file://') === 0 ?\n    this.baseUrl + destination : url.resolve(this.baseUrl, destination);\n  var msg = function(str) {\n    return 'Protractor.get(' + destination + ') - ' + str;\n  };\n\n  if (this.ignoreSynchronization) {\n    this.driver.get(destination);\n    return this.driver.controlFlow().execute(function() {\n      return self.plugins_.onPageLoad();\n    });\n  }\n\n  var deferred = webdriver.promise.defer();\n\n  this.driver.get(this.resetUrl).then(null, deferred.reject);\n  this.executeScript_(\n      'window.name = \"' + DEFER_LABEL + '\" + window.name;' +\n      'window.location.replace(\"' + destination + '\");',\n      msg('reset url'))\n      .then(null, deferred.reject);\n\n  // We need to make sure the new url has loaded before\n  // we try to execute any asynchronous scripts.\n  this.driver.wait(function() {\n    return self.executeScript_('return window.location.href;', msg('get url')).\n        then(function(url) {\n          return url !== self.resetUrl;\n        }, function(err) {\n          if (err.code == 13) {\n            // Ignore the error, and continue trying. This is because IE\n            // driver sometimes (~1%) will throw an unknown error from this\n            // execution. See https://github.com/angular/protractor/issues/841\n            // This shouldn't mask errors because it will fail with the timeout\n            // anyway.\n            return false;\n          } else {\n            throw err;\n          }\n        });\n  }, timeout,\n  'waiting for page to load for ' + timeout + 'ms')\n  .then(null, deferred.reject);\n\n  this.driver.controlFlow().execute(function() {\n    return self.plugins_.onPageLoad();\n  });\n\n  // Make sure the page is an Angular page.\n  self.executeAsyncScript_(clientSideScripts.testForAngular,\n      msg('test for angular'),\n      Math.floor(timeout / 1000)).\n      then(function(angularTestResult) {\n        var angularVersion = angularTestResult.ver;\n        if (!angularVersion) {\n          var message = angularTestResult.message;\n          throw new Error('Angular could not be found on the page ' +\n              destination + ' : ' + message);\n        }\n        return angularVersion;\n      }, function(err) {\n        throw 'Error while running testForAngular: ' + err.message;\n      })\n      .then(loadMocks, deferred.reject);\n\n  function loadMocks(angularVersion) {\n    if (angularVersion === 1) {\n      // At this point, Angular will pause for us until angular.resumeBootstrap\n      // is called.\n      var moduleNames = [];\n      for (var i = 0; i < self.mockModules_.length; ++i) {\n        var mockModule = self.mockModules_[i];\n        var name = mockModule.name;\n        moduleNames.push(name);\n        var executeScriptArgs = [mockModule.script, msg('add mock module ' + name)].\n            concat(mockModule.args);\n        self.executeScript_.apply(self, executeScriptArgs).\n            then(null, function(err) {\n              throw 'Error while running module script ' + name +\n                  ': ' + err.message;\n            })\n            .then(null, deferred.reject);\n      }\n\n      self.executeScript_(\n          'angular.resumeBootstrap(arguments[0]);',\n          msg('resume bootstrap'),\n          moduleNames)\n          .then(null, deferred.reject);\n    } else {\n      // TODO: support mock modules in Angular2. For now, error if someone\n      // has tried to use one.\n      if (self.mockModules_.length > 1) {\n        deferred.reject('Trying to load mock modules on an Angular2 app ' +\n            'is not yet supported.');\n      }\n    }\n  }\n\n  this.driver.controlFlow().execute(function() {\n    return self.plugins_.onPageStable().then(function() {\n      deferred.fulfill();\n    }, function(error) {\n      deferred.reject(error);\n    });\n  });\n\n  return deferred.promise;\n};\n\n/**\n * @see webdriver.WebDriver.refresh\n *\n * Makes a full reload of the current page and loads mock modules before\n * Angular. Assumes that the page being loaded uses Angular.\n * If you need to access a page which does not have Angular on load, use\n * the wrapped webdriver directly.\n *\n * @param {number=} opt_timeout Number of milliseconds to wait for Angular to start.\n */\nProtractor.prototype.refresh = function(opt_timeout) {\n  var self = this;\n\n  if (self.ignoreSynchronization) {\n    return self.driver.navigate().refresh();\n  }\n\n  return self.executeScript_(\n      'return window.location.href',\n      'Protractor.refresh() - getUrl').then(function(href) {\n        return self.get(href, opt_timeout);\n      });\n};\n\n/**\n * Mixin navigation methods back into the navigation object so that\n * they are invoked as before, i.e. driver.navigate().refresh()\n */\nProtractor.prototype.navigate = function() {\n  var nav = this.driver.navigate();\n  mixin(nav, this, 'refresh');\n  return nav;\n};\n\n/**\n * Browse to another page using in-page navigation.\n *\n * @example\n * browser.get('http://angular.github.io/protractor/#/tutorial');\n * browser.setLocation('api');\n * expect(browser.getCurrentUrl())\n *     .toBe('http://angular.github.io/protractor/#/api');\n *\n * @param {string} url In page URL using the same syntax as $location.url()\n * @return {!webdriver.promise.Promise} A promise that will resolve once\n *    page has been changed.\n */\nProtractor.prototype.setLocation = function(url) {\n  this.waitForAngular();\n  return this.executeScript_(clientSideScripts.setLocation,\n    'Protractor.setLocation()', this.rootEl, url).then(function(browserErr) {\n      if (browserErr) {\n        throw 'Error while navigating to \\'' + url + '\\' : ' +\n            JSON.stringify(browserErr);\n      }\n    });\n};\n\n/**\n * Returns the current absolute url from AngularJS.\n *\n * @example\n * browser.get('http://angular.github.io/protractor/#/api');\n * expect(browser.getLocationAbsUrl())\n *     .toBe('http://angular.github.io/protractor/#/api');\n */\nProtractor.prototype.getLocationAbsUrl = function() {\n  this.waitForAngular();\n  return this.executeScript_(clientSideScripts.getLocationAbsUrl,\n      'Protractor.getLocationAbsUrl()', this.rootEl);\n};\n\n/**\n * Adds a task to the control flow to pause the test and inject helper functions\n * into the browser, so that debugging may be done in the browser console.\n *\n * This should be used under node in debug mode, i.e. with\n * protractor debug <configuration.js>\n *\n * @example\n * While in the debugger, commands can be scheduled through webdriver by\n * entering the repl:\n *   debug> repl\n *   Press Ctrl + C to leave rdebug repl\n *   > ptor.findElement(protractor.By.input('user').sendKeys('Laura'));\n *   > ptor.debugger();\n *   debug> c\n *\n * This will run the sendKeys command as the next task, then re-enter the\n * debugger.\n */\nProtractor.prototype.debugger = function() {\n  // jshint debug: true\n  this.driver.executeScript(clientSideScripts.installInBrowser);\n  webdriver.promise.controlFlow().execute(function() { debugger; },\n                                          'add breakpoint to control flow');\n};\n\n/**\n * Helper function to:\n *  1) Set up helper functions for debugger clients to call on (e.g.\n *     getControlFlowText, execute code, get autocompletion).\n *  2) Enter process into debugger mode. (i.e. process._debugProcess).\n *  3) Invoke the debugger client specified by debuggerClientPath.\n *\n * @param {string=} debuggerClientPath Absolute path of debugger client to use\n * @param {number=} opt_debugPort Optional port to use for the debugging process\n */\nProtractor.prototype.initDebugger_ = function(debuggerClientPath, opt_debugPort) {\n  // Patch in a function to help us visualize what's going on in the control\n  // flow.\n  webdriver.promise.ControlFlow.prototype.getControlFlowText = function() {\n    var controlFlowText = this.getSchedule(/* opt_includeStackTraces */ true);\n    // This filters the entire control flow text, not just the stack trace, so\n    // unless we maintain a good (i.e. non-generic) set of keywords in\n    // STACK_SUBSTRINGS_TO_FILTER, we run the risk of filtering out non stack\n    // trace. The alternative though, which is to reimplement\n    // webdriver.promise.ControlFlow.prototype.getSchedule() here is much\n    // hackier, and involves messing with the control flow's internals / private\n    // variables.\n    return helper.filterStackTrace(controlFlowText);\n\n  };\n\n  // Invoke fn if port is available.\n  var onPortAvailable = function(port, fn) {\n    var net = require('net');\n    var tester = net.connect({port: port}, function() {\n      console.error('Port ' + port + ' is already in use. Please specify ' + \n        'another port to debug.');\n      process.exit(1);\n    });\n    tester.once('error', function (err) {\n      if (err.code === 'ECONNREFUSED') {\n        tester.once('close', fn).end();\n      } else {\n        console.error('Unexpected failure testing for port ' + port + ': ', \n          err);\n        process.exit(1);\n      }\n    });\n  };\n\n  var vm_ = require('vm');\n  var flow = webdriver.promise.controlFlow();\n\n  var context = { require: require };\n  global.list = function(locator) {\n    /* globals browser */\n    return browser.findElements(locator).then(function(arr) {\n      var found = [];\n      for (var i = 0; i < arr.length; ++i) {\n        arr[i].getText().then(function(text) {\n          found.push(text);\n        });\n      }\n      return found;\n    });\n  };\n  for (var key in global) {\n    context[key] = global[key];\n  }\n  var sandbox = vm_.createContext(context);\n\n  var browserUnderDebug = this;\n  var debuggerReadyPromise = webdriver.promise.defer();\n  flow.execute(function() {   \n    log.puts('Starting WebDriver debugger in a child process. Pause is ' +\n        'still beta, please report issues at github.com/angular/protractor\\n');\n    process.debugPort = opt_debugPort || process.debugPort;\n    onPortAvailable(process.debugPort, function() {\n      var args = [process.pid, process.debugPort];\n      if (browserUnderDebug.debuggerServerPort_) {\n        args.push(browserUnderDebug.debuggerServerPort_);\n      }\n      var nodedebug = require('child_process').fork(debuggerClientPath, args);\n      process.on('exit', function() {\n        nodedebug.kill('SIGTERM');\n      });\n      nodedebug.on('message', function(m) {\n        if (m === 'ready') {\n          debuggerReadyPromise.fulfill();\n        }\n      });\n    });\n  });\n\n  var pausePromise = flow.execute(function() {\n    return debuggerReadyPromise.then(function() {\n      // Necessary for backward compatibility with node < 0.12.0\n      return browserUnderDebug.executeScript_('', 'empty debugger hook');\n    });\n  });\n\n  // Helper used only by debuggers at './debugger/modes/*.js' to insert code\n  // into the control flow.\n  // In order to achieve this, we maintain a promise at the top of the control\n  // flow, so that we can insert frames into it.\n  // To be able to simulate callback/asynchronous code, we poll this object\n  // for an result at every run of DeferredExecutor.execute.\n  this.dbgCodeExecutor_ = {\n    execPromise_: pausePromise, // Promise pointing to current stage of flow.\n    execPromiseResult_: undefined, // Return value of promise.\n    execPromiseError_: undefined, // Error from promise.\n\n    // A dummy repl server to make use of its completion function.\n    replServer_: require('repl').start({\n      input: {on: function() {}, resume: function() {}}, // dummy readable stream\n      output: {write: function() {}}, // dummy writable stream\n      useGlobal: true\n    }),\n\n    // Execute a function, which could yield a value or a promise,\n    // and allow its result to be accessed synchronously\n    execute_: function(execFn_) {\n      var self = this;\n      self.execPromiseResult_ = self.execPromiseError_ = undefined;\n\n      self.execPromise_ = self.execPromise_.\n          then(execFn_).then(function(result) {\n            self.execPromiseResult_ = result;\n          }, function(err) {\n            self.execPromiseError_ = err;\n          });\n\n      // This dummy command is necessary so that the DeferredExecutor.execute\n      // break point can find something to stop at instead of moving on to the\n      // next real command.\n      self.execPromise_.then(function() {\n        return browserUnderDebug.executeScript_('', 'empty debugger hook');\n      });\n    },\n\n    // Execute a piece of code.\n    // Result is a string representation of the evaluation.\n    execute: function(code) {\n      var execFn_ = function() {\n        // Run code through vm so that we can maintain a local scope which is\n        // isolated from the rest of the execution.\n        var res = vm_.runInContext(code, sandbox);\n        if (!webdriver.promise.isPromise(res)) {\n          res = webdriver.promise.fulfilled(res);\n        }\n\n        return res.then(function(res) {\n          if (res === undefined) {\n            return undefined;\n          } else {\n            // The '' forces res to be expanded into a string instead of just\n            // '[Object]'. Then we remove the extra space caused by the '' using\n            // substring.\n            return util.format.apply(this, ['', res]).substring(1);\n          }\n        });\n      };\n      this.execute_(execFn_);\n    },\n\n    // Autocomplete for a line.\n    // Result is a JSON representation of the autocomplete response.\n    complete: function(line) {\n      var self = this;\n      var execFn_ = function() {\n        var deferred = webdriver.promise.defer();\n        self.replServer_.complete(line, function(err, res) {\n          if (err) {\n            deferred.reject(err);\n          } else {\n            deferred.fulfill(JSON.stringify(res));\n          }\n        });\n        return deferred;\n      };\n      this.execute_(execFn_);\n    },\n\n    // Code finished executing.\n    resultReady: function() {\n      return !this.execPromise_.isPending();\n    },\n\n    // Get asynchronous results synchronously.\n    // This will throw if result is not ready.\n    getResult: function() {\n      if (!this.resultReady()) {\n        throw new Error('Result not ready');\n      }\n      if (this.execPromiseError_) {\n        throw this.execPromiseError_;\n      }\n      return this.execPromiseResult_;\n    }\n  };\n};\n\n/**\n * Beta (unstable) enterRepl function for entering the repl loop from\n * any point in the control flow. Use browser.enterRepl() in your test.\n * Does not require changes to the command line (no need to add 'debug').\n * Note, if you are wrapping your own instance of Protractor, you must\n * expose globals 'browser' and 'protractor' for pause to work.\n *\n * @example\n * element(by.id('foo')).click();\n * browser.enterRepl();\n * // Execution will stop before the next click action.\n * element(by.id('bar')).click();\n *\n * @param {number=} opt_debugPort Optional port to use for the debugging process\n */\nProtractor.prototype.enterRepl = function(opt_debugPort) {\n  var debuggerClientPath = __dirname + '/debugger/clients/explorer.js';\n  this.initDebugger_(debuggerClientPath, opt_debugPort);\n};\n\n/**\n * Beta (unstable) pause function for debugging webdriver tests. Use\n * browser.pause() in your test to enter the protractor debugger from that\n * point in the control flow.\n * Does not require changes to the command line (no need to add 'debug').\n * Note, if you are wrapping your own instance of Protractor, you must\n * expose globals 'browser' and 'protractor' for pause to work.\n *\n * @example\n * element(by.id('foo')).click();\n * browser.pause();\n * // Execution will stop before the next click action.\n * element(by.id('bar')).click();\n *\n * @param {number=} opt_debugPort Optional port to use for the debugging process\n */\nProtractor.prototype.pause = function(opt_debugPort) {\n  var debuggerClientPath = __dirname + '/debugger/clients/wddebugger.js';\n  this.initDebugger_(debuggerClientPath, opt_debugPort);\n};\n\n/**\n * Create a new instance of Protractor by wrapping a webdriver instance.\n *\n * @param {webdriver.WebDriver} webdriver The configured webdriver instance.\n * @param {string=} opt_baseUrl A URL to prepend to relative gets.\n * @return {Protractor}\n */\nexports.wrapDriver = function(webdriver, opt_baseUrl, opt_rootElement) {\n  return new Protractor(webdriver, opt_baseUrl, opt_rootElement);\n};\n"]}