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

chore(types): add in types inherited from selenium-webdriver #3288

Merged
merged 1 commit into from
Jun 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ gulp.task('default',['prepublish']);

gulp.task('types', function(done) {
var folder = 'built';
var files = ['ptor', 'browser', 'locators', 'expectedConditions'];
var files = ['ptor', 'browser', 'element', 'locators', 'expectedConditions'];
var outputFile = path.resolve(folder, 'index.d.ts');
var contents = '';
files.forEach(file => {
Expand Down Expand Up @@ -104,8 +104,29 @@ var parseTypingsFile = function(folder, file) {
if (line.indexOf('export') !== -1) {
line = line.replace('export', '').trim();
}

// Remove webdriver types and plugins for now
line = removeTypes(line,'webdriver.ActionSequence');
line = removeTypes(line,'webdriver.promise.Promise');
line = removeTypes(line,'webdriver.util.Condition');
line = removeTypes(line,'webdriver.WebDriver');
line = removeTypes(line,'webdriver.Locator');
line = removeTypes(line,'webdriver.WebElement');
line = removeTypes(line,'Plugins');
contents += line + '\n';
}

}
return contents;
}

var removeTypes = function(line, webdriverType) {
var tempLine = line.trim();
if (tempLine.startsWith('/**') || tempLine.startsWith('*')) {
Copy link
Member

@juliemr juliemr Jun 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They would usually start with * for multiline comments. (That didn't show up well, it's a space in front of the *)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine because I am trimming the line prior to testing if it starts with a *. This should capture the comments in the index.d.ts file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right you are.

return line;
}
if (line.indexOf(webdriverType) !== -1) {
return line.replace(new RegExp(webdriverType,'g'), 'any');
}
return line;
}
25 changes: 21 additions & 4 deletions lib/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as url from 'url';
import * as util from 'util';

import {ElementArrayFinder, ElementFinder, build$, build$$} from './element';
import * as EC from './expectedConditions';
import {ExpectedConditions_} from './expectedConditions';
import {Locator, ProtractorBy} from './locators';
import {Logger} from './logger2';
import {Plugins} from './plugins';
Expand All @@ -30,6 +30,22 @@ for (let foo in webdriver) {
exports[foo] = webdriver[foo];
}

// Explicitly define webdriver.WebDriver.
export class Webdriver {
actions: () => webdriver.ActionSequence = webdriver.WebDriver.actions;
wait:
(condition: webdriver.promise.Promise|webdriver.util.Condition|Function,
opt_timeout?: number,
opt_message?:
string) => webdriver.promise.Promise = webdriver.WebDriver.wait;
sleep: (ms: number) => webdriver.promise.Promise = webdriver.WebDriver.sleep;
getCurrentUrl:
() => webdriver.promise.Promise = webdriver.WebDriver.getCurrentUrl;
getTitle: () => webdriver.promise.Promise = webdriver.WebDriver.getTitle;
takeScreenshot:
() => webdriver.promise.Promise = webdriver.WebDriver.takeScreenshot;
}

/**
* Mix a function from one object onto another. The function will still be
* called in the context of the original object.
Expand Down Expand Up @@ -85,7 +101,7 @@ function buildElementHelper(browser: Browser): ElementHelper {
* @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should
* stop tracking outstanding $timeouts.
*/
export class Browser {
export class Browser extends Webdriver {
/**
* @type {ProtractorBy}
*/
Expand All @@ -94,7 +110,7 @@ export class Browser {
/**
* @type {ExpectedConditions}
*/
static ExpectedConditions = new EC.ExpectedConditions();
static ExpectedConditions = new ExpectedConditions_();

/**
* The wrapped webdriver instance. Use this to interact with pages that do
Expand Down Expand Up @@ -225,6 +241,7 @@ export class Browser {
constructor(
webdriverInstance: webdriver.WebDriver, opt_baseUrl?: string,
opt_rootElement?: string, opt_untrackOutstandingTimeouts?: boolean) {
super();
// These functions should delegate to the webdriver instance, but should
// wait for Angular to sync up before performing the action. This does not
// include functions which are overridden by protractor below.
Expand Down Expand Up @@ -281,7 +298,7 @@ export class Browser {
*
* Set by the runner.
*
* @return {q.Promise} A promise which resolves to the capabilities object.
* @return {webdriver.promise.Promise} A promise which resolves to the capabilities object.
*/
getProcessedConfig: () => webdriver.promise.Promise;

Expand Down
50 changes: 41 additions & 9 deletions lib/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@ let WEB_ELEMENT_FUNCTIONS = [
'serialize', 'takeScreenshot'
];

// Explicitly define webdriver.WebElement.
export class WebdriverWebElement {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense for these to be interfaces instead of classes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this to be an interface.

getDriver: () => webdriver.WebDriver;
getId: () => webdriver.promise.Promise;
getRawId: () => webdriver.promise.Promise;
serialize: () => webdriver.promise.Promise;
findElement: (subLocator: Locator) => webdriver.promise.Promise;
click: () => webdriver.promise.Promise;
sendKeys: (...args: (string|webdriver.promise.Promise)[]) =>
webdriver.promise.Promise;
getTagName: () => webdriver.promise.Promise;
getCssValue: (cssStyleProperty: string) => webdriver.promise.Promise;
getAttribute: (attributeName: string) => webdriver.promise.Promise;
getText: () => webdriver.promise.Promise;
getSize: () => webdriver.promise.Promise;
getLocation: () => webdriver.promise.Promise;
isEnabled: () => webdriver.promise.Promise;
isSelected: () => webdriver.promise.Promise;
submit: () => webdriver.promise.Promise;
clear: () => webdriver.promise.Promise;
isDisplayed: () => webdriver.promise.Promise;
takeScreenshot: (opt_scroll?: boolean) => webdriver.promise.Promise;
getOuterHtml: () => webdriver.promise.Promise;
getInnerHtml: () => webdriver.promise.Promise;
}

/**
* ElementArrayFinder is used for operations on an array of elements (as opposed
* to a single element).
Expand Down Expand Up @@ -67,13 +93,14 @@ let WEB_ELEMENT_FUNCTIONS = [
* action result, or null if no action has been called.
* @return {ElementArrayFinder}
*/
export class ElementArrayFinder {
export class ElementArrayFinder extends WebdriverWebElement {
getWebElements: Function;

constructor(
private browser_: Browser, getWebElements?: Function,
private locator_?: any,
public actionResults_: webdriver.promise.Promise = null) {
super();
this.getWebElements = getWebElements || null;

// TODO(juliemr): might it be easier to combine this with our docs and just
Expand Down Expand Up @@ -379,7 +406,7 @@ export class ElementArrayFinder {
*
* @return {webdriver.Locator}
*/
locator(): any { return this.locator_; }
locator(): Locator { return this.locator_; }

/**
* Apply an action function to every element in the ElementArrayFinder,
Expand Down Expand Up @@ -661,12 +688,14 @@ export class ElementArrayFinder {
* that this is branched from.
* @return {ElementFinder}
*/
export class ElementFinder {
export class ElementFinder extends WebdriverWebElement {
parentElementArrayFinder: ElementArrayFinder;
elementArrayFinder_: ElementArrayFinder;
then: Function = null;
then: (fn: Function, errorFn: Function) => webdriver.promise.Promise = null;

constructor(private browser_: Browser, elementArrayFinder: ElementArrayFinder) {
constructor(
private browser_: Browser, elementArrayFinder: ElementArrayFinder) {
super();
if (!elementArrayFinder) {
throw new Error('BUG: elementArrayFinder cannot be empty');
}
Expand All @@ -680,6 +709,7 @@ export class ElementFinder {
*
* @param {function(webdriver.promise.Promise)} fn Function which takes
* the value of the underlying actionResult.
* @param {function(Error)} errorFn
*
* @return {webdriver.promise.Promise} Promise which contains the results of
* evaluating fn.
Expand Down Expand Up @@ -731,10 +761,12 @@ export class ElementFinder {
});
}

static fromWebElement_(ptor: any, webElem: any, locator: any): ElementFinder {
static fromWebElement_(
browser: Browser, webElem: webdriver.WebElement,
locator: Locator): ElementFinder {
let getWebElements =
() => { return webdriver.promise.fulfilled([webElem]); };
return new ElementArrayFinder(ptor, getWebElements, locator)
return new ElementArrayFinder(browser, getWebElements, locator)
.toElementFinder_();
}

Expand Down Expand Up @@ -802,7 +834,7 @@ export class ElementFinder {
* @param {webdriver.Locator} subLocator
* @return {ElementArrayFinder}
*/
all(subLocator: any): ElementArrayFinder {
all(subLocator: Locator): ElementArrayFinder {
return this.elementArrayFinder_.all(subLocator);
}

Expand Down Expand Up @@ -833,7 +865,7 @@ export class ElementFinder {
* @param {webdriver.Locator} subLocator
* @return {ElementFinder}
*/
element(subLocator: any): ElementFinder {
element(subLocator: Locator): ElementFinder {
return this.all(subLocator).toElementFinder_();
}

Expand Down
11 changes: 7 additions & 4 deletions lib/expectedConditions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {protractor} from './ptor';
import {ElementFinder} from './element';
import {protractor} from './ptor';

let webdriver = require('selenium-webdriver');

/* globals browser */
Expand Down Expand Up @@ -44,7 +45,7 @@ let webdriver = require('selenium-webdriver');
*
* @constructor
*/
export class ExpectedConditions {
export class ExpectedConditions_ {
/**
* Negates the result of a promise.
*
Expand Down Expand Up @@ -189,7 +190,8 @@ export class ExpectedConditions {
* @return {!function} An expected condition that returns a promise
* representing whether the text is present in the element.
*/
textToBePresentInElement(elementFinder: ElementFinder, text: string): Function {
textToBePresentInElement(elementFinder: ElementFinder, text: string):
Function {
var hasText = () => {
return elementFinder.getText().then((actualText: string): boolean => {
return actualText.indexOf(text) > -1;
Expand All @@ -213,7 +215,8 @@ export class ExpectedConditions {
* @return {!function} An expected condition that returns a promise
* representing whether the text is present in the element's value.
*/
textToBePresentInElementValue(elementFinder: ElementFinder, text: string): Function {
textToBePresentInElementValue(elementFinder: ElementFinder, text: string):
Function {
var hasText = () => {
return elementFinder.getAttribute('value').then(
(actualText: string): boolean => {
Expand Down
14 changes: 10 additions & 4 deletions lib/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ declare interface String { startsWith: Function; }

declare namespace webdriver {
var error: any;

class ActionSequence {}

class WebDriver {
findElements: Function;
getSession: Function;
Expand All @@ -61,12 +64,15 @@ declare namespace webdriver {
}

namespace promise {
interface Promise {
controlFlow: Function,
then: Function
}
interface Promise {
controlFlow: Function;
then: Function;
}
}

namespace util {
interface Condition {}
}
class Capabilities {
get: Function;
}
Expand Down
31 changes: 14 additions & 17 deletions lib/locators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ import * as util from 'util';
let webdriver: any = require('selenium-webdriver');
let clientSideScripts: any = require('./clientsidescripts');

/**
* webdriver's By is an enum of locator functions, so we must set it to
* a prototype before inheriting from it.
*/
export class WebdriverBy {}
WebdriverBy.prototype = webdriver.By;
// Explicitly define webdriver.By.
export class WebdriverBy {
className: (className: string) => Locator = webdriver.By.className;
css: (css: string) => Locator = webdriver.By.css;
id: (id: string) => Locator = webdriver.By.id;
linkText: (linkText: string) => Locator = webdriver.By.linkText;
js: (js: string) => Locator = webdriver.By.js;
name: (name: string) => Locator = webdriver.By.name;
partialLinkText:
(partialText: string) => Locator = webdriver.By.partialLinkText;
tagName: (tagName: string) => Locator = webdriver.By.tagName;
xpath: (xpath: string) => Locator = webdriver.By.xpath;
}

// Interface for webdriver.Locator.
export interface Locator {
findElementsOverride?:
(driver: webdriver.WebDriver, using: webdriver.WebElement,
Expand All @@ -27,17 +35,6 @@ export interface Locator {
export class ProtractorBy extends WebdriverBy {
[key: string]: any;

className: (className: string) => Locator = webdriver.By.className;
css: (css: string) => Locator = webdriver.By.css;
id: (id: string) => Locator = webdriver.By.id;
linkText: (linkText: string) => Locator = webdriver.By.linkText;
js: (js: string) => Locator = webdriver.By.js;
name: (name: string) => Locator = webdriver.By.name;
partialLinkText:
(partialText: string) => Locator = webdriver.By.partialLinkText;
tagName: (tagName: string) => Locator = webdriver.By.tagName;
xpath: (xpath: string) => Locator = webdriver.By.xpath;

/**
* Add a locator to this instance of ProtractorBy. This locator can then be
* used with element(by.locatorName(args)).
Expand Down
Loading