-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat(mobile): add extended wd commands for appium #3326
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import {ActionSequence, By, Capabilities, Command as WdCommand, FileDetector, ICommandName, Options, promise as wdpromise, Session, TargetLocator, TouchSequence, until, WebDriver, WebElement} from 'selenium-webdriver'; | ||
import * as url from 'url'; | ||
import {extend as extendWD, ExtendedWebDriver} from 'webdriver-js-extender'; | ||
|
||
import {DebugHelper} from './debugger'; | ||
import {build$, build$$, ElementArrayFinder, ElementFinder} from './element'; | ||
|
@@ -34,7 +35,7 @@ for (let foo in require('selenium-webdriver')) { | |
|
||
// Explicitly define webdriver.WebDriver | ||
// TODO: extend WebDriver from selenium-webdriver typings | ||
export class Webdriver { | ||
export class AbstractWebDriver { | ||
actions: () => ActionSequence; | ||
call: | ||
(fn: (...var_args: any[]) => any, opt_scope?: any, | ||
|
@@ -63,6 +64,11 @@ export class Webdriver { | |
opt_message?: string) => wdpromise.Promise<any>; | ||
} | ||
|
||
export class AbstractExtendedWebDriver extends AbstractWebDriver { | ||
getNetworkConnection: () => wdpromise.Promise<number>; | ||
setNetworkConnection: (type: number) => wdpromise.Promise<void>; | ||
} | ||
|
||
/** | ||
* Mix a function from one object onto another. The function will still be | ||
* called in the context of the original object. Any arguments of type | ||
|
@@ -115,15 +121,15 @@ function buildElementHelper(browser: ProtractorBrowser): ElementHelper { | |
/** | ||
* @alias browser | ||
* @constructor | ||
* @extends {webdriver.WebDriver} | ||
* @extends {webdriver_extensions.ExtendedWebDriver} | ||
* @param {webdriver.WebDriver} webdriver | ||
* @param {string=} opt_baseUrl A base URL to run get requests against. | ||
* @param {string=} opt_rootElement Selector element that has an ng-app in | ||
* scope. | ||
* @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should | ||
* stop tracking outstanding $timeouts. | ||
*/ | ||
export class ProtractorBrowser extends Webdriver { | ||
export class ProtractorBrowser extends AbstractExtendedWebDriver { | ||
/** | ||
* @type {ProtractorBy} | ||
*/ | ||
|
@@ -138,9 +144,9 @@ export class ProtractorBrowser 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 {webdriver_extensions.ExtendedWebDriver} | ||
*/ | ||
driver: WebDriver; | ||
driver: ExtendedWebDriver; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cnishina are there any type implications here once we fixed definitely typed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cnishina are there any type implications here once we fixed definitely typed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this is taken care of. This does not appear to have typing implications. |
||
|
||
/** | ||
* Helper function for finding elements. | ||
|
@@ -279,19 +285,27 @@ export class ProtractorBrowser 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) { | ||
// Probably not a driver that can be extended (e.g. gotten using | ||
// `directConnect: true` in the config) | ||
extendWDInstance = webdriverInstance as ExtendedWebDriver; | ||
} | ||
|
||
// Mix all other driver functionality into Protractor. | ||
Object.getOwnPropertyNames(WebDriver.prototype).forEach(method => { | ||
if (!this[method] && typeof(webdriverInstance as any)[method] === 'function') { | ||
if (!this[method] && typeof(extendWDInstance as any)[method] === 'function') { | ||
if (methodsToSync.indexOf(method) !== -1) { | ||
ptorMixin(this, webdriverInstance, method, this.waitForAngular.bind(this)); | ||
ptorMixin(this, extendWDInstance, method, this.waitForAngular.bind(this)); | ||
} else { | ||
ptorMixin(this, webdriverInstance, method); | ||
ptorMixin(this, extendWDInstance, method); | ||
} | ||
} | ||
}); | ||
|
||
this.driver = webdriverInstance; | ||
this.driver = extendWDInstance; | ||
this.element = buildElementHelper(this); | ||
this.$ = build$(this.element, By); | ||
this.$$ = build$$(this.element, By); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ import {EventEmitter} from 'events'; | |
import * as q from 'q'; | ||
import {promise as wdpromise, Session} from 'selenium-webdriver'; | ||
import * as util from 'util'; | ||
// TODO(sjelin): patch() will no longer be needed with `selenium-webdriver` 3.x | ||
import {patch} from 'webdriver-js-extender'; | ||
|
||
import {ProtractorBrowser} from './browser'; | ||
import {Config} from './config'; | ||
|
@@ -98,6 +100,13 @@ 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')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with the new types, could we import these with
? |
||
this.config_ = config; | ||
if (this.config_.directConnect) { | ||
this.driverprovider_ = new Direct(this.config_); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Used to provide better protractor documentation for methods given by | ||
// `webdriver-js-extender`. | ||
|
||
/** | ||
* @fileoverview Extra methods provided by webdriver-js-extender. | ||
*/ | ||
|
||
goog.provide('webdriver_extensions'); | ||
|
||
// ///////////////////////////////////////////////////////////////////////////// | ||
// // | ||
// // webdriver_extensions.ExtendedWebDriver | ||
// // | ||
// ///////////////////////////////////////////////////////////////////////////// | ||
/** | ||
* Protractor's `browser` object is a wrapper for an instance of | ||
* `ExtendedWebDriver`, provided by `webdriver-js-extender`, which itself is | ||
* just an instance of `selenium-webdriver`'s WebDriver with some extra methods | ||
* added in. The `browser` object inherits all of WebDriver's and | ||
* ExtendedWebDriver's methods, but only the methods most useful to Protractor | ||
* users are documented here. | ||
* | ||
* More information about `webdriver-js-extender` can be found on the [GitHub | ||
* repo](https://github.com/angular/webdriver-js-extender). | ||
* @alias ExtendedWebDriver | ||
* @constructor | ||
* @extends {webdriver.WebDriver} | ||
*/ | ||
webdriver_extensions.ExtendedWebDriver = function() {}; | ||
|
||
/** | ||
* 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.<number>} A promise that will be | ||
* resolved with the current network connection type. | ||
*/ | ||
webdriver_extensions.ExtendedWebDriver.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.<void>} A promise that will be | ||
* resolved when the network connection type is set. | ||
*/ | ||
webdriver_extensions.ExtendedWebDriver.prototype.setNetworkConnection = function(type) {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this extends the class above and not really the
webdriver_extensions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order for js doc to work, this is the correct type (see old version pointing to
webdriver.WebDriver
notWebdriver
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Alright, that makes sense.