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

chore(types): clean up TypeScript support #3520

Merged
merged 2 commits into from
Sep 13, 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
1 change: 1 addition & 0 deletions exampleTypescript/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.js
node_modules
tmp/
6 changes: 5 additions & 1 deletion exampleTypescript/conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ export let config: Config = {
browserName: 'chrome'
},
specs: [ 'spec.js' ],
seleniumAddress: 'http://localhost:4444/wd/hub'
seleniumAddress: 'http://localhost:4444/wd/hub',

// You could set no globals to true to avoid jQuery '$' and protractor '$'
// collisions on the global namespace.
noGlobals: true
};
88 changes: 6 additions & 82 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ gulp.task('checkVersion', function(done) {
}
});

gulp.task('built:copy', function() {
return gulp.src(['lib/**/*.js','lib/globals.d.ts'])
gulp.task('built:copy', function(done) {
return gulp.src(['lib/**/*.js','lib/globals.d.ts','lib/index.d.ts'])
.pipe(gulp.dest('built/'));
done();
});

gulp.task('webdriver:update', function(done) {
Expand Down Expand Up @@ -88,91 +89,14 @@ gulp.task('tsc:globals', function(done) {
});

gulp.task('prepublish', function(done) {
runSequence('checkVersion', ['jshint', 'format'], 'tsc', 'tsc:globals', 'types',
'ambient', 'built:copy', done);
runSequence('checkVersion', ['jshint', 'format'], 'tsc', 'tsc:globals',
'built:copy', done);
});

gulp.task('pretest', function(done) {
runSequence('checkVersion',
['webdriver:update', 'jshint', 'format'], 'tsc', 'tsc:globals',
'types', 'ambient', 'built:copy', done);
'built:copy', done);
});

gulp.task('default',['prepublish']);

gulp.task('types', function(done) {
var folder = 'built';
var files = ['browser', 'element', 'locators', 'expectedConditions',
'config', 'plugins', 'ptor'];
var outputFile = path.resolve(folder, 'index.d.ts');
var contents = '';
contents += '/// <reference path="../typings/index.d.ts" />\n';
contents += '/// <reference path="./globals.d.ts" />\n';
contents += 'import {ActionSequence, By, WebDriver, WebElement, WebElementPromise, promise, promise as wdpromise, until} from \'selenium-webdriver\';\n';
files.forEach(function(file) {
contents += parseTypingsFile(folder, file);
});

// remove files with d.ts
glob.sync(folder + '/**/*.d.ts').forEach(function(file) {
fs.unlinkSync(path.resolve(file));
});

// write contents to 'built/index.d.ts'
fs.writeFileSync(outputFile, contents);
done();
});

var parseTypingsFile = function(folder, file) {
var fileContents = fs.readFileSync(path.resolve(folder, file + '.d.ts')).toString();
// Remove new lines inside types
fileContents = fileContents.replace(
/webdriver.promise.Promise<\{[a-zA-Z:,; \n]+\}>/g, function(type) {
return type.replace(/\n/g, '');
}
);
var lines = fileContents.split('\n');
var contents = '';
for (var linePos in lines) {
var line = lines[linePos];
if (!line.startsWith('import')) {
if (line.indexOf('declare') !== -1) {
line = line.replace('declare', '').trim();
}

// Remove webdriver types, q, http proxy agent
line = removeTypes(line,'webdriver.ActionSequence');
line = removeTypes(line,'webdriver.promise.Promise<[a-zA-Z{},:; ]+>');
line = removeTypes(line,'webdriver.util.Condition');
line = removeTypes(line,'webdriver.WebDriver');
line = removeTypes(line,'webdriver.Locator');
line = removeTypes(line,'webdriver.WebElement');
line = removeTypes(line,'HttpProxyAgent');
line = removeTypes(line,'Q.Promise<[a-zA-Z{},:; ]+>');
contents += line + '\n';
}
}
return contents;
}

var removeTypes = function(line, webdriverType) {
var tempLine = line.trim();
if (tempLine.startsWith('/**') || tempLine.startsWith('*')) {
return line;
}
return line.replace(new RegExp(webdriverType,'g'), 'any');
}

gulp.task('ambient', function(done) {
var fileContents = fs.readFileSync(path.resolve('built/index.d.ts')).toString();
var contents = '';
contents += 'declare namespace protractor {\n';
contents += fileContents + '\n';
contents += '}\n';
contents += 'declare module "protractor" {\n';

contents += ' export = protractor; \n';
contents += '}\n';
fs.writeFileSync(path.resolve('built/ambient.d.ts'), contents);
done();
});
60 changes: 37 additions & 23 deletions lib/browser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Util from NodeJs
import * as net from 'net';
import {ActionSequence, promise as wdpromise, until, WebDriver, WebElement} from 'selenium-webdriver';
import {ActionSequence, Capabilities, Command as WdCommand, FileDetector, Options, promise as wdpromise, Session, TargetLocator, TouchSequence, until, WebDriver, WebElement} from 'selenium-webdriver';

import * as url from 'url';
import * as util from 'util';

Expand Down Expand Up @@ -32,20 +33,37 @@ for (let foo in webdriver) {
exports[foo] = webdriver[foo];
}

// Explicitly define webdriver.WebDriver.
// Explicitly define webdriver.WebDriver
Copy link
Member

Choose a reason for hiding this comment

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

Please add a TODO to extend Webdriver from our typings for it.

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

// TODO: extend WebDriver from selenium-webdriver typings
export class Webdriver {
actions: () => ActionSequence = webdriver.WebDriver.actions;
actions: () => ActionSequence;
call:
(fn: (...var_args: any[]) => any, opt_scope?: any,
...var_args: any[]) => wdpromise.Promise<any>;
close: () => void;
controlFlow: () => wdpromise.ControlFlow;
executeScript:
(script: string|Function, ...var_args: any[]) => wdpromise.Promise<any>;
executeAsyncScript:
(script: string|Function, ...var_args: any[]) => wdpromise.Promise<any>;
getCapabilities: () => Capabilities;
getCurrentUrl: () => wdpromise.Promise<string>;
getPageSource: () => wdpromise.Promise<string>;
getSession: () => wdpromise.Promise<Session>;
getTitle: () => wdpromise.Promise<string>;
getWindowHandle: () => wdpromise.Promise<string>;
getAllWindowHandles: () => wdpromise.Promise<string[]>;
manage: () => Options;
quit: () => void;
schedule: (command: WdCommand, description: string) => wdpromise.Promise<any>;
setFileDetector: (detector: FileDetector) => void;
sleep: (ms: number) => wdpromise.Promise<void>;
switchTo: () => TargetLocator;
takeScreenshot: () => wdpromise.Promise<any>;
touchActions: () => TouchSequence;
wait:
(condition: wdpromise.Promise<any>|until.Condition<any>|Function,
opt_timeout?: number,
opt_message?:
string) => wdpromise.Promise<any> = webdriver.WebDriver.wait;
sleep: (ms: number) => wdpromise.Promise<any> = webdriver.WebDriver.sleep;
getCurrentUrl:
() => wdpromise.Promise<any> = webdriver.WebDriver.getCurrentUrl;
getTitle: () => wdpromise.Promise<any> = webdriver.WebDriver.getTitle;
takeScreenshot:
() => wdpromise.Promise<any> = webdriver.WebDriver.takeScreenshot;
opt_timeout?: number, opt_message?: string) => wdpromise.Promise<any>;
}

/**
Expand Down Expand Up @@ -268,7 +286,6 @@ export class ProtractorBrowser extends Webdriver {
// include functions which are overridden by protractor below.
let methodsToSync = ['getCurrentUrl', 'getPageSource', 'getTitle'];


// Mix all other driver functionality into Protractor.
Object.getOwnPropertyNames(webdriver.WebDriver.prototype)
.forEach((method: string) => {
Expand Down Expand Up @@ -298,7 +315,7 @@ export class ProtractorBrowser extends Webdriver {
this.resetUrl = DEFAULT_RESET_URL;
this.ng12Hybrid = false;

this.driver.getCapabilities().then((caps: webdriver.Capabilities) => {
this.driver.getCapabilities().then((caps: Capabilities) => {
// Internet Explorer does not accept data URLs, which are the default
// reset URL for Protractor.
// Safari accepts data urls, but SafariDriver fails after one is used.
Expand Down Expand Up @@ -492,7 +509,7 @@ export class ProtractorBrowser extends Webdriver {
'Timed out waiting for Protractor to synchronize with ' +
'the page after ' + timeout + '. Please see ' +
'https://github.com/angular/protractor/blob/master/docs/faq.md';
if (description.startsWith(' - Locator: ')) {
if (description.indexOf(' - Locator: ') == 0) {
errMsg +=
'\nWhile waiting for element with locator' + description;
}
Expand Down Expand Up @@ -572,7 +589,7 @@ export class ProtractorBrowser extends Webdriver {
* @returns {!webdriver.promise.Promise} A promise that will resolve to whether
* the element is present on the page.
*/
isElementPresent(locatorOrElement: webdriver.Locator|
isElementPresent(locatorOrElement: ProtractorBy|
webdriver.WebElement): webdriver.promise.Promise<any> {
let element = ((locatorOrElement as any).isPresent) ?
locatorOrElement :
Expand Down Expand Up @@ -757,17 +774,14 @@ export class ProtractorBrowser extends Webdriver {
'return window.location.href;', msg('get url'))
.then(
(url: any) => { return url !== this.resetUrl; },
(err: webdriver.ErrorCode) => {
(err: IError) => {
if (err.code == 13) {
// Ignore the error, and continue trying. This is
// because IE
// driver sometimes (~1%) will throw an unknown error
// from this
// execution. See
// because IE driver sometimes (~1%) will throw an
// unknown error from this execution. See
// https://github.com/angular/protractor/issues/841
// This shouldn't mask errors because it will fail
// with the timeout
// anyway.
// with the timeout anyway.
return false;
} else {
throw err;
Expand Down
Loading