diff options
Diffstat (limited to 'node_modules/selenium-webdriver/index.js')
-rw-r--r-- | node_modules/selenium-webdriver/index.js | 141 |
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; |