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

Commit

Permalink
chore(types): clean up TypeScript support (#3520)
Browse files Browse the repository at this point in the history
- fix exampleTypescript to have noGlobals
- change the exampleTypescript tsconfig.json to include @types
- alias promise as wdpromise everywhere
- add browser method types applied from webdriver
- remove gulpfile 'types' task
- remove webdriver namespace from globals.d.ts

this closes #3430, closes #3477, and closes #3500
  • Loading branch information
cnishina authored Sep 13, 2016
1 parent 9be4b75 commit 11c9418
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 189 deletions.
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
// 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

0 comments on commit 11c9418

Please sign in to comment.