aboutsummaryrefslogtreecommitdiff
path: root/node_modules/selenium-webdriver/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/selenium-webdriver/index.js')
-rw-r--r--node_modules/selenium-webdriver/index.js141
1 files changed, 105 insertions, 36 deletions
diff --git a/node_modules/selenium-webdriver/index.js b/node_modules/selenium-webdriver/index.js
index 47f825738..3cde7f396 100644
--- a/node_modules/selenium-webdriver/index.js
+++ b/node_modules/selenium-webdriver/index.js
@@ -47,6 +47,7 @@ const safari = require('./safari');
const Browser = capabilities.Browser;
const Capabilities = capabilities.Capabilities;
const Capability = capabilities.Capability;
+const Session = session.Session;
const WebDriver = webdriver.WebDriver;
@@ -94,6 +95,80 @@ function ensureFileDetectorsAreEnabled(ctor) {
/**
+ * A thenable wrapper around a {@linkplain webdriver.IWebDriver IWebDriver}
+ * instance that allows commands to be issued directly instead of having to
+ * repeatedly call `then`:
+ *
+ * let driver = new Builder().build();
+ * driver.then(d => d.get(url)); // You can do this...
+ * driver.get(url); // ...or this
+ *
+ * If the driver instance fails to resolve (e.g. the session cannot be created),
+ * every issued command will fail.
+ *
+ * @extends {webdriver.IWebDriver}
+ * @extends {promise.CancellableThenable<!webdriver.IWebDriver>}
+ * @interface
+ */
+class ThenableWebDriver {
+ /** @param {...?} args */
+ static createSession(...args) {}
+}
+
+
+/**
+ * @const {!Map<function(new: WebDriver, !IThenable<!Session>, ...?),
+ * function(new: ThenableWebDriver, !IThenable<!Session>, ...?)>}
+ */
+const THENABLE_DRIVERS = new Map;
+
+
+/**
+ * @param {function(new: WebDriver, !IThenable<!Session>, ...?)} ctor
+ * @param {...?} args
+ * @return {!ThenableWebDriver}
+ */
+function createDriver(ctor, ...args) {
+ let thenableWebDriverProxy = THENABLE_DRIVERS.get(ctor);
+ if (!thenableWebDriverProxy) {
+ /** @implements {ThenableWebDriver} */
+ thenableWebDriverProxy = class extends ctor {
+ /**
+ * @param {!IThenable<!Session>} session
+ * @param {...?} rest
+ */
+ constructor(session, ...rest) {
+ super(session, ...rest);
+
+ const pd = this.getSession().then(session => {
+ return new ctor(session, ...rest);
+ });
+
+ /**
+ * @param {(string|Error)=} opt_reason
+ * @override
+ */
+ this.cancel = function(opt_reason) {
+ if (promise.CancellableThenable.isImplementation(pd)) {
+ /** @type {!promise.CancellableThenable} */(pd).cancel(opt_reason);
+ }
+ };
+
+ /** @override */
+ this.then = pd.then.bind(pd);
+
+ /** @override */
+ this.catch = pd.then.bind(pd);
+ }
+ }
+ promise.CancellableThenable.addImplementation(thenableWebDriverProxy);
+ THENABLE_DRIVERS.set(ctor, thenableWebDriverProxy);
+ }
+ return thenableWebDriverProxy.createSession(...args);
+}
+
+
+/**
* 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.
@@ -134,6 +209,9 @@ function ensureFileDetectorsAreEnabled(ctor) {
*/
class Builder {
constructor() {
+ /** @private @const */
+ this.log_ = logging.getLogger('webdriver.Builder');
+
/** @private {promise.ControlFlow} */
this.flow_ = null;
@@ -465,15 +543,14 @@ class Builder {
* Creates a new WebDriver client based on this builder's current
* configuration.
*
- * While this method will immediately return a new WebDriver instance, any
- * commands issued against it will be deferred until the associated browser
- * has been fully initialized. Users may call {@link #buildAsync()} to obtain
- * a promise that will not be fulfilled until the browser has been created
- * (the difference is purely in style).
+ * This method will return a {@linkplain ThenableWebDriver} instance, allowing
+ * users to issue commands directly without calling `then()`. The returned
+ * thenable wraps a promise that will resolve to a concrete
+ * {@linkplain webdriver.WebDriver WebDriver} instance. The promise will be
+ * rejected if the remote end fails to create a new session.
*
- * @return {!webdriver.WebDriver} A new WebDriver instance.
+ * @return {!ThenableWebDriver} A new WebDriver instance.
* @throws {Error} If the current configuration is invalid.
- * @see #buildAsync()
*/
build() {
// Create a copy for any changes we may need to make based on the current
@@ -482,6 +559,7 @@ class Builder {
var browser;
if (!this.ignoreEnv_ && process.env.SELENIUM_BROWSER) {
+ this.log_.fine(`SELENIUM_BROWSER=${process.env.SELENIUM_BROWSER}`);
browser = process.env.SELENIUM_BROWSER.split(/:/, 3);
capabilities.set(Capability.BROWSER_NAME, browser[0]);
capabilities.set(Capability.VERSION, browser[1] || null);
@@ -524,76 +602,65 @@ class Builder {
let url = this.url_;
if (!this.ignoreEnv_) {
if (process.env.SELENIUM_REMOTE_URL) {
+ this.log_.fine(
+ `SELENIUM_REMOTE_URL=${process.env.SELENIUM_REMOTE_URL}`);
url = process.env.SELENIUM_REMOTE_URL;
} else if (process.env.SELENIUM_SERVER_JAR) {
+ this.log_.fine(
+ `SELENIUM_SERVER_JAR=${process.env.SELENIUM_SERVER_JAR}`);
url = startSeleniumServer(process.env.SELENIUM_SERVER_JAR);
}
}
if (url) {
+ this.log_.fine('Creating session on remote server');
let client = Promise.resolve(url)
.then(url => new _http.HttpClient(url, this.agent_, this.proxy_));
let executor = new _http.Executor(client);
if (browser === Browser.CHROME) {
const driver = ensureFileDetectorsAreEnabled(chrome.Driver);
- return new driver(capabilities, null, this.flow_, executor);
+ return createDriver(
+ driver, capabilities, executor, this.flow_);
}
if (browser === Browser.FIREFOX) {
const driver = ensureFileDetectorsAreEnabled(firefox.Driver);
- return new driver(capabilities, executor, this.flow_);
+ return createDriver(
+ driver, capabilities, executor, this.flow_);
}
-
- return WebDriver.createSession(executor, capabilities, this.flow_);
+ return createDriver(
+ WebDriver, executor, capabilities, this.flow_);
}
// Check for a native browser.
switch (browser) {
case Browser.CHROME:
- return new chrome.Driver(capabilities, null, this.flow_);
+ return createDriver(chrome.Driver, capabilities, null, this.flow_);
case Browser.FIREFOX:
- return new firefox.Driver(capabilities, null, this.flow_);
+ return createDriver(firefox.Driver, capabilities, null, this.flow_);
case Browser.INTERNET_EXPLORER:
- return new ie.Driver(capabilities, this.flow_);
+ return createDriver(ie.Driver, capabilities, this.flow_);
case Browser.EDGE:
- return new edge.Driver(capabilities, null, this.flow_);
+ return createDriver(edge.Driver, capabilities, null, this.flow_);
case Browser.OPERA:
- return new opera.Driver(capabilities, null, this.flow_);
+ return createDriver(opera.Driver, capabilities, null, this.flow_);
case Browser.PHANTOM_JS:
- return new phantomjs.Driver(capabilities, this.flow_);
+ return createDriver(phantomjs.Driver, capabilities, this.flow_);
case Browser.SAFARI:
- return new safari.Driver(capabilities, this.flow_);
+ return createDriver(safari.Driver, capabilities, this.flow_);
default:
throw new Error('Do not know how to build driver: ' + browser
+ '; did you forget to call usingServer(url)?');
}
}
-
- /**
- * Creates a new WebDriver client based on this builder's current
- * configuration. This method returns a promise that will not be fulfilled
- * until the new browser session has been fully initialized.
- *
- * __Note:__ this method is purely a convenience wrapper around
- * {@link #build()}.
- *
- * @return {!promise.Promise<!webdriver.WebDriver>} A promise that will be
- * fulfilled with the newly created WebDriver instance once the browser
- * has been fully initialized.
- * @see #build()
- */
- buildAsync() {
- let driver = this.build();
- return driver.getSession().then(() => driver);
- }
}
@@ -612,6 +679,8 @@ exports.EventEmitter = events.EventEmitter;
exports.FileDetector = input.FileDetector;
exports.Key = input.Key;
exports.Session = session.Session;
+exports.ThenableWebDriver = ThenableWebDriver;
+exports.TouchSequence = actions.TouchSequence;
exports.WebDriver = webdriver.WebDriver;
exports.WebElement = webdriver.WebElement;
exports.WebElementCondition = webdriver.WebElementCondition;