diff --git a/lib/browser.ts b/lib/browser.ts index ca47fd075..7c4bc7a58 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -10,7 +10,6 @@ import {Logger} from './logger'; import {Plugins} from './plugins'; const clientSideScripts = require('./clientsidescripts'); -const webdriver = require('selenium-webdriver'); // TODO: fix the typings for selenium-webdriver/lib/command const Command = require('selenium-webdriver/lib/command').Command as typeof WdCommand; const CommandName = require('selenium-webdriver/lib/command').Name as ICommandName; @@ -23,11 +22,14 @@ const DEFAULT_GET_PAGE_TIMEOUT = 10000; let logger = new Logger('protractor'); +// TODO(cnishina): either remove for loop entirely since this does not export anything +// the user might need since everything is composed (with caveat that this could be a +// potential breaking change) or export the types with `export * from 'selenium-webdriver'`; /* * Mix in other webdriver functionality to be accessible via protractor. */ -for (let foo in webdriver) { - exports[foo] = webdriver[foo]; +for (let foo in require('selenium-webdriver')) { + exports[foo] = require('selenium-webdriver')[foo]; } // Explicitly define webdriver.WebDriver diff --git a/lib/debugger.ts b/lib/debugger.ts index cb7f55d2f..6827a26d1 100644 --- a/lib/debugger.ts +++ b/lib/debugger.ts @@ -12,7 +12,6 @@ declare var global: any; declare var process: any; let logger = new Logger('protractor'); -const webdriver = require('selenium-webdriver'); export class DebugHelper { /** @@ -40,7 +39,7 @@ export class DebugHelper { * process. */ init(debuggerClientPath: string, onStartFn: Function, opt_debugPort?: number) { - webdriver.promise.ControlFlow.prototype.getControlFlowText = function() { + (wdpromise.ControlFlow as any).prototype.getControlFlowText = function() { let controlFlowText = this.getSchedule(/* opt_includeStackTraces */ true); // This filters the entire control flow text, not just the stack trace, so // unless we maintain a good (i.e. non-generic) set of keywords in @@ -52,8 +51,8 @@ export class DebugHelper { return helper.filterStackTrace(controlFlowText); }; - let vm_ = require('vm'); - let flow = webdriver.promise.controlFlow(); + const vm_ = require('vm'); + let flow = wdpromise.controlFlow(); interface Context { require: any; @@ -76,7 +75,7 @@ export class DebugHelper { } let sandbox = vm_.createContext(context); - let debuggerReadyPromise = webdriver.promise.defer(); + let debuggerReadyPromise = wdpromise.defer(); flow.execute(() => { process['debugPort'] = opt_debugPort || process['debugPort']; this.validatePortAvailability_(process['debugPort']).then((firstTime: boolean) => { @@ -161,8 +160,8 @@ export class DebugHelper { // Run code through vm so that we can maintain a local scope which is // isolated from the rest of the execution. let res = vm_.runInContext(code, sandbox); - if (!webdriver.promise.isPromise(res)) { - res = webdriver.promise.fulfilled(res); + if (!wdpromise.isPromise(res)) { + res = wdpromise.fulfilled(res); } return res.then((res: any) => { @@ -171,8 +170,7 @@ export class DebugHelper { } else { // The '' forces res to be expanded into a string instead of just // '[Object]'. Then we remove the extra space caused by the '' - // using - // substring. + // using substring. return util.format.apply(this, ['', res]).substring(1); } }); @@ -184,7 +182,7 @@ export class DebugHelper { // Result is a JSON representation of the autocomplete response. complete: function(line: string) { let execFn_ = () => { - let deferred = webdriver.promise.defer(); + let deferred = wdpromise.defer(); this.replServer_.complete(line, (err: any, res: any) => { if (err) { deferred.reject(err); @@ -234,7 +232,7 @@ export class DebugHelper { return wdpromise.fulfilled(false); } - let doneDeferred = webdriver.promise.defer(); + let doneDeferred = wdpromise.defer(); // Resolve doneDeferred if port is available. let tester = net.connect({port: port}, () => { diff --git a/lib/driverProviders/local.ts b/lib/driverProviders/local.ts index 3eff1e319..3328cce5c 100644 --- a/lib/driverProviders/local.ts +++ b/lib/driverProviders/local.ts @@ -65,7 +65,7 @@ export class Local extends DriverProvider { throw new BrowserError( logger, 'Could not find chromedriver at ' + this.config_.chromeDriver + - '. Run \'webdriver-manager update\' to download binaries.');); + '. Run \'webdriver-manager update\' to download binaries.'); } } } diff --git a/lib/element.ts b/lib/element.ts index 0455603ca..7d16810b7 100644 --- a/lib/element.ts +++ b/lib/element.ts @@ -1,11 +1,10 @@ -import {By, error, ILocation, ISize, promise as wdpromise, WebDriver, WebElement, WebElementPromise} from 'selenium-webdriver'; +import {By, error as wderror, ILocation, ISize, promise as wdpromise, WebDriver, WebElement, WebElementPromise} from 'selenium-webdriver'; import {ElementHelper, ProtractorBrowser} from './browser'; import {IError} from './exitCodes'; import {Locator} from './locators'; import {Logger} from './logger'; -let webdriver = require('selenium-webdriver'); let clientSideScripts = require('./clientsidescripts'); let logger = new Logger('element'); @@ -239,7 +238,7 @@ export class ElementArrayFinder extends WebdriverWebElement { return filterFn(elementFinder, index); }); - return webdriver.promise.all(list).then((resolvedList: any) => { + return wdpromise.all(list).then((resolvedList: any) => { return parentWebElements.filter((parentWebElement: WebElement, index: number) => { return resolvedList[index]; }); @@ -276,21 +275,16 @@ export class ElementArrayFinder extends WebdriverWebElement { * @param {number|webdriver.promise.Promise} index Element index. * @returns {ElementFinder} finder representing element at the given index. */ - get(index: number): ElementFinder { - let getWebElements = () => { - return webdriver.promise.all([index, this.getWebElements()]).then((results: any) => { - let i = results[0]; - let parentWebElements = results[1]; - + get(index: number|wdpromise.Promise): ElementFinder { + let getWebElements = (): wdpromise.Promise => { + return wdpromise.all([index, this.getWebElements()]).then(([i, parentWebElements]) => { if (i < 0) { - // wrap negative indices - i = parentWebElements.length + i; + i += parentWebElements.length; } if (i < 0 || i >= parentWebElements.length) { - throw new error.NoSuchElementError( - 'Index out of bound. ' + - 'Trying to access element at index: ' + index + ', but there are ' + - 'only ' + parentWebElements.length + ' elements that match ' + + throw new wderror.NoSuchElementError( + 'Index out of bound. Trying to access element at index: ' + index + + ', but there are only ' + parentWebElements.length + ' elements that match ' + 'locator ' + this.locator_.toString()); } return [parentWebElements[i]]; @@ -383,7 +377,7 @@ export class ElementArrayFinder extends WebdriverWebElement { * array of the located {@link webdriver.WebElement}s. */ $$(selector: string): ElementArrayFinder { - return this.all(webdriver.By.css(selector)); + return this.all(By.css(selector)); } /** @@ -427,7 +421,7 @@ export class ElementArrayFinder extends WebdriverWebElement { return arr.length; }, (err: IError) => { - if (err.code && err.code == new webdriver.error.NoSuchElementError()) { + if (err.code && err.code == (new wderror.NoSuchSessionError() as any).code) { return 0; } else { throw err; @@ -821,7 +815,7 @@ export class ElementFinder extends WebdriverWebElement { let getWebElements = (): wdpromise.Promise => { return elementArrayFinder.getWebElements().then((webElements: WebElement[]) => { if (webElements.length === 0) { - throw new error.NoSuchElementError( + throw new wderror.NoSuchElementError( 'No element found using locator: ' + elementArrayFinder.locator().toString()); } else { if (webElements.length > 1) { @@ -999,7 +993,7 @@ export class ElementFinder extends WebdriverWebElement { * @returns {ElementArrayFinder} */ $$(selector: string): ElementArrayFinder { - return this.all(webdriver.By.css(selector)); + return this.all(By.css(selector)); } /** @@ -1041,7 +1035,7 @@ export class ElementFinder extends WebdriverWebElement { * @returns {ElementFinder} */ $(selector: string): ElementFinder { - return this.element(webdriver.By.css(selector)); + return this.element(By.css(selector)); } /** @@ -1071,7 +1065,7 @@ export class ElementFinder extends WebdriverWebElement { return true; // is present, whether it is enabled or not }, (err: any) => { - if (err.code == webdriver.error.ErrorCode.STALE_ELEMENT_REFERENCE) { + if (err.code == (new wderror.StaleElementReferenceError() as any).code) { return false; } else { throw err; @@ -1079,7 +1073,7 @@ export class ElementFinder extends WebdriverWebElement { }); }, (err: any) => { - if (err.code == webdriver.error.ErrorCode.NO_SUCH_ELEMENT) { + if (err.code == (new wderror.NoSuchElementError() as any).code) { return false; } else { throw err; diff --git a/lib/expectedConditions.ts b/lib/expectedConditions.ts index 87242ec70..483e982aa 100644 --- a/lib/expectedConditions.ts +++ b/lib/expectedConditions.ts @@ -1,8 +1,7 @@ +import {error as wderror} from 'selenium-webdriver'; import {ProtractorBrowser} from './browser'; import {ElementFinder} from './element'; -const webdriver = require('selenium-webdriver'); - /** * Represents a library of canned expected conditions that are useful for * protractor, especially when dealing with non-angular apps. @@ -161,7 +160,7 @@ export class ProtractorExpectedConditions { return true; }, (err: any) => { - if (err.code == webdriver.error.ErrorCode.NO_SUCH_ALERT) { + if (err.code == (new wderror.NoSuchAlertError() as any).code) { return false; } else { throw err; diff --git a/lib/locators.ts b/lib/locators.ts index 9f97fd486..5dbe7d7f3 100644 --- a/lib/locators.ts +++ b/lib/locators.ts @@ -1,20 +1,19 @@ import {By, promise as wdpromise, WebDriver, WebElement} from 'selenium-webdriver'; -const webdriver = require('selenium-webdriver'); let clientSideScripts = require('./clientsidescripts'); // Explicitly define webdriver.By. export class WebdriverBy { - className: (className: string) => By = webdriver.By.className; - css: (css: string) => By = webdriver.By.css; - id: (id: string) => By = webdriver.By.id; - linkText: (linkText: string) => By = webdriver.By.linkText; - js: (js: string) => By = webdriver.By.js; - name: (name: string) => By = webdriver.By.name; - partialLinkText: (partialText: string) => By = webdriver.By.partialLinkText; - tagName: (tagName: string) => By = webdriver.By.tagName; - xpath: (xpath: string) => By = webdriver.By.xpath; + className: (className: string) => By = By.className; + css: (css: string) => By = By.css; + id: (id: string) => By = By.id; + linkText: (linkText: string) => By = By.linkText; + js: (js: string) => By = By.js; + name: (name: string) => By = By.name; + partialLinkText: (partialText: string) => By = By.partialLinkText; + tagName: (tagName: string) => By = By.tagName; + xpath: (xpath: string) => By = By.xpath; } // Protractor locator strategy @@ -83,7 +82,7 @@ export class ProtractorBy extends WebdriverBy { findElementArguments.push(using); findElementArguments.push(rootSelector); - return driver.findElements(webdriver.By.js.apply(webdriver.By, findElementArguments)); + return driver.findElements(By.js.apply(By, findElementArguments)); }, toString: (): string => { return 'by.' + name + '("' + Array.prototype.join.call(locatorArguments, '", "') + '")'; @@ -126,8 +125,8 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( - clientSideScripts.findBindings, bindingDescriptor, false, using, rootSelector)); + return driver.findElements( + By.js(clientSideScripts.findBindings, bindingDescriptor, false, using, rootSelector)); }, toString: (): string => { return 'by.binding("' + bindingDescriptor + '")'; @@ -158,8 +157,8 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( - clientSideScripts.findBindings, bindingDescriptor, true, using, rootSelector)); + return driver.findElements( + By.js(clientSideScripts.findBindings, bindingDescriptor, true, using, rootSelector)); }, toString: (): string => { return 'by.exactBinding("' + bindingDescriptor + '")'; @@ -187,7 +186,7 @@ export class ProtractorBy extends WebdriverBy { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { return driver.findElements( - webdriver.By.js(clientSideScripts.findByModel, model, using, rootSelector)); + By.js(clientSideScripts.findByModel, model, using, rootSelector)); }, toString: (): string => { return 'by.model("' + model + '")'; @@ -212,7 +211,7 @@ export class ProtractorBy extends WebdriverBy { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { return driver.findElements( - webdriver.By.js(clientSideScripts.findByButtonText, searchText, using, rootSelector)); + By.js(clientSideScripts.findByButtonText, searchText, using, rootSelector)); }, toString: (): string => { return 'by.buttonText("' + searchText + '")'; @@ -236,8 +235,8 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( - clientSideScripts.findByPartialButtonText, searchText, using, rootSelector)); + return driver.findElements( + By.js(clientSideScripts.findByPartialButtonText, searchText, using, rootSelector)); }, toString: (): string => { return 'by.partialButtonText("' + searchText + '")'; @@ -251,7 +250,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findAllRepeaterRows, repeatDescriptor, exact, using, rootSelector)); }, toString: (): string => { @@ -261,7 +260,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findRepeaterRows, repeatDescriptor, exact, index, using, rootSelector)); }, @@ -272,7 +271,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findRepeaterElement, repeatDescriptor, exact, index, binding, using, rootSelector)); }, @@ -288,7 +287,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findRepeaterColumn, repeatDescriptor, exact, binding, using, rootSelector)); }, @@ -299,7 +298,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findRepeaterElement, repeatDescriptor, exact, index, binding, using, rootSelector)); }, @@ -415,7 +414,7 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( + return driver.findElements(By.js( clientSideScripts.findByCssContainingText, cssSelector, searchText, using, rootSelector)); }, @@ -448,8 +447,8 @@ export class ProtractorBy extends WebdriverBy { return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { - return driver.findElements(webdriver.By.js( - clientSideScripts.findByOptions, optionsDescriptor, using, rootSelector)); + return driver.findElements( + By.js(clientSideScripts.findByOptions, optionsDescriptor, using, rootSelector)); }, toString: (): string => { return 'by.option("' + optionsDescriptor + '")'; @@ -481,6 +480,6 @@ export class ProtractorBy extends WebdriverBy { deepCss(selector: string): Locator { // TODO(julie): syntax will change from /deep/ to >>> at some point. // When that is supported, switch it here. - return webdriver.By.css('* /deep/ ' + selector); + return By.css('* /deep/ ' + selector); }; } diff --git a/lib/ptor.ts b/lib/ptor.ts index 69f85cbae..f8c7af88b 100644 --- a/lib/ptor.ts +++ b/lib/ptor.ts @@ -1,5 +1,6 @@ -import {ActionSequence, Browser, Builder, Button, Capabilities, Capability, Command, CommandName, error, EventEmitter, FileDetector, Key, logging, promise, Session, until, WebDriver, WebElement, WebElementPromise} from 'selenium-webdriver'; -import * as chrome from 'selenium-webdriver/firefox'; +import * as webdriver from 'selenium-webdriver'; +import * as chrome from 'selenium-webdriver/chrome'; +import * as firefox from 'selenium-webdriver/firefox'; import * as http from 'selenium-webdriver/http'; import * as remote from 'selenium-webdriver/remote'; @@ -8,8 +9,6 @@ import {ElementArrayFinder, ElementFinder} from './element'; import {ProtractorExpectedConditions} from './expectedConditions'; import {ProtractorBy} from './locators'; -let webdriver = require('selenium-webdriver'); - export class Ptor { // Variables tied to the global namespace. browser: ProtractorBrowser; @@ -23,7 +22,7 @@ export class Ptor { By: ProtractorBy; by: ProtractorBy; wrapDriver: - (webdriver: WebDriver, baseUrl?: string, rootElement?: string, + (webdriver: webdriver.WebDriver, baseUrl?: string, rootElement?: string, untrackOutstandingTimeouts?: boolean) => ProtractorBrowser; ExpectedConditions: ProtractorExpectedConditions; @@ -54,11 +53,7 @@ export class Ptor { until = webdriver.until; Command = require('selenium-webdriver/lib/command').Command; CommandName = require('selenium-webdriver/lib/command').Name; - utils = { - firefox: require('selenium-webdriver/firefox'), - http: require('selenium-webdriver/http'), - remote: require('selenium-webdriver/remote') - }; + utils = {firefox: firefox, http: http, remote: remote, chrome: chrome}; } export let protractor = new Ptor(); diff --git a/lib/runner.ts b/lib/runner.ts index 8aaac4a83..38da964da 100644 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -1,6 +1,6 @@ import {EventEmitter} from 'events'; import * as q from 'q'; -import {Session} from 'selenium-webdriver'; +import {promise as wdpromise, Session} from 'selenium-webdriver'; import * as util from 'util'; import {ProtractorBrowser} from './browser'; @@ -14,7 +14,6 @@ import * as helper from './util'; declare let global: any; declare let process: any; -const webdriver = require('selenium-webdriver'); let logger = new Logger('runner'); /* * Runner is responsible for starting the execution of a test run and triggering @@ -45,7 +44,7 @@ export class Runner extends EventEmitter { if (config.nodeDebug) { process['_debugProcess'](process.pid); - let flow = webdriver.promise.controlFlow(); + let flow = wdpromise.controlFlow(); flow.execute(() => { let nodedebug = require('child_process').fork('debug', ['localhost:5858']); @@ -151,7 +150,7 @@ export class Runner extends EventEmitter { * @return {Object} WebDriver control flow. */ controlFlow(): any { - return webdriver.promise.controlFlow(); + return wdpromise.controlFlow(); } /** @@ -232,7 +231,7 @@ export class Runner extends EventEmitter { browser_.ready = driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout); browser_.getProcessedConfig = () => { - return webdriver.promise.fulfilled(config); + return wdpromise.fulfilled(config); }; browser_.forkNewDriverInstance = (opt_useSameUrl: boolean, opt_copyMockModules: boolean) => { diff --git a/package.json b/package.json index e36aa317c..b37d4c74b 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@types/jasmine": "^2.5.36", "@types/node": "^6.0.46", "@types/q": "^0.0.32", - "@types/selenium-webdriver": "2.53.31", + "@types/selenium-webdriver": "2.53.37", "adm-zip": "0.4.7", "chalk": "^1.1.3", "glob": "^7.0.3",