// Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. 'use strict'; /** * @fileoverview Defines types related to describing the capabilities of a * WebDriver session. */ const Symbols = require('./symbols'); /** * Recognized browser names. * @enum {string} */ const Browser = { ANDROID: 'android', CHROME: 'chrome', EDGE: 'MicrosoftEdge', FIREFOX: 'firefox', IE: 'internet explorer', INTERNET_EXPLORER: 'internet explorer', IPAD: 'iPad', IPHONE: 'iPhone', OPERA: 'opera', PHANTOM_JS: 'phantomjs', SAFARI: 'safari', HTMLUNIT: 'htmlunit' }; /** * Common Capability keys. * @enum {string} */ const Capability = { /** * Indicates whether a driver should accept all SSL certs by default. This * capability only applies when requesting a new session. To query whether * a driver can handle insecure SSL certs, see {@link #SECURE_SSL}. */ ACCEPT_SSL_CERTS: 'acceptSslCerts', /** * The browser name. Common browser names are defined in the {@link Browser} * enum. */ 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, * use {@link #UNEXPECTED_ALERT_BEHAVIOR}. */ HANDLES_ALERTS: 'handlesAlerts', /** * Key for the logging driver logging preferences. */ 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 * session, ANY may be used to indicate no platform preference (this is * semantically equivalent to omitting the platform capability). */ PLATFORM: 'platform', /** * Describes the proxy configuration to use for a new WebDriver session. */ PROXY: 'proxy', /** Whether the driver supports changing the browser's orientation. */ ROTATABLE: 'rotatable', /** * Whether a driver is only capable of handling secure SSL certs. To request * that a driver accept insecure SSL certs by default, use * {@link #ACCEPT_SSL_CERTS}. */ SECURE_SSL: 'secureSsl', /** Whether the driver supports manipulating the app cache. */ SUPPORTS_APPLICATION_CACHE: 'applicationCacheEnabled', /** Whether the driver supports locating elements with CSS selectors. */ SUPPORTS_CSS_SELECTORS: 'cssSelectorsEnabled', /** Whether the browser supports JavaScript. */ SUPPORTS_JAVASCRIPT: 'javascriptEnabled', /** Whether the driver supports controlling the browser's location info. */ SUPPORTS_LOCATION_CONTEXT: 'locationContextEnabled', /** Whether the driver supports taking screenshots. */ TAKES_SCREENSHOT: 'takesScreenshot', /** * Defines how the driver should handle unexpected alerts. The value should * be one of "accept", "dismiss", or "ignore". */ UNEXPECTED_ALERT_BEHAVIOR: 'unexpectedAlertBehavior', /** Defines the browser version. */ VERSION: 'version' }; /** * Describes how a proxy should be configured for a WebDriver session. * @record */ function ProxyConfig() {} /** * The proxy type. Must be one of {"manual", "pac", "system"}. * @type {string} */ ProxyConfig.prototype.proxyType; /** * URL for the PAC file to use. Only used if {@link #proxyType} is "pac". * @type {(string|undefined)} */ ProxyConfig.prototype.proxyAutoconfigUrl; /** * The proxy host for FTP requests. Only used if {@link #proxyType} is "manual". * @type {(string|undefined)} */ ProxyConfig.prototype.ftpProxy; /** * The proxy host for HTTP requests. Only used if {@link #proxyType} is * "manual". * @type {(string|undefined)} */ ProxyConfig.prototype.httpProxy; /** * The proxy host for HTTPS requests. Only used if {@link #proxyType} is * "manual". * @type {(string|undefined)} */ ProxyConfig.prototype.sslProxy; /** * A comma delimited list of hosts which should bypass all proxies. Only used if * {@link #proxyType} is "manual". * @type {(string|undefined)} */ ProxyConfig.prototype.noProxy; /** * Converts a generic hash object to a map. * @param {!Object} hash The hash object. * @return {!Map} The converted map. */ function toMap(hash) { let m = new Map; for (let key in hash) { if (hash.hasOwnProperty(key)) { m.set(key, hash[key]); } } return m; } /** * Describes a set of capabilities for a WebDriver session. */ class Capabilities extends Map { /** * @param {(Capabilities|Map|Object)=} opt_other Another set of * capabilities to initialize this instance from. */ constructor(opt_other) { if (opt_other && !(opt_other instanceof Map)) { opt_other = toMap(opt_other); } super(opt_other); } /** * @return {!Capabilities} A basic set of capabilities for Android. */ static android() { return new Capabilities() .set(Capability.BROWSER_NAME, Browser.ANDROID) .set(Capability.PLATFORM, 'ANDROID'); } /** * @return {!Capabilities} A basic set of capabilities for Chrome. */ static chrome() { return new Capabilities().set(Capability.BROWSER_NAME, Browser.CHROME); } /** * @return {!Capabilities} A basic set of capabilities for Microsoft Edge. */ static edge() { return new Capabilities() .set(Capability.BROWSER_NAME, Browser.EDGE) .set(Capability.PLATFORM, 'WINDOWS'); } /** * @return {!Capabilities} A basic set of capabilities for Firefox. */ static firefox() { return new Capabilities().set(Capability.BROWSER_NAME, Browser.FIREFOX); } /** * @return {!Capabilities} A basic set of capabilities for Internet Explorer. */ static ie() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.INTERNET_EXPLORER). set(Capability.PLATFORM, 'WINDOWS'); } /** * @return {!Capabilities} A basic set of capabilities for iPad. */ static ipad() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.IPAD). set(Capability.PLATFORM, 'MAC'); } /** * @return {!Capabilities} A basic set of capabilities for iPhone. */ static iphone() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.IPHONE). set(Capability.PLATFORM, 'MAC'); } /** * @return {!Capabilities} A basic set of capabilities for Opera. */ static opera() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.OPERA); } /** * @return {!Capabilities} A basic set of capabilities for PhantomJS. */ static phantomjs() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.PHANTOM_JS); } /** * @return {!Capabilities} A basic set of capabilities for Safari. */ static safari() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.SAFARI). set(Capability.PLATFORM, 'MAC'); } /** * @return {!Capabilities} A basic set of capabilities for HTMLUnit. */ static htmlunit() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.HTMLUNIT); } /** * @return {!Capabilities} A basic set of capabilities for HTMLUnit * with enabled Javascript. */ static htmlunitwithjs() { return new Capabilities(). set(Capability.BROWSER_NAME, Browser.HTMLUNIT). set(Capability.SUPPORTS_JAVASCRIPT, true); } /** * @return {!Object} The JSON representation of this instance. * Note, the returned object may contain nested promised values. * @suppress {checkTypes} Suppress [] access on a struct (state inherited from * Map). */ [Symbols.serialize]() { return serialize(this); } /** * Merges another set of capabilities into this instance. * @param {!(Capabilities|Map|Object)} other The other * set of capabilities to merge. * @return {!Capabilities} A self reference. */ merge(other) { if (!other) { throw new TypeError('no capabilities provided for merge'); } if (!(other instanceof Map)) { other = toMap(other); } for (let key of other.keys()) { this.set(key, other.get(key)); } return this; } /** * @param {string} key The capability key. * @param {*} value The capability value. * @return {!Capabilities} A self reference. * @throws {TypeError} If the `key` is not a string. * @override */ set(key, value) { if (typeof key !== 'string') { throw new TypeError('Capability keys must be strings: ' + typeof key); } super.set(key, value); return this; } /** * Sets the logging preferences. Preferences may be specified as a * {@link ./logging.Preferences} instance, or as a map of log-type to * log-level. * @param {!(./logging.Preferences|Object)} prefs The logging * preferences. * @return {!Capabilities} A self reference. */ setLoggingPrefs(prefs) { return this.set(Capability.LOGGING_PREFS, prefs); } /** * Sets the proxy configuration for this instance. * @param {ProxyConfig} proxy The desired proxy configuration. * @return {!Capabilities} A self reference. */ setProxy(proxy) { return this.set(Capability.PROXY, proxy); } /** * Sets whether native events should be used. * @param {boolean} enabled Whether to enable native events. * @return {!Capabilities} A self reference. */ setEnableNativeEvents(enabled) { return this.set(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 {!Capabilities} A self reference. */ setScrollBehavior(behavior) { return this.set(Capability.ELEMENT_SCROLL_BEHAVIOR, behavior); } /** * Sets the default action to take with an unexpected alert before returning * an error. * @param {string} behavior The desired behavior should be "accept", * "dismiss", or "ignore". Defaults to "dismiss". * @return {!Capabilities} A self reference. */ setAlertBehavior(behavior) { return this.set(Capability.UNEXPECTED_ALERT_BEHAVIOR, behavior); } } /** * Serializes a capabilities object. This is defined as a standalone function * so it may be type checked (where Capabilities[Symbols.serialize] has type * checking disabled since it is defined with [] access on a struct). * * @param {!Capabilities} caps The capabilities to serialize. * @return {!Object} The JSON representation of this instance. * Note, the returned object may contain nested promised values. */ function serialize(caps) { let ret = {}; for (let key of caps.keys()) { let cap = caps.get(key); if (cap !== undefined && cap !== null) { ret[key] = cap; } } return ret; } // PUBLIC API module.exports = { Browser: Browser, Capabilities: Capabilities, Capability: Capability, ProxyConfig: ProxyConfig };