Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(mobile): add extended wd commands for appium
Browse files Browse the repository at this point in the history
Had to make some minor changes to the website to handle longer inheritance
chains
  • Loading branch information
sjelin committed Dec 13, 2016
1 parent 288dfeb commit 0f582cc
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 29 deletions.
6 changes: 3 additions & 3 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ gulp.task('webdriver:update', function(done) {
});

gulp.task('jshint', function(done) {
runSpawn(done, 'node', ['node_modules/jshint/bin/jshint', '-c', '.jshintrc', 'lib', 'spec', 'scripts',
'--exclude=lib/selenium-webdriver/**/*.js,spec/dependencyTest/*.js,' +
'spec/install/**/*.js']);
runSpawn(done, 'node', ['node_modules/jshint/bin/jshint', '-c', '.jshintrc', 'lib', 'spec',
'scripts', '--exclude=lib/selenium-webdriver/**/*.js,lib/webdriver-js-extender/**/*.js,' +
'spec/dependencyTest/*.js,spec/install/**/*.js']);
});

gulp.task('format:enforce', function() {
Expand Down
32 changes: 23 additions & 9 deletions lib/browser.ts
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';
Expand Down Expand Up @@ -32,7 +33,7 @@ for (let foo in 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,
Expand Down Expand Up @@ -61,6 +62,11 @@ export class Webdriver {
opt_message?: string) => wdpromise.Promise<any>;
}

export class AbstractExtendedWebDriver extends AbstractWebDriver {
getNetworkConnection: () => webdriver.promise.Promise<number>;
setNetworkConnection: (type: number) => webdriver.promise.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
Expand Down Expand Up @@ -114,15 +120,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}
*/
Expand All @@ -137,9 +143,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;

/**
* Helper function for finding elements.
Expand Down Expand Up @@ -278,19 +284,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);
Expand Down
9 changes: 9 additions & 0 deletions lib/runner.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {EventEmitter} from 'events';
import * as q from 'q';
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';
Expand Down Expand Up @@ -99,6 +101,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'));
this.config_ = config;
if (this.config_.directConnect) {
this.driverprovider_ = new Direct(this.config_);
Expand Down
8 changes: 4 additions & 4 deletions lib/selenium-webdriver/webdriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

goog.provide('webdriver');

// //////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////
// //
// // webdriver.WebDriver
// //
// //////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////
/**
* Protractor's `browser` object is a wrapper for `selenium-webdriver` WebDriver.
* It inherits call of WebDriver's methods, but only the methods most useful to
Expand Down Expand Up @@ -318,11 +318,11 @@ webdriver.WebDriver.prototype.takeScreenshot = function() {};
*/
webdriver.WebDriver.prototype.switchTo = function() {}

// //////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////
// //
// // webdriver.WebElement
// //
// //////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////
//
//
//
Expand Down
63 changes: 63 additions & 0 deletions lib/webdriver-js-extender/index.js
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) {};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"saucelabs": "~1.3.0",
"selenium-webdriver": "2.53.3",
"source-map-support": "~0.4.0",
"webdriver-manager": "^10.2.8"
"webdriver-manager": "^10.2.8",
"webdriver-js-extender": "^0.2.2"
},
"devDependencies": {
"@types/chalk": "^0.4.28",
Expand Down
3 changes: 2 additions & 1 deletion website/docgen/dgeni-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ myPackage.config(function(readFilesProcessor, templateFinder, writeFilesProcesso
{include: 'built/locators.js'},
{include: 'built/expectedConditions.js'},
{include: 'lib/selenium-webdriver/locators.js'},
{include: 'lib/selenium-webdriver/webdriver.js'}
{include: 'lib/selenium-webdriver/webdriver.js'},
{include: 'lib/webdriver-js-extender/index.js'}
];

// Add a folder to search for our own templates to use when rendering docs
Expand Down
20 changes: 11 additions & 9 deletions website/js/api-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,18 @@
// Remove braces from {type}.
var parentName = item.extends.replace(/[{}]/g, '');
var nameExpr = new RegExp(parentName + '\\.prototype');
var parent = self.itemsByName[parentName];

// Find all the parent functions.
item.base = {
name: parentName,
items: _.filter(list, function(item) {
return item.name && item.name.match(nameExpr);
})
};
if (self.itemsByName[parentName]) {
self.itemsByName[parentName].extension = true;
if (parent) {
item.base = parent;
parent.extension = true;
} else {
item.base = {
name: parentName,
children: _.filter(list, function(item) {
return item.name && item.name.match(nameExpr);
}),
};
}
});
};
Expand Down
11 changes: 9 additions & 2 deletions website/partials/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,16 @@ <h4>Functions</h4>

<!-- Extends -->
<div ng-if="currentItem.extends">
<h4>Extends {{currentItem.base.name}}</h4>
<h4>Extends {{currentItem.base.title}}</h4>

<div ptor-function-list="currentItem.base.items"></div>
<div ptor-function-list="currentItem.base.children"></div>

<!-- Extension Extends -->
<div ng-if="currentItem.base.extends">
<h4>Extends {{currentItem.base.base.title}} (via {{currentItem.base.title}})</h4>

<div ptor-function-list="currentItem.base.base.children"></div>
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit 0f582cc

Please sign in to comment.