diff --git a/lib/browser.ts b/lib/browser.ts index 4e70dd2d7..c4b37eea3 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -11,6 +11,8 @@ import {Plugins} from './plugins'; import {protractor} from './ptor'; import * as helper from './util'; +import {extend as extendWD, ExtendedWebDriver} from 'webdriver-js-extender'; + let clientSideScripts = require('./clientsidescripts'); let webdriver = require('selenium-webdriver'); @@ -118,9 +120,9 @@ export class Browser extends Webdriver { * The wrapped webdriver instance. Use this to interact with pages that do * not contain Angular (such as a log-in screen). * - * @type {webdriver.WebDriver} + * @type {ExtendedWebDriver} */ - driver: webdriver.WebDriver; + driver: ExtendedWebDriver; /** * Helper function for finding elements. @@ -248,23 +250,29 @@ export class Browser extends Webdriver { // wait for Angular to sync up before performing the action. This does not // include functions which are overridden by protractor below. let methodsToSync = ['getCurrentUrl', 'getPageSource', 'getTitle']; - + let extendWDInstance: ExtendedWebDriver; + try { + extendWDInstance = extendWD(webdriverInstance); + } catch (e) { + // Must not have a driver that can be extended (e.g. directly provided) + extendWDInstance = webdriverInstance as ExtendedWebDriver; + } // Mix all other driver functionality into Protractor. Object.getOwnPropertyNames(webdriver.WebDriver.prototype) .forEach((method: string) => { - if (!this[method] && typeof webdriverInstance[method] == 'function') { + if (!this[method] && typeof extendWDInstance[method] == 'function') { if (methodsToSync.indexOf(method) !== -1) { mixin( - this, webdriverInstance, method, + this, extendWDInstance, method, this.waitForAngular.bind(this)); } else { - mixin(this, webdriverInstance, method); + mixin(this, extendWDInstance, method); } } }); - this.driver = webdriverInstance; + this.driver = extendWDInstance; this.element = buildElementHelper(this); this.$ = build$(this.element, webdriver.By); this.$$ = build$$(this.element, webdriver.By); diff --git a/lib/runner.ts b/lib/runner.ts index 2a5a109c2..e01d42e40 100644 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -11,6 +11,8 @@ import {Logger} from './logger'; import {Plugins} from './plugins'; import {protractor} from './ptor'; import * as helper from './util'; +// TODO(sjelin): patch() will no longer be needed with `selenium-webdriver` 3.x +import {patch} from 'webdriver-js-extender'; var webdriver = require('selenium-webdriver'); let logger = new Logger('runner'); @@ -91,6 +93,14 @@ export class Runner extends EventEmitter { * 5) try to find the seleniumServerJar in protractor/selenium */ loadDriverProvider_(config: Config) { + // `webdriver-js-extender` needs to overwrite `DeferredExecutor` and some + // associated functions so that it can define custom commands. In version + // 3.x of `selenium-webdriver`, this will no longer be necessary and will + // have to be removed + patch( + require('selenium-webdriver/lib/command'), + require('selenium-webdriver/executors'), + require('selenium-webdriver/http')); this.config_ = config; if (this.config_.directConnect) { this.driverprovider_ = new Direct(this.config_); diff --git a/lib/selenium-webdriver/webdriver.js b/lib/selenium-webdriver/webdriver.js index f19fc67de..676d46fa0 100644 --- a/lib/selenium-webdriver/webdriver.js +++ b/lib/selenium-webdriver/webdriver.js @@ -537,3 +537,40 @@ webdriver.WebElement.prototype.isDisplayed = function() {}; * resolved to the screenshot as a base-64 encoded PNG. */ webdriver.WebElement.prototype.takeScreenshot = function(opt_scroll) {}; + + +// EXTENDED WD METHODS + +/** + * Schedules a command to retrieve the network connection type + * + * Network connection types are a bitmask with: + * 1 -> airplane mode + * 2 -> wifi + * 4 -> data + * + * @example + * expect(browser.getNetworkConnection()).toBe(6); //Expect wifi and data on + * + * @returns {!webdriver.promise.Promise.} A promise that will be + * resolved with the current network connection type. + */ +webdriver.WebDriver.prototype.getNetworkConnection = function() {}; + +/** + * Schedules a command to set the network connection type + * + * Network connection types are a bitmask with: + * 1 -> airplane mode + * 2 -> wifi + * 4 -> data + * + * @example + * browser.setNetworkConnection(1); //Turn on airplane mode + * expect(browser.getNetworkConnection()).toBe(1); + * + * @param {number} type The type to set the network connection to + * @returns {!webdriver.promise.Promise.} A promise that will be + * resolved when the network connection type is set + */ +webdriver.WebDriver.prototype.setNetworkConnection = function(type) {}; diff --git a/package.json b/package.json index 4abca61a8..06426c075 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "saucelabs": "~1.2.0", "selenium-webdriver": "2.53.3", "source-map-support": "~0.4.0", + "webdriver-js-extender": "^0.2.2", "webdriver-manager": "^10.2.1" }, "devDependencies": {