From 701945121043cc0616afad04e8f3d4d37da6299f Mon Sep 17 00:00:00 2001 From: Jason Leyba Date: Wed, 20 Aug 2014 21:09:18 -0700 Subject: [PATCH] * Add more options to the Builder API (every common, settable capability should be covered). * Require calling Builder.usingServer(url) to use a remote server. If this is not called, the builder will attempt to create a client locally, throwing an error if it can't (e.g. for IE). * Add browser specific constructors to simplify creating a client without the Builder. Fixes issue 7593 --- javascript/node/selenium-webdriver/CHANGES.md | 18 +- javascript/node/selenium-webdriver/builder.js | 272 ++++++++++++++---- javascript/node/selenium-webdriver/chrome.js | 45 ++- .../node/selenium-webdriver/lib/test/index.js | 6 +- .../node/selenium-webdriver/phantomjs.js | 30 +- javascript/node/selenium-webdriver/proxy.js | 23 +- .../test/chrome/options_test.js | 6 +- .../selenium-webdriver/test/logging_test.js | 10 +- javascript/remote/deps.js | 3 +- javascript/webdriver/capabilities.js | 93 +++++- 10 files changed, 399 insertions(+), 107 deletions(-) diff --git a/javascript/node/selenium-webdriver/CHANGES.md b/javascript/node/selenium-webdriver/CHANGES.md index c9fe1e0d72b12..899703b7095a0 100644 --- a/javascript/node/selenium-webdriver/CHANGES.md +++ b/javascript/node/selenium-webdriver/CHANGES.md @@ -4,7 +4,23 @@ `ControlFlow#wait`. For more information, see documentation on `webdriver.promise.consume`. Requires harmony support (run with `node --harmony-generators` in `v0.11.x`). -* Added `Builder#setLoggingPreferences()` +* Various improvements to the `Builder` API. Notably, the `build()` function + will no longer default to attempting to use a server at + `http://localhost:4444/wd/hub` if it cannot start a browser directly - + you must specify the WebDriver server with `usingServer(url)`. You can + also set the target browser and WebDriver server through a pair of + environment variables. See the documentation on the `Builder` constructor + for more information. +* For consistency with the other language bindings, added browser specific + classes that can be used to start a browser without the builder. + + var webdriver = require('selenium-webdriver') + chrome = require('selenium-webdriver/chrome'); + + // The following are equivalent. + var driver1 = new webdriver.Builder().forBrowser('chrome').build(); + var driver2 = new chrome.Driver(); + * Promise A+ compliance: a promise may no longer resolve to itself. * For consistency with other language bindings, deprecated `UnhandledAlertError#getAlert` and added `#getAlertText`. diff --git a/javascript/node/selenium-webdriver/builder.js b/javascript/node/selenium-webdriver/builder.js index f1e5dd56a5959..9fa3850f8947c 100644 --- a/javascript/node/selenium-webdriver/builder.js +++ b/javascript/node/selenium-webdriver/builder.js @@ -15,77 +15,206 @@ var base = require('./_base'), executors = require('./executors'); -var goog = base.require('goog'), - AbstractBuilder = base.require('webdriver.AbstractBuilder'), - Browser = base.require('webdriver.Browser'), +// Use base.require to avoid circular references between index and this module. +var Browser = base.require('webdriver.Browser'), + Capabilities = base.require('webdriver.Capabilities'), Capability = base.require('webdriver.Capability'), WebDriver = base.require('webdriver.WebDriver'), promise = base.require('webdriver.promise'); + /** - * @param {!webdriver.Capabilities} capabilities The desired capabilities. - * @param {webdriver.promise.ControlFlow} flow The control flow to use, or - * {@code null} to use the currently active flow. - * @return {webdriver.WebDriver} A new WebDriver instance or {@code null} - * if the requested browser is not natively supported in Node. + * Creates new {@link webdriver.WebDriver WebDriver} instances. The environment + * variables listed below may be used to override a builder's configuration, + * allowing quick runtime changes. + * + * + *

Suppose you had mytest.js that created WebDriver with + * {@code var driver = new webdriver.Builder().build();}. + * + * This test could be made to use Firefox on the local machine by running with + * {@code SELENIUM_BROWSER=firefox node mytest.js}. + * + *

Alternatively, you could request Chrome 36 on Linux from a remote + * server with {@code + * SELENIUM_BROWSER=chrome:36:LINUX + * SELENIUM_REMOTE_URL=http://www.example.com:4444/wd/hub + * node mytest.js}. + * + * @constructor */ -function createNativeDriver(capabilities, flow) { - switch (capabilities.get(Capability.BROWSER_NAME)) { - case Browser.CHROME: - // Requiring 'chrome' above would create a cycle: - // index -> builder -> chrome -> index - var chrome = require('./chrome'); - return chrome.createDriver(capabilities, null, flow); +var Builder = function() { - case Browser.PHANTOM_JS: - // Requiring 'phantomjs' would create a cycle: - // index -> builder -> phantomjs -> index - var phantomjs = require('./phantomjs'); - return phantomjs.createDriver(capabilities, flow); + /** @private {webdriver.promise.ControlFlow} */ + this.flow_ = null; - default: - return null; - } -} + /** @private {string} */ + this.url_ = ''; + + /** @private {!webdriver.Capabilities} */ + this.capabilities_ = new Capabilities(); + /** @private {chrome.Options} */ + this.chromeOptions_ = null; +}; /** - * Creates new {@link webdriver.WebDriver WebDriver} instances. - * @constructor - * @extends {webdriver.AbstractBuilder} + * Sets the URL of a remote WebDriver server to use. Once a remote URL has been + * specified, the builder direct all new clients to that server. If this method + * is never called, the Builder will attempt to create all clients locally. + * + *

As an alternative to this method, you may also set the + * {@code SELENIUM_REMOTE_URL} environment variable. + * + * @param {string} url The URL of a remote server to use. + * @return {!Builder} A self reference. */ -var Builder = function() { - goog.base(this); +Builder.prototype.usingServer = function(url) { + this.url_ = url; + return url; +}; - /** @private {webdriver.promise.ControlFlow} */ - this.flow_ = null; + +/** + * @return {string} The URL of the WebDriver server this instance is configured + * to use. + */ +Builder.prototype.getServerUrl = function() { + return this.url_; +}; + + +/** + * Sets the desired capabilities when requesting a new session. This will + * overwrite any previously set capabilities. + * @param {!(Object|webdriver.Capabilities)} capabilities The desired + * capabilities for a new session. + * @return {!Builder} A self reference. + */ +Builder.prototype.withCapabilities = function(capabilities) { + this.capabilities_ = new Capabilities(capabilities); + return this; +}; + + +/** + * Returns the base set of capabilities this instance is currently configured + * to use. + * @return {!webdriver.Capabilities} The current capabilities for this builder. + */ +Builder.prototype.getCapabilities = function() { + return this.capabilities_; +}; + + +/** + * Configures the target browser for clients created by this instance. + * Any calls to {@link #withCapabilities} after this function will + * overwrite these settings. + * + *

You may also define the target browser using the {@code SELENIUM_BROWSER} + * environment variable. If set, this environment variable should be of the + * form {@code browser[:[version][:platform]]}. + * + * @param {(string|webdriver.Browser)} name The name of the target browser; + * common defaults are available on the {@link webdriver.Browser} enum. + * @param {string=} opt_version A desired version; may be omitted if any + * version should be used. + * @param {string=} opt_platform The desired platform; may be omitted if any + * version may be used. + * @return {!Builder} A self reference. + */ +Builder.prototype.forBrowser = function(name, opt_version, opt_platform) { + this.capabilities_.set(Capability.BROWSER_NAME, name); + this.capabilities_.set(Capability.VERSION, opt_version || null); + this.capabilities_.set(Capability.PLATFORM, opt_platform || null); + return this; }; -goog.inherits(Builder, AbstractBuilder); /** * Sets the proxy configuration to use for WebDriver clients created by this * builder. Any calls to {@link #withCapabilities} after this function will * overwrite these settings. - * @param {!proxy.ProxyConfig} config The configuration to use. + * @param {!webdriver.ProxyConfig} config The configuration to use. * @return {!Builder} A self reference. */ Builder.prototype.setProxy = function(config) { - this.getCapabilities().set(Capability.PROXY, config); + this.capabilities_.setProxy(config); + return this; +}; + + +/** + * Sets the logging preferences for the created session. Preferences may be + * changed by repeated calls, or by calling {@link #withCapabilities}. + * @param {!(webdriver.logging.Preferences|Object.)} prefs The + * desired logging preferences. + * @return {!Builder} A self reference. + */ +Builder.prototype.setLoggingPrefs = function(prefs) { + this.capabilities_.setLoggingPrefs(prefs); + return this; +}; + + +/** + * Sets whether native events should be used. + * @param {boolean} enabled Whether to enable native events. + * @return {!Builder} A self reference. + */ +Builder.prototype.setEnableNativeEvents = function(enabled) { + this.capabilities_.setEnableNativeEvents(enabled); + return this; +}; + + +/** + * Sets how elements should be scrolled into view for interaction. + * @param {number} behavior The desired scroll behavior: either 0 to align with + * the top of the viewport or 1 to align with the bottom. + * @return {!Builder} A self reference. + */ +Builder.prototype.setScrollBehavior = function(behavior) { + this.capabilities_.setScrollBehavior(behavior); + return this; +}; + + +/** + * Sets the default action to take with an unexpected alert before returning + * an error. + * @param {string} beahvior The desired behavior; should be "accept", "dismiss", + * or "ignore". Defaults to "dismiss". + * @return {!Builder} A self reference. + */ +Builder.prototype.setAlertBehavior = function(behavior) { + this.capabilities_.setAlertBehavior(behavior); return this; }; /** - * Sets Chrome-specific options for drivers created by this builder. + * Sets Chrome-specific options for drivers created by this builder. Any + * logging or proxy settings defined on the given options will take precedence + * over those set through {@link #setLoggingPrefs} and {@link #setProxy}, + * respectively. + * * @param {!chrome.Options} options The ChromeDriver options to use. * @return {!Builder} A self reference. */ Builder.prototype.setChromeOptions = function(options) { - var newCapabilities = options.toCapabilities(this.getCapabilities()); - return /** @type {!Builder} */(this.withCapabilities(newCapabilities)); + this.chromeOptions_ = options; + return this; }; @@ -94,7 +223,7 @@ Builder.prototype.setChromeOptions = function(options) { * the flow is never set, or is set to {@code null}, it will use the active * flow at the time {@link #build()} is called. * @param {webdriver.promise.ControlFlow} flow The control flow to use, or - * {@code null} to + * {@code null} to * @return {!Builder} A self reference. */ Builder.prototype.setControlFlow = function(flow) { @@ -104,25 +233,62 @@ Builder.prototype.setControlFlow = function(flow) { /** - * @override + * Creates a new WebDriver client based on this builder's current + * configuration. + * + * @return {!webdriver.WebDriver} A new WebDriver instance. + * @throws {Error} If the current configuration is invalid. */ Builder.prototype.build = function() { - var url = this.getServerUrl(); - - // If a remote server wasn't specified, check for browsers we support - // natively in node before falling back to using the java Selenium server. - if (!url) { - var driver = createNativeDriver(this.getCapabilities(), this.flow_); - if (driver) { - return driver; - } - - // Nope, fall-back to using the default java server. - url = AbstractBuilder.DEFAULT_SERVER_URL; + // Create a copy for any changes we may need to make based on the current + // environment. + var capabilities = new Capabilities(this.capabilities_); + + var browser = process.env.SELENIUM_BROWSER; + if (browser) { + browser = browser.split(/:/, 3); + capabilities.set(Capability.BROWSER_NAME, browser[0]); + capabilities.set(Capability.VERSION, browser[1] || null); + capabilities.set(Capability.PLATFORM, browser[2] || null); + } + + browser = capabilities.get(Capability.BROWSER_NAME); + + if (!browser) { + throw Error( + 'Target browser not defined; did you forget to call forBrowser()?'); + } + + // Apply browser specific overrides. + if (browser === Browser.CHROME && this.chromeOptions_) { + capabilities.merge(this.chromeOptions_.toCapabilities()); + } + + // Check for a remote browser. + var url = process.env.SELENIUM_REMOTE_URL || this.url_; + if (url) { + var executor = executors.createExecutor(url); + return WebDriver.createSession(executor, capabilities, this.flow_); } - var executor = executors.createExecutor(url); - return WebDriver.createSession(executor, this.getCapabilities(), this.flow_); + // Check for a native browser. + switch (browser) { + case Browser.CHROME: + // Requiring 'chrome' above would create a cycle: + // index -> builder -> chrome -> index + var chrome = require('./chrome'); + return new chrome.Driver(capabilities, null, this.flow_); + + case Browser.PHANTOM_JS: + // Requiring 'phantomjs' would create a cycle: + // index -> builder -> phantomjs -> index + var phantomjs = require('./phantomjs'); + return new phantomjs.Driver(capabilities, this.flow_); + + default: + throw new Error('Do not know how to build driver: ' + browser + + '; did you forget to call usingServer(url)?'); + } }; diff --git a/javascript/node/selenium-webdriver/chrome.js b/javascript/node/selenium-webdriver/chrome.js index a790763e464dc..6a6a7de3d2b73 100644 --- a/javascript/node/selenium-webdriver/chrome.js +++ b/javascript/node/selenium-webdriver/chrome.js @@ -267,7 +267,7 @@ Options.fromCapabilities = function(capabilities) { } if (capabilities.has(webdriver.Capability.LOGGING_PREFS)) { - options.setLoggingPreferences( + options.setLoggingPrefs( capabilities.get(webdriver.Capability.LOGGING_PREFS)); } @@ -352,7 +352,7 @@ Options.prototype.setUserPreferences = function(prefs) { * @param {!webdriver.logging.Preferences} prefs The logging preferences. * @return {!Options} A self reference. */ -Options.prototype.setLoggingPreferences = function(prefs) { +Options.prototype.setLoggingPrefs = function(prefs) { this.logPrefs_ = prefs; return this; }; @@ -384,7 +384,7 @@ Options.prototype.setChromeLogFile = function(path) { /** * Sets the proxy settings for the new session. - * @param {ProxyConfig} proxy The proxy configuration to use. + * @param {webdriver.ProxyConfig} proxy The proxy configuration to use. * @return {!Options} A self reference. */ Options.prototype.setProxy = function(proxy) { @@ -447,29 +447,48 @@ Options.prototype.toJSON = function() { * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or * {@code null} to use the currently active flow. * @return {!webdriver.WebDriver} A new WebDriver instance. + * @deprecated Use {@link Driver new Driver()}. */ function createDriver(opt_options, opt_service, opt_flow) { + return new Driver(opt_options, opt_service, opt_flow); +} + + +/** + * Creates a new WebDriver client for Chrome. + * + * @param {(webdriver.Capabilities|Options)=} opt_config The configuration + * options. + * @param {remote.DriverService=} opt_service The session to use; will use + * the {@link getDefaultService default service} by default. + * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or + * {@code null} to use the currently active flow. + * @constructor + * @extends {webdriver.WebDriver} + */ +var Driver = function(opt_config, opt_service, opt_flow) { var service = opt_service || getDefaultService(); var executor = executors.createExecutor(service.start()); - var options = opt_options || new Options(); - if (opt_options instanceof webdriver.Capabilities) { - // Extract the Chrome-specific options so we do not send unnecessary - // data across the wire. - options = Options.fromCapabilities(options); - } + var capabilities = + opt_config instanceof Options ? opt_config.toCapabilities() : + (opt_config || webdriver.Capabilities.chrome()); - return webdriver.WebDriver.createSession( - executor, options.toCapabilities(), opt_flow); -} + var driver = webdriver.WebDriver.createSession( + executor, capabilities, opt_flow); + webdriver.WebDriver.call( + this, driver.getSession(), executor, driver.controlFlow()); +}; +util.inherits(Driver, webdriver.WebDriver); // PUBLIC API -exports.ServiceBuilder = ServiceBuilder; +exports.Driver = Driver; exports.Options = Options; +exports.ServiceBuilder = ServiceBuilder; exports.createDriver = createDriver; exports.getDefaultService = getDefaultService; exports.setDefaultService = setDefaultService; diff --git a/javascript/node/selenium-webdriver/lib/test/index.js b/javascript/node/selenium-webdriver/lib/test/index.js index 041f8bfda7e6c..500c777515682 100644 --- a/javascript/node/selenium-webdriver/lib/test/index.js +++ b/javascript/node/selenium-webdriver/lib/test/index.js @@ -54,7 +54,7 @@ var NATIVE_BROWSERS = [ var browsersToTest = (function() { - var browsers = process.env['SELENIUM_BROWSER'] || Browser.CHROME; + var browsers = process.env['SELENIUM_BROWSERS'] || Browser.CHROME; browsers = browsers.split(','); browsers.forEach(function(browser) { if (browser === Browser.IOS) { @@ -110,6 +110,10 @@ function TestEnvironment(browserName, server) { var driver; this.__defineGetter__('driver', function() { return driver; }); + this.__defineSetter__('driver', function(d) { + if (driver) throw Error('Driver already created'); + driver = d; + }); this.browsers = function(var_args) { var browsersToIgnore = Array.prototype.slice.apply(arguments, [0]); diff --git a/javascript/node/selenium-webdriver/phantomjs.js b/javascript/node/selenium-webdriver/phantomjs.js index 8be9b561c1e26..a81a3172c098c 100644 --- a/javascript/node/selenium-webdriver/phantomjs.js +++ b/javascript/node/selenium-webdriver/phantomjs.js @@ -104,8 +104,23 @@ var WEBDRIVER_TO_PHANTOMJS_LEVEL = (function() { * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or * {@code null} to use the currently active flow. * @return {!webdriver.WebDriver} A new WebDriver instance. + * @deprecated Use {@link Driver}. */ function createDriver(opt_capabilities, opt_flow) { + return new Driver(opt_capabilities, opt_flow); +} + + +/** + * Creates a new WebDriver client for PhantomJS. + * + * @param {webdriver.Capabilities=} opt_capabilities The desired capabilities. + * @param {webdriver.promise.ControlFlow=} opt_flow The control flow to use, or + * {@code null} to use the currently active flow. + * @constructor + * @extends {webdriver.WebDriver} + */ +var Driver = function(opt_capabilities, opt_flow) { var capabilities = opt_capabilities || webdriver.Capabilities.phantomjs(); var exe = findExecutable(capabilities.get(BINARY_PATH_CAPABILITY)); var args = ['--webdriver-logfile=' + DEFAULT_LOG_FILE]; @@ -157,15 +172,22 @@ function createDriver(opt_capabilities, opt_flow) { var executor = executors.createExecutor(service.start()); var driver = webdriver.WebDriver.createSession( executor, capabilities, opt_flow); - var boundQuit = driver.quit.bind(driver); - driver.quit = function() { + + webdriver.WebDriver.call( + this, driver.getSession(), executor, driver.controlFlow()); + + var boundQuit = this.quit.bind(this); + + /** @override */ + this.quit = function() { return boundQuit().thenFinally(service.kill.bind(service)); }; return driver; -} +}; +util.inherits(Driver, webdriver.WebDriver); // PUBLIC API - +exports.Driver = Driver; exports.createDriver = createDriver; diff --git a/javascript/node/selenium-webdriver/proxy.js b/javascript/node/selenium-webdriver/proxy.js index 0341346e3b8f1..131d947841b0d 100644 --- a/javascript/node/selenium-webdriver/proxy.js +++ b/javascript/node/selenium-webdriver/proxy.js @@ -30,28 +30,13 @@ var util = require('util'); -/** - * Proxy configuration object, as defined by the WebDriver wire protocol. - * @typedef {( - * {proxyType: string}| - * {proxyType: string, - * proxyAutoconfigUrl: string}| - * {proxyType: string, - * ftpProxy: string, - * httpProxy: string, - * sslProxy: string, - * noProxy: string})} - */ -var ProxyConfig; - - // PUBLIC API /** * Configures WebDriver to bypass all browser proxies. - * @return {!ProxyConfig} A new proxy configuration object. + * @return {!webdriver.ProxyConfig} A new proxy configuration object. */ exports.direct = function() { return {proxyType: 'direct'}; @@ -78,7 +63,7 @@ exports.direct = function() { * https: (string|undefined), * bypass: (string|!Array.|undefined)}} options Proxy * configuration options. - * @return {!ProxyConfig} A new proxy configuration object. + * @return {!webdriver.ProxyConfig} A new proxy configuration object. */ exports.manual = function(options) { return { @@ -96,7 +81,7 @@ exports.manual = function(options) { * Configures WebDriver to configure the browser proxy using the PAC file at * the given URL. * @param {string} url URL for the PAC proxy to use. - * @return {!ProxyConfig} A new proxy configuration object. + * @return {!webdriver.ProxyConfig} A new proxy configuration object. */ exports.pac = function(url) { return { @@ -108,7 +93,7 @@ exports.pac = function(url) { /** * Configures WebDriver to use the current system's proxy. - * @return {!ProxyConfig} A new proxy configuration object. + * @return {!webdriver.ProxyConfig} A new proxy configuration object. */ exports.system = function() { return {proxyType: 'system'}; diff --git a/javascript/node/selenium-webdriver/test/chrome/options_test.js b/javascript/node/selenium-webdriver/test/chrome/options_test.js index 2398ddf4df8e1..0a372c35c472e 100644 --- a/javascript/node/selenium-webdriver/test/chrome/options_test.js +++ b/javascript/node/selenium-webdriver/test/chrome/options_test.js @@ -181,7 +181,7 @@ describe('chrome.Options', function() { var proxyPrefs = {}; var loggingPrefs = {}; var options = new chrome.Options(). - setLoggingPreferences(loggingPrefs). + setLoggingPrefs(loggingPrefs). setProxy(proxyPrefs); var caps = options.toCapabilities(); @@ -199,9 +199,7 @@ test.suite(function(env) { var options = new chrome.Options(). addArguments('user-agent=foo;bar'); - var driver = env.builder(). - setChromeOptions(options). - build(); + var driver = env.driver = new chrome.Driver(options); driver.get(test.Pages.ajaxyPage); diff --git a/javascript/node/selenium-webdriver/test/logging_test.js b/javascript/node/selenium-webdriver/test/logging_test.js index 484149bbfb085..154bfe578f8c9 100644 --- a/javascript/node/selenium-webdriver/test/logging_test.js +++ b/javascript/node/selenium-webdriver/test/logging_test.js @@ -38,7 +38,7 @@ test.suite(function(env) { prefs.setLevel(logging.Type.BROWSER, logging.Level.OFF); var driver = env.builder() - .setLoggingPreferences(prefs) + .setLoggingPrefs(prefs) .build(); driver.get(dataUrl( @@ -59,7 +59,7 @@ test.suite(function(env) { prefs.setLevel(logging.Type.BROWSER, logging.Level.SEVERE); var driver = env.builder() - .setLoggingPreferences(prefs) + .setLoggingPrefs(prefs) .build(); driver.get(dataUrl( @@ -82,7 +82,7 @@ test.suite(function(env) { prefs.setLevel(logging.Type.BROWSER, logging.Level.DEBUG); var driver = env.builder() - .setLoggingPreferences(prefs) + .setLoggingPrefs(prefs) .build(); driver.get(dataUrl( @@ -111,7 +111,7 @@ test.suite(function(env) { prefs.setLevel(logging.Type.BROWSER, logging.Level.DEBUG); var driver = env.builder() - .setLoggingPreferences(prefs) + .setLoggingPrefs(prefs) .build(); driver.get(dataUrl( @@ -134,7 +134,7 @@ test.suite(function(env) { prefs.setLevel(logging.Type.DRIVER, logging.Level.SEVERE); var driver = env.builder() - .setLoggingPreferences(prefs) + .setLoggingPrefs(prefs) .build(); driver.get(dataUrl( diff --git a/javascript/remote/deps.js b/javascript/remote/deps.js index be09f02a16ce4..fd192696d7728 100644 --- a/javascript/remote/deps.js +++ b/javascript/remote/deps.js @@ -30,7 +30,8 @@ goog.addDependency( [ 'goog.debug.ErrorHandler', 'goog.events.EventWrapper', - 'goog.testing.JsUnitException' + 'goog.testing.JsUnitException', + 'webdriver.logging.Preferences' ], // And symbols we require, which is always empty here. []); diff --git a/javascript/webdriver/capabilities.js b/javascript/webdriver/capabilities.js index 783322a78e395..d55cc61032325 100644 --- a/javascript/webdriver/capabilities.js +++ b/javascript/webdriver/capabilities.js @@ -19,6 +19,7 @@ goog.provide('webdriver.Browser'); goog.provide('webdriver.Capabilities'); goog.provide('webdriver.Capability'); +goog.provide('webdriver.ProxyConfig'); @@ -41,6 +42,23 @@ webdriver.Browser = { +/** + * Describes how a proxy should be configured for a WebDriver session. + * Proxy configuration object, as defined by the WebDriver wire protocol. + * @typedef {( + * {proxyType: string}| + * {proxyType: string, + * proxyAutoconfigUrl: string}| + * {proxyType: string, + * ftpProxy: string, + * httpProxy: string, + * sslProxy: string, + * noProxy: string})} + */ +webdriver.ProxyConfig; + + + /** * Common webdriver capability keys. * @enum {string} @@ -62,6 +80,14 @@ webdriver.Capability = { */ BROWSER_NAME: 'browserName', + /** + * Defines how elements should be scrolled into the viewport for interaction. + * This capability will be set to zero (0) if elements are aligned with the + * top of the viewport, or one (1) if aligned with the bottom. The default + * behavior is to align with the top of the viewport. + */ + ELEMENT_SCROLL_BEHAVIOR: 'elementScrollBehavior', + /** * Whether the driver is capable of handling modal alerts (e.g. alert, * confirm, prompt). To define how a driver should handle alerts, @@ -74,6 +100,11 @@ webdriver.Capability = { */ LOGGING_PREFS: 'loggingPrefs', + /** + * Whether this session generates native events when simulating user input. + */ + NATIVE_EVENTS: 'nativeEvents', + /** * Describes the platform the browser is running on. Will be one of * ANDROID, IOS, LINUX, MAC, UNIX, or WINDOWS. When requesting a @@ -100,12 +131,6 @@ webdriver.Capability = { /** Whether the driver supports manipulating the app cache. */ SUPPORTS_APPLICATION_CACHE: 'applicationCacheEnabled', - /** - * Whether the driver supports controlling the browser's internet - * connectivity. - */ - SUPPORTS_BROWSER_CONNECTION: 'browserConnectionEnabled', - /** Whether the driver supports locating elements with CSS selectors. */ SUPPORTS_CSS_SELECTORS: 'cssSelectorsEnabled', @@ -316,3 +341,59 @@ webdriver.Capabilities.prototype.get = function(key) { webdriver.Capabilities.prototype.has = function(key) { return !!this.get(key); }; + + +/** + * Sets the logging preferences. Preferences may be specified as a + * {@link webdriver.logging.Preferences} instance, or a as a map of log-type to + * log-level. + * @param {!(webdriver.logging.Preferences|Object.)} prefs The + * logging preferences. + * @return {!webdriver.Capabilities} A self reference. + */ +webdriver.Capabilities.prototype.setLoggingPrefs = function(prefs) { + return this.set(webdriver.Capability.LOGGING_PREFS, prefs); +}; + + +/** + * Sets the proxy configuration for this instance. + * @param {webdriver.ProxyConfig} proxy The desired proxy configuration. + * @return {!webdriver.Capabilities} A self reference. + */ +webdriver.Capabilities.prototype.setProxy = function(proxy) { + return this.set(webdriver.Capability.PROXY, proxy); +}; + + +/** + * Sets whether native events should be used. + * @param {boolean} enabled Whether to enable native events. + * @return {!webdriver.Capabilities} A self reference. + */ +webdriver.Capabilities.prototype.setEnableNativeEvents = function(enabled) { + return this.set(webdriver.Capability.NATIVE_EVENTS, enabled); +}; + + +/** + * Sets how elements should be scrolled into view for interaction. + * @param {number} behavior The desired scroll behavior: either 0 to align with + * the top of the viewport or 1 to align with the bottom. + * @return {!webdriver.Capabilities} A self reference. + */ +webdriver.Capabilities.prototype.setScrollBehavior = function(behavior) { + return this.set(webdriver.Capability.ELEMENT_SCROLL_BEHAVIOR, behavior); +}; + + +/** + * Sets the default action to take with an unexpected alert before returning + * an error. + * @param {string} beahvior The desired behavior; should be "accept", "dismiss", + * or "ignore". Defaults to "dismiss". + * @return {!webdriver.Capabilities} A self reference. + */ +webdriver.Capabilities.prototype.setAlertBehavior = function(behavior) { + return this.set(webdriver.Capability.UNEXPECTED_ALERT_BEHAVIOR, behavior); +};