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
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
- refactor gulpfile task 'types' to use multiple files from tsc
- add browser method types applied from webdriver

this closes #3430, closes #3477, and closes #3500
  • Loading branch information
cnishina committed Sep 7, 2016
1 parent c7fff5e commit 5a929e7
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 163 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
};
3 changes: 2 additions & 1 deletion exampleTypescript/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"sourceMap": false,
"declaration": false,
"noImplicitAny": false,
"outDir": "tmp"
"outDir": "tmp",
"types": ["node", "jasmine"]
},
"exclude": [
"node_modules",
Expand Down
85 changes: 11 additions & 74 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var runSpawn = function(done, task, opt_arg, opt_io) {
};

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

Expand Down Expand Up @@ -72,91 +72,28 @@ gulp.task('tsc:globals', function(done) {

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

gulp.task('pretest', function(done) {
runSequence(
['webdriver:update', 'jshint', 'format'], 'tsc', 'tsc:globals',
'types', 'ambient', 'built:copy', done);
'types', '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 outputFile = path.resolve('built', 'index.d.ts');
var contents = '';
contents += '/// <reference path="../../@types/node/index.d.ts" />\n';
contents += '/// <reference path="../../@types/jasmine/index.d.ts" />\n';
contents += '/// <reference path="../typings/index.d.ts" />\n';
contents += 'import {ActionSequence, By, WebDriver, WebElement, WebElementPromise, promise, promise as wdpromise, until} from \'selenium-webdriver\';\n';
files.forEach(file => {
contents += parseTypingsFile(folder, file);
});

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

// write contents to 'built/index.d.ts'
contents += '/// <reference path="./globals.d.ts" />\n';
contents += 'export { ElementHelper, ProtractorBrowser } from \'./browser\';\n';
contents += 'export { ElementArrayFinder, ElementFinder } from \'./element\';\n';
contents += 'export { ProtractorExpectedConditions } from \'./expectedConditions\';\n';
contents += 'export { ProtractorBy } from \'./locators\';\n';
contents += 'export { Config } from \'./config\';\n';
contents += 'export { Ptor } from \'./ptor\';\n';
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, (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();
});
57 changes: 43 additions & 14 deletions lib/browser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
// 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,18 +44,29 @@ for (let foo in webdriver) {
exports[foo] = webdriver[foo];
}

// Explicitly define webdriver.WebDriver.
// Explicitly define webdriver.WebDriver
export class Webdriver {
actions: () => ActionSequence = webdriver.WebDriver.actions;
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;
actions: () => ActionSequence;
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) => webdriver.promise.Promise<any>;
setFileDetector: (detector: FileDetector) => void;
sleep: (ms: number) => wdpromise.Promise<void>;
switchTo: () => TargetLocator;
touchActions: () => TouchSequence;
wait: (condition: wdpromise.Promise<any>|until.Condition<any>|Function,
opt_timeout?: number, opt_message?: string) => wdpromise.Promise<any>;
takeScreenshot:
() => wdpromise.Promise<any> = webdriver.WebDriver.takeScreenshot;
}
Expand Down Expand Up @@ -266,7 +289,13 @@ export class ProtractorBrowser extends Webdriver {
// 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.
let methodsToSync = ['getCurrentUrl', 'getPageSource', 'getTitle'];
let methodsToSync = [
'actions', 'close', 'controlFlow', 'executeScript', 'executeAsyncScript',
'getCapabilities', 'getCurrentUrl', 'getPageSource', 'getSession',
'getTitle', 'getWindowHandle', 'getAllWindowHandles', 'manage', 'quit',
'schedule', 'setFileDetector', 'sleep', 'switchTo', 'touchActions',
'touchSequence', 'wait'
];


// Mix all other driver functionality into Protractor.
Expand Down Expand Up @@ -572,7 +601,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
Loading

0 comments on commit 5a929e7

Please sign in to comment.