From 7dd46464118748a3ad9688343b65dc1a15a95245 Mon Sep 17 00:00:00 2001 From: Jason Leyba Date: Thu, 30 Oct 2014 13:18:18 -0700 Subject: [PATCH] Update the js builder to select a server jar from the current environment. Also update the examples to support this new behavior. --- javascript/node/selenium-webdriver/builder.js | 88 ++++++++++++++++--- .../example/google_search.js | 26 ++++-- .../example/google_search_generator.js | 8 +- .../example/google_search_test.js | 15 ++-- .../example/parallel_flows.js | 7 +- .../node/selenium-webdriver/remote/index.js | 22 +++-- 6 files changed, 129 insertions(+), 37 deletions(-) diff --git a/javascript/node/selenium-webdriver/builder.js b/javascript/node/selenium-webdriver/builder.js index 222d38aeb7907..edc6c534a8a87 100644 --- a/javascript/node/selenium-webdriver/builder.js +++ b/javascript/node/selenium-webdriver/builder.js @@ -24,30 +24,67 @@ var Browser = base.require('webdriver.Browser'), +var seleniumServer; + +/** + * Starts an instance of the Selenium server if not yet running. + * @param {string} jar Path to the server jar to use. + * @return {!webdriver.promise.Promise.} A promise for the server's + * addrss once started. + */ +function startSeleniumServer(jar) { + if (!seleniumServer) { + // Requiring 'chrome' above would create a cycle: + // index -> builder -> chrome -> index + var remote = require('./remote'); + seleniumServer = new remote.SeleniumServer(jar); + } + return seleniumServer.start(); +} + + /** * 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();}. + *


+ *   var driver = new webdriver.Builder()
+ *       .forBrowser('chrome')
+ *       .build();
+ * 
* * This test could be made to use Firefox on the local machine by running with - * {@code SELENIUM_BROWSER=firefox node mytest.js}. + * {@code SELENIUM_BROWSER=firefox node mytest.js}. Rather than change the + * code to target Google Chrome on a remote machine, you can simply set the + * SELENIUM_BROWSER and SELENIUM_REMOTE_URL environment variables: + *

+ *   SELENIUM_BROWSER=chrome:36:LINUX \
+ *   SELENIUM_REMOTE_URL=http://www.example.com:4444/wd/hub \
+ *   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}. + *

You could also use a local copy of the standalone Selenium server: + *


+ *   SELENIUM_BROWSER=chrome:36:LINUX \
+ *   SELENIUM_SERVER_JAR=/path/to/selenium-server-standalone.jar \
+ *   node mytest.js
+ * 
* * @constructor */ @@ -67,6 +104,21 @@ var Builder = function() { /** @private {firefox.Options} */ this.firefoxOptions_ = null; + + /** @private {boolean} */ + this.ignoreEnv_ = false; +}; + + +/** + * Configures this builder to ignore any environment variable overrides and to + * only use the configuration specified through this instance's API. + * + * @return {!Builder} A self reference. + */ +Builder.prototype.disableEnvironmentOverrides = function() { + this.ignoreEnv_ = true; + return this; }; @@ -262,9 +314,9 @@ Builder.prototype.build = function() { // environment. var capabilities = new Capabilities(this.capabilities_); - var browser = process.env.SELENIUM_BROWSER; - if (browser) { - browser = browser.split(/:/, 3); + var browser; + if (!this.ignoreEnv_ && 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); capabilities.set(Capability.PLATFORM, browser[2] || null); @@ -288,7 +340,15 @@ Builder.prototype.build = function() { } // Check for a remote browser. - var url = process.env.SELENIUM_REMOTE_URL || this.url_; + var url = this.url_; + if (!this.ignoreEnv_) { + if (process.env.SELENIUM_REMOTE_URL) { + url = process.env.SELENIUM_REMOTE_URL; + } else if (process.env.SELENIUM_SERVER_JAR) { + url = startSeleniumServer(process.env.SELENIUM_SERVER_JAR); + } + } + if (url) { var executor = executors.createExecutor(url); return WebDriver.createSession(executor, capabilities, this.flow_); diff --git a/javascript/node/selenium-webdriver/example/google_search.js b/javascript/node/selenium-webdriver/example/google_search.js index 289ef1bf50469..87649669810f7 100644 --- a/javascript/node/selenium-webdriver/example/google_search.js +++ b/javascript/node/selenium-webdriver/example/google_search.js @@ -16,14 +16,30 @@ /** * @fileoverview An example WebDriver script. This requires the chromedriver * to be present on the system PATH. - * Usage: node selenium-webdriver/example/google_search.js + * + * Usage: + * // Default behavior + * node selenium-webdriver/example/google_search.js + * + * // Target Chrome locally; the chromedriver must be on your PATH + * SELENIUM_BROWSER=chrome node selenium-webdriver/example/google_search.js + * + * // Use a local copy of the standalone Selenium server + * SELENIUM_SERVER_JAR=/path/to/selenium-server-standalone.jar \ + * node selenium-webdriver/example/google_search.js + * + * // Target a remove Selenium server + * SELENIUM_REMOTE_URL=http://www.example.com:4444/wd/hub \ + * node selenium-webdriver/example/google_search.js */ -var By = require('..').By, - until = require('..').until, - firefox = require('../firefox'); +var webdriver = require('..'), + By = webdriver.By, + until = webdriver.until; -var driver = new firefox.Driver(); +var driver = new webdriver.Builder() + .forBrowser('firefox') + .build(); driver.get('http://www.google.com/ncr'); driver.findElement(By.name('q')).sendKeys('webdriver'); diff --git a/javascript/node/selenium-webdriver/example/google_search_generator.js b/javascript/node/selenium-webdriver/example/google_search_generator.js index 708f5e13271f3..08f7e5d1974d7 100644 --- a/javascript/node/selenium-webdriver/example/google_search_generator.js +++ b/javascript/node/selenium-webdriver/example/google_search_generator.js @@ -21,10 +21,12 @@ * selenium-webdriver/example/google_search_generator.js */ -var By = require('..').By, - firefox = require('../firefox'); +var webdriver = require('..'), + By = webdriver.By; -var driver = new firefox.Driver(); +var driver = new webdriver.Builder() + .forBrowser('firefox') + .build(); driver.get('http://www.google.com/ncr'); driver.call(function* () { diff --git a/javascript/node/selenium-webdriver/example/google_search_test.js b/javascript/node/selenium-webdriver/example/google_search_test.js index 66054f0fb0b67..1198f9fb2a0b2 100644 --- a/javascript/node/selenium-webdriver/example/google_search_test.js +++ b/javascript/node/selenium-webdriver/example/google_search_test.js @@ -18,17 +18,18 @@ * Usage: mocha -t 10000 selenium-webdriver/example/google_search_test.js */ -var By = require('..').By, - until = require('..').until, - firefox = require('../firefox'), +var webdriver = require('..'), + By = webdriver.By, + until = webdriver.until, test = require('../testing'); - test.describe('Google Search', function() { var driver; test.before(function() { - driver = new firefox.Driver(); + driver = new webdriver.Builder() + .forBrowser('firefox') + .build(); }); test.it('should append query to title', function() { @@ -38,5 +39,7 @@ test.describe('Google Search', function() { driver.wait(until.titleIs('webdriver - Google Search'), 1000); }); - test.after(function() { driver.quit(); }); + test.after(function() { + driver.quit(); + }); }); diff --git a/javascript/node/selenium-webdriver/example/parallel_flows.js b/javascript/node/selenium-webdriver/example/parallel_flows.js index e9fba174bbb93..7184e0ca1eddf 100644 --- a/javascript/node/selenium-webdriver/example/parallel_flows.js +++ b/javascript/node/selenium-webdriver/example/parallel_flows.js @@ -19,6 +19,7 @@ */ var webdriver = require('..'), + By = webdriver.By, until = webdriver.until; for (var i = 0; i < 3; i++) { @@ -29,7 +30,7 @@ for (var i = 0; i < 3; i++) { }); var driver = new webdriver.Builder(). - withCapabilities(webdriver.Capabilities.firefox()). + forBrowser('firefox'). setControlFlow(flow). // Comment out this line to see the difference. build(); @@ -38,8 +39,8 @@ for (var i = 0; i < 3; i++) { driver.manage().window().setPosition(300 * i, 400 * i); driver.get('http://www.google.com'); - driver.findElement(webdriver.By.name('q')).sendKeys('webdriver'); - driver.findElement(webdriver.By.name('btnG')).click(); + driver.findElement(By.name('q')).sendKeys('webdriver'); + driver.findElement(By.name('btnG')).click(); driver.wait(until.titleIs('webdriver - Google Search'), 1000); driver.quit(); diff --git a/javascript/node/selenium-webdriver/remote/index.js b/javascript/node/selenium-webdriver/remote/index.js index 4a70609bc0daa..003af1d6cbf75 100644 --- a/javascript/node/selenium-webdriver/remote/index.js +++ b/javascript/node/selenium-webdriver/remote/index.js @@ -231,18 +231,28 @@ DriverService.prototype.stop = function() { /** - * Manages the life and death of the Selenium standalone server. The server - * may be obtained from http://selenium-release.storage.googleapis.com/index.html. + * Manages the life and death of the + * + * standalone Selenium server. + * * @param {string} jar Path to the Selenium server jar. - * @param {!SeleniumServer.Options} options Configuration options for the + * @param {SeleniumServer.Options=} opt_options Configuration options for the * server. - * @throws {Error} If an invalid port is specified. + * @throws {Error} If the path to the Selenium jar is not specified or if an + * invalid port is specified. * @constructor * @extends {DriverService} */ -function SeleniumServer(jar, options) { - if (options.port < 0) +function SeleniumServer(jar, opt_options) { + if (!jar) { + throw Error('Path to the Selenium jar not specified'); + } + + var options = opt_options || {}; + + if (options.port < 0) { throw Error('Port must be >= 0: ' + options.port); + } var port = options.port || portprober.findFreePort(); var args = promise.when(options.jvmArgs || [], function(jvmArgs) {