protractor
Advanced tools
Comparing version 5.4.2 to 6.0.0-beta
/// <reference types="node" /> | ||
/// <reference types="q" /> | ||
import { ChildProcess } from 'child_process'; | ||
import * as q from 'q'; | ||
import { Config } from './config'; | ||
@@ -11,4 +9,4 @@ export declare class BlockingProxyRunner { | ||
constructor(config: Config); | ||
start(): q.Promise<{}>; | ||
start(): Promise<{}>; | ||
checkSupportedConfig(): void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const child_process_1 = require("child_process"); | ||
const q = require("q"); | ||
const logger_1 = require("./logger"); | ||
@@ -13,3 +12,3 @@ const BP_PATH = require.resolve('blocking-proxy/built/lib/bin.js'); | ||
start() { | ||
return q.Promise((resolve, reject) => { | ||
return new Promise((resolve, reject) => { | ||
this.checkSupportedConfig(); | ||
@@ -16,0 +15,0 @@ let args = [ |
import { BPClient } from 'blocking-proxy'; | ||
import { Navigation, promise as wdpromise, WebDriver, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
import { Navigation, WebDriver, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
import { ExtendedWebDriver } from 'webdriver-js-extender'; | ||
import { DebugHelper } from './debugger'; | ||
import { ElementArrayFinder, ElementFinder } from './element'; | ||
@@ -27,3 +26,3 @@ import { ProtractorExpectedConditions } from './expectedConditions'; | ||
* @param {string=} opt_baseUrl A base URL to run get requests against. | ||
* @param {string|webdriver.promise.Promise<string>=} opt_rootElement Selector element that has an | ||
* @param {string|Promise<string>=} opt_rootElement Selector element that has an | ||
* ng-app in scope. | ||
@@ -96,10 +95,6 @@ * @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should | ||
* | ||
* The change will be made within WebDriver's control flow, so that commands after | ||
* this method is called use the new app root. Pass nothing to get a promise that | ||
* resolves to the value of the selector. | ||
* | ||
* @param {string|webdriver.promise.Promise<string>} value The new selector. | ||
* @param {string|Promise<string>} valuePromise The new selector. | ||
* @returns A promise that resolves with the value of the selector. | ||
*/ | ||
angularAppRoot(value?: string | wdpromise.Promise<string>): wdpromise.Promise<string>; | ||
angularAppRoot(valuePromise?: string | Promise<string>): Promise<string>; | ||
/** | ||
@@ -114,8 +109,9 @@ * If true, Protractor will not attempt to synchronize with the page before | ||
* | ||
* This property is deprecated - please use waitForAngularEnabled instead. | ||
* ignoreSynchornization is deprecated. | ||
* | ||
* Please use waitForAngularEnabled instead. | ||
* | ||
* @deprecated | ||
* @type {boolean} | ||
*/ | ||
ignoreSynchronization: boolean; | ||
private internalIgnoreSynchronization; | ||
@@ -138,9 +134,9 @@ /** | ||
* | ||
* forkedBrowser = await browser.forkNewDriverInstance().ready; | ||
* forkedBrowser = await browser.forkNewDriverInstance(); | ||
* | ||
* Set by the runner. | ||
* | ||
* @type {webdriver.promise.Promise.<ProtractorBrowser>} | ||
* @type {Promise<ProtractorBrowser>} | ||
*/ | ||
ready: wdpromise.Promise<ProtractorBrowser>; | ||
ready: Promise<ProtractorBrowser>; | ||
plugins_: Plugins; | ||
@@ -185,8 +181,4 @@ /** | ||
ng12Hybrid: boolean; | ||
/** | ||
* A helper that manages debugging tests. | ||
*/ | ||
debugHelper: DebugHelper; | ||
[key: string]: any; | ||
constructor(webdriverInstance: WebDriver, opt_baseUrl?: string, opt_rootElement?: string | wdpromise.Promise<string>, opt_untrackOutstandingTimeouts?: boolean, opt_blockingProxyUrl?: string); | ||
constructor(webdriverInstance: WebDriver, opt_baseUrl?: string, opt_rootElement?: string | Promise<string>, opt_untrackOutstandingTimeouts?: boolean, opt_blockingProxyUrl?: string); | ||
/** | ||
@@ -201,3 +193,3 @@ * If set to false, Protractor will not wait for Angular $http and $timeout | ||
*/ | ||
waitForAngularEnabled(enabled?: boolean | wdpromise.Promise<boolean>): wdpromise.Promise<boolean>; | ||
waitForAngularEnabled(enabledPromise?: boolean | Promise<boolean>): Promise<boolean>; | ||
/** | ||
@@ -210,6 +202,6 @@ * Get the processed configuration object that is currently being run. This | ||
* | ||
* @returns {webdriver.promise.Promise} A promise which resolves to the | ||
* @returns {Promise} A promise which resolves to the | ||
* capabilities object. | ||
*/ | ||
getProcessedConfig(): wdpromise.Promise<any>; | ||
getProcessedConfig(): Promise<any>; | ||
/** | ||
@@ -219,8 +211,3 @@ * Fork another instance of browser for use in interactive tests. | ||
* @example | ||
* // Running with control flow enabled | ||
* var fork = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); // 'page1' gotten by forked browser | ||
* | ||
* // Running with control flow disabled | ||
* var forked = await browser.forkNewDriverInstance().ready; | ||
* var forked = await browser.forkNewDriverInstance(); | ||
* await forked.get('page1'); // 'page1' gotten by forked browser | ||
@@ -235,3 +222,3 @@ * | ||
*/ | ||
forkNewDriverInstance(useSameUrl?: boolean, copyMockModules?: boolean, copyConfigUpdates?: boolean): ProtractorBrowser; | ||
forkNewDriverInstance(useSameUrl?: boolean, copyMockModules?: boolean, copyConfigUpdates?: boolean): Promise<ProtractorBrowser>; | ||
/** | ||
@@ -246,16 +233,6 @@ * Restart the browser. This is done by closing this browser instance and creating a new one. | ||
* | ||
* This function behaves slightly differently depending on if the webdriver control flow is | ||
* enabled. If the control flow is enabled, the global `browser` object is synchronously | ||
* replaced. If the control flow is disabled, the global `browser` is replaced asynchronously | ||
* after the old driver quits. | ||
* | ||
* Set by the runner. | ||
* | ||
* @example | ||
* // Running against global browser, with control flow enabled | ||
* browser.get('page1'); | ||
* browser.restart(); | ||
* browser.get('page2'); // 'page2' gotten by restarted browser | ||
* | ||
* // Running against global browser, with control flow disabled | ||
* // Running against global browser | ||
* await browser.get('page1'); | ||
@@ -265,12 +242,4 @@ * await browser.restart(); | ||
* | ||
* // Running against forked browsers, with the control flow enabled | ||
* // In this case, you may prefer `restartSync` (documented below) | ||
* var forked = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); | ||
* fork.restart().then(function(fork) { | ||
* fork.get('page2'); // 'page2' gotten by restarted fork | ||
* }); | ||
* | ||
* // Running against forked browsers, with the control flow disabled | ||
* var forked = await browser.forkNewDriverInstance().ready; | ||
* // Running against forked browsers | ||
* var forked = await browser.forkNewDriverInstance(); | ||
* await fork.get('page1'); | ||
@@ -287,27 +256,7 @@ * fork = await fork.restart(); | ||
* | ||
* @returns {webdriver.promise.Promise<ProtractorBrowser>} A promise resolving to the restarted | ||
* @returns {Promise<ProtractorBrowser>} A promise resolving to the restarted | ||
* browser | ||
*/ | ||
restart(): wdpromise.Promise<ProtractorBrowser>; | ||
restart(): Promise<ProtractorBrowser>; | ||
/** | ||
* Like `restart`, but instead of returning a promise resolving to the new browser instance, | ||
* returns the new browser instance directly. Can only be used when the control flow is enabled. | ||
* | ||
* @example | ||
* // Running against global browser | ||
* browser.get('page1'); | ||
* browser.restartSync(); | ||
* browser.get('page2'); // 'page2' gotten by restarted browser | ||
* | ||
* // Running against forked browsers | ||
* var forked = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); | ||
* fork = fork.restartSync(); | ||
* fork.get('page2'); // 'page2' gotten by restarted fork | ||
* | ||
* @throws {TypeError} Will throw an error if the control flow is not enabled | ||
* @returns {ProtractorBrowser} The restarted browser | ||
*/ | ||
restartSync(): ProtractorBrowser; | ||
/** | ||
* Instead of using a single root element, search through all angular apps | ||
@@ -326,7 +275,7 @@ * available on the page when finding elements or waiting for stability. | ||
* @param {...*} var_args The arguments to pass to the script. | ||
* @returns {!webdriver.promise.Promise.<T>} A promise that will resolve to | ||
* @returns {!Promise<T>} A promise that will resolve to | ||
* the scripts return value. | ||
* @template T | ||
*/ | ||
executeScriptWithDescription(script: string | Function, description: string, ...scriptArgs: any[]): wdpromise.Promise<any>; | ||
executeScriptWithDescription(script: string | Function, description: string, ...scriptArgs: any[]): Promise<any>; | ||
/** | ||
@@ -340,3 +289,3 @@ * The same as {@code webdriver.WebDriver.prototype.executeAsyncScript}, | ||
* @param {...*} var_args The arguments to pass to the script. | ||
* @returns {!webdriver.promise.Promise.<T>} A promise that will resolve to | ||
* @returns {!Promise<T>} A promise that will resolve to | ||
* the | ||
@@ -346,3 +295,3 @@ * scripts return value. | ||
*/ | ||
private executeAsyncScript_(script, description, ...scriptArgs); | ||
private executeAsyncScript_; | ||
/** | ||
@@ -356,6 +305,6 @@ * Instruct webdriver to wait until Angular has finished rendering and has | ||
* to webdriver logs. | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve to the | ||
* @returns {!Promise} A promise that will resolve to the | ||
* scripts return value. | ||
*/ | ||
waitForAngular(opt_description?: string): wdpromise.Promise<any>; | ||
waitForAngular(opt_description?: string): Promise<any>; | ||
/** | ||
@@ -371,13 +320,13 @@ * Waits for Angular to finish rendering before searching for elements. | ||
* @see webdriver.WebDriver.findElements | ||
* @returns {!webdriver.promise.Promise} A promise that will be resolved to an | ||
* @returns {!Promise} A promise that will be resolved to an | ||
* array of the located {@link webdriver.WebElement}s. | ||
*/ | ||
findElements(locator: Locator): wdpromise.Promise<WebElement[]>; | ||
findElements(locator: Locator): Promise<WebElement[]>; | ||
/** | ||
* Tests if an element is present on the page. | ||
* @see webdriver.WebDriver.isElementPresent | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve to whether | ||
* @returns {!Promise} A promise that will resolve to whether | ||
* the element is present on the page. | ||
*/ | ||
isElementPresent(locatorOrElement: Locator | WebElement | ElementFinder): wdpromise.Promise<any>; | ||
isElementPresent(locatorOrElement: Locator | WebElement | ElementFinder): Promise<any>; | ||
/** | ||
@@ -426,3 +375,3 @@ * Add a module to load before Angular whenever Protractor.get is called. | ||
*/ | ||
private addBaseMockModules_(); | ||
private addBaseMockModules_; | ||
/** | ||
@@ -437,4 +386,4 @@ * @see webdriver.WebDriver.get | ||
* @example | ||
* browser.get('https://angularjs.org/'); | ||
* expect(browser.getCurrentUrl()).toBe('https://angularjs.org/'); | ||
* await browser.get('https://angularjs.org/'); | ||
* expect(await browser.getCurrentUrl()).toBe('https://angularjs.org/'); | ||
* | ||
@@ -445,3 +394,3 @@ * @param {string} destination Destination URL. | ||
*/ | ||
get(destination: string, timeout?: number): wdpromise.Promise<any>; | ||
get(destination: string, timeout?: number): Promise<void>; | ||
/** | ||
@@ -457,3 +406,3 @@ * @see webdriver.WebDriver.refresh | ||
*/ | ||
refresh(opt_timeout?: number): wdpromise.Promise<any>; | ||
refresh(opt_timeout?: number): Promise<void>; | ||
/** | ||
@@ -468,12 +417,12 @@ * Mixin navigation methods back into the navigation object so that | ||
* @example | ||
* browser.get('http://angular.github.io/protractor/#/tutorial'); | ||
* browser.setLocation('api'); | ||
* expect(browser.getCurrentUrl()) | ||
* await browser.get('http://angular.github.io/protractor/#/tutorial'); | ||
* await browser.setLocation('api'); | ||
* expect(await browser.getCurrentUrl()) | ||
* .toBe('http://angular.github.io/protractor/#/api'); | ||
* | ||
* @param {string} url In page URL using the same syntax as $location.url() | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve once | ||
* @returns {!Promise} A promise that will resolve once | ||
* page has been changed. | ||
*/ | ||
setLocation(url: string): wdpromise.Promise<any>; | ||
setLocation(url: string): Promise<any>; | ||
/** | ||
@@ -488,70 +437,10 @@ * Deprecated, use `browser.getCurrentUrl()` instead. | ||
* @example | ||
* browser.get('http://angular.github.io/protractor/#/api'); | ||
* expect(browser.getLocationAbsUrl()) | ||
* await browser.get('http://angular.github.io/protractor/#/api'); | ||
* expect(await browser.getLocationAbsUrl()) | ||
* .toBe('http://angular.github.io/protractor/#/api'); | ||
* @returns {webdriver.promise.Promise<string>} The current absolute url from | ||
* @returns {Promise<string>} The current absolute url from | ||
* AngularJS. | ||
*/ | ||
getLocationAbsUrl(): wdpromise.Promise<any>; | ||
getLocationAbsUrl(): Promise<any>; | ||
/** | ||
* Adds a task to the control flow to pause the test and inject helper | ||
* functions | ||
* into the browser, so that debugging may be done in the browser console. | ||
* | ||
* This should be used under node in debug mode, i.e. with | ||
* protractor debug <configuration.js> | ||
* | ||
* @example | ||
* While in the debugger, commands can be scheduled through webdriver by | ||
* entering the repl: | ||
* debug> repl | ||
* > element(by.input('user')).sendKeys('Laura'); | ||
* > browser.debugger(); | ||
* Press Ctrl + c to leave debug repl | ||
* debug> c | ||
* | ||
* This will run the sendKeys command as the next task, then re-enter the | ||
* debugger. | ||
*/ | ||
debugger(): wdpromise.Promise<void>; | ||
/** | ||
* See browser.explore(). | ||
*/ | ||
enterRepl(opt_debugPort?: number): void; | ||
/** | ||
* Beta (unstable) explore function for entering the repl loop from | ||
* any point in the control flow. Use browser.explore() in your test. | ||
* Does not require changes to the command line (no need to add 'debug'). | ||
* Note, if you are wrapping your own instance of Protractor, you must | ||
* expose globals 'browser' and 'protractor' for pause to work. | ||
* | ||
* @example | ||
* element(by.id('foo')).click(); | ||
* browser.explore(); | ||
* // Execution will stop before the next click action. | ||
* element(by.id('bar')).click(); | ||
* | ||
* @param {number=} opt_debugPort Optional port to use for the debugging | ||
* process | ||
*/ | ||
explore(opt_debugPort?: number): void; | ||
/** | ||
* Beta (unstable) pause function for debugging webdriver tests. Use | ||
* browser.pause() in your test to enter the protractor debugger from that | ||
* point in the control flow. | ||
* Does not require changes to the command line (no need to add 'debug'). | ||
* Note, if you are wrapping your own instance of Protractor, you must | ||
* expose globals 'browser' and 'protractor' for pause to work. | ||
* | ||
* @example | ||
* element(by.id('foo')).click(); | ||
* browser.pause(); | ||
* // Execution will stop before the next click action. | ||
* element(by.id('bar')).click(); | ||
* | ||
* @param {number=} opt_debugPort Optional port to use for the debugging | ||
* process | ||
*/ | ||
pause(opt_debugPort?: number): wdpromise.Promise<any>; | ||
/** | ||
* Determine if the control flow is enabled. | ||
@@ -558,0 +447,0 @@ * |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -7,3 +15,2 @@ const blocking_proxy_1 = require("blocking-proxy"); | ||
const webdriver_js_extender_1 = require("webdriver-js-extender"); | ||
const debugger_1 = require("./debugger"); | ||
const element_1 = require("./element"); | ||
@@ -21,3 +28,3 @@ const expectedConditions_1 = require("./expectedConditions"); | ||
const DEFAULT_GET_PAGE_TIMEOUT = 10000; | ||
let logger = new logger_1.Logger('protractor'); | ||
let logger = new logger_1.Logger('browser'); | ||
// TODO(cnishina): either remove for loop entirely since this does not export anything | ||
@@ -72,3 +79,2 @@ // the user might need since everything is composed (with caveat that this could be a | ||
} | ||
; | ||
/** | ||
@@ -90,3 +96,2 @@ * Build the helper 'element' function for a given instance of Browser. | ||
} | ||
; | ||
/** | ||
@@ -98,3 +103,3 @@ * @alias browser | ||
* @param {string=} opt_baseUrl A base URL to run get requests against. | ||
* @param {string|webdriver.promise.Promise<string>=} opt_rootElement Selector element that has an | ||
* @param {string|Promise<string>=} opt_rootElement Selector element that has an | ||
* ng-app in scope. | ||
@@ -143,3 +148,2 @@ * @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should | ||
this.resetUrl = DEFAULT_RESET_URL; | ||
this.debugHelper = new debugger_1.DebugHelper(this); | ||
let ng12Hybrid_ = false; | ||
@@ -161,18 +165,2 @@ Object.defineProperty(this, 'ng12Hybrid', { | ||
}); | ||
this.ready = this.angularAppRoot(opt_rootElement || '') | ||
.then(() => { | ||
return this.driver.getSession(); | ||
}) | ||
.then((session) => { | ||
// 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. | ||
// PhantomJS produces a "Detected a page unload event" if we use data urls | ||
let browserName = session.getCapabilities().get('browserName'); | ||
if (browserName === 'internet explorer' || browserName === 'safari' || | ||
browserName === 'phantomjs' || browserName === 'MicrosoftEdge') { | ||
this.resetUrl = 'about:blank'; | ||
} | ||
return this; | ||
}); | ||
this.trackOutstandingTimeouts_ = !opt_untrackOutstandingTimeouts; | ||
@@ -205,46 +193,18 @@ this.mockModules_ = []; | ||
* | ||
* The change will be made within WebDriver's control flow, so that commands after | ||
* this method is called use the new app root. Pass nothing to get a promise that | ||
* resolves to the value of the selector. | ||
* | ||
* @param {string|webdriver.promise.Promise<string>} value The new selector. | ||
* @param {string|Promise<string>} valuePromise The new selector. | ||
* @returns A promise that resolves with the value of the selector. | ||
*/ | ||
angularAppRoot(value = null) { | ||
return this.driver.controlFlow().execute(() => { | ||
if (value != null) { | ||
return selenium_webdriver_1.promise.when(value).then((value) => { | ||
this.internalRootEl = value; | ||
if (this.bpClient) { | ||
const bpCommandPromise = this.bpClient.setWaitParams(value); | ||
// Convert to webdriver promise as best as possible | ||
return selenium_webdriver_1.promise.when(bpCommandPromise).then(() => this.internalRootEl); | ||
} | ||
return this.internalRootEl; | ||
}); | ||
angularAppRoot(valuePromise = null) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (valuePromise != null) { | ||
const value = yield valuePromise; | ||
this.internalRootEl = value; | ||
if (this.bpClient) { | ||
yield this.bpClient.setWaitParams(value); | ||
} | ||
} | ||
return selenium_webdriver_1.promise.when(this.internalRootEl); | ||
}, `Set angular root selector to ${value}`); | ||
return this.internalRootEl; | ||
}); | ||
} | ||
/** | ||
* If true, Protractor will not attempt to synchronize with the page before | ||
* performing actions. This can be harmful because Protractor will not wait | ||
* until $timeouts and $http calls have been processed, which can cause | ||
* tests to become flaky. This should be used only when necessary, such as | ||
* when a page continuously polls an API using $timeout. | ||
* | ||
* Initialized to `false` by the runner. | ||
* | ||
* This property is deprecated - please use waitForAngularEnabled instead. | ||
* | ||
* @deprecated | ||
* @type {boolean} | ||
*/ | ||
set ignoreSynchronization(value) { | ||
this.waitForAngularEnabled(!value); | ||
} | ||
get ignoreSynchronization() { | ||
return this.internalIgnoreSynchronization; | ||
} | ||
/** | ||
* If set to false, Protractor will not wait for Angular $http and $timeout | ||
@@ -258,18 +218,14 @@ * tasks to complete before interacting with the browser. This can cause | ||
*/ | ||
waitForAngularEnabled(enabled = null) { | ||
if (enabled != null) { | ||
const ret = this.driver.controlFlow().execute(() => { | ||
return selenium_webdriver_1.promise.when(enabled).then((enabled) => { | ||
if (this.bpClient) { | ||
logger.debug('Setting waitForAngular' + !enabled); | ||
const bpCommandPromise = this.bpClient.setWaitEnabled(enabled); | ||
// Convert to webdriver promise as best as possible | ||
return selenium_webdriver_1.promise.when(bpCommandPromise).then(() => enabled); | ||
} | ||
}); | ||
}, `Set proxy synchronization enabled to ${enabled}`); | ||
this.internalIgnoreSynchronization = !enabled; | ||
return ret; | ||
} | ||
return selenium_webdriver_1.promise.when(!this.ignoreSynchronization); | ||
waitForAngularEnabled(enabledPromise = null) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (enabledPromise != null) { | ||
const enabled = yield enabledPromise; | ||
if (this.bpClient) { | ||
logger.debug('Setting waitForAngular' + !enabled); | ||
yield this.bpClient.setWaitEnabled(enabled); | ||
} | ||
this.internalIgnoreSynchronization = !enabled; | ||
} | ||
return !this.internalIgnoreSynchronization; | ||
}); | ||
} | ||
@@ -283,3 +239,3 @@ /** | ||
* | ||
* @returns {webdriver.promise.Promise} A promise which resolves to the | ||
* @returns {Promise} A promise which resolves to the | ||
* capabilities object. | ||
@@ -294,8 +250,3 @@ */ | ||
* @example | ||
* // Running with control flow enabled | ||
* var fork = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); // 'page1' gotten by forked browser | ||
* | ||
* // Running with control flow disabled | ||
* var forked = await browser.forkNewDriverInstance().ready; | ||
* var forked = await browser.forkNewDriverInstance(); | ||
* await forked.get('page1'); // 'page1' gotten by forked browser | ||
@@ -311,3 +262,5 @@ * | ||
forkNewDriverInstance(useSameUrl, copyMockModules, copyConfigUpdates = true) { | ||
return null; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return null; | ||
}); | ||
} | ||
@@ -323,16 +276,6 @@ /** | ||
* | ||
* This function behaves slightly differently depending on if the webdriver control flow is | ||
* enabled. If the control flow is enabled, the global `browser` object is synchronously | ||
* replaced. If the control flow is disabled, the global `browser` is replaced asynchronously | ||
* after the old driver quits. | ||
* | ||
* Set by the runner. | ||
* | ||
* @example | ||
* // Running against global browser, with control flow enabled | ||
* browser.get('page1'); | ||
* browser.restart(); | ||
* browser.get('page2'); // 'page2' gotten by restarted browser | ||
* | ||
* // Running against global browser, with control flow disabled | ||
* // Running against global browser | ||
* await browser.get('page1'); | ||
@@ -342,12 +285,4 @@ * await browser.restart(); | ||
* | ||
* // Running against forked browsers, with the control flow enabled | ||
* // In this case, you may prefer `restartSync` (documented below) | ||
* var forked = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); | ||
* fork.restart().then(function(fork) { | ||
* fork.get('page2'); // 'page2' gotten by restarted fork | ||
* }); | ||
* | ||
* // Running against forked browsers, with the control flow disabled | ||
* var forked = await browser.forkNewDriverInstance().ready; | ||
* // Running against forked browsers | ||
* var forked = await browser.forkNewDriverInstance(); | ||
* await fork.get('page1'); | ||
@@ -364,3 +299,3 @@ * fork = await fork.restart(); | ||
* | ||
* @returns {webdriver.promise.Promise<ProtractorBrowser>} A promise resolving to the restarted | ||
* @returns {Promise<ProtractorBrowser>} A promise resolving to the restarted | ||
* browser | ||
@@ -372,24 +307,2 @@ */ | ||
/** | ||
* Like `restart`, but instead of returning a promise resolving to the new browser instance, | ||
* returns the new browser instance directly. Can only be used when the control flow is enabled. | ||
* | ||
* @example | ||
* // Running against global browser | ||
* browser.get('page1'); | ||
* browser.restartSync(); | ||
* browser.get('page2'); // 'page2' gotten by restarted browser | ||
* | ||
* // Running against forked browsers | ||
* var forked = browser.forkNewDriverInstance(); | ||
* fork.get('page1'); | ||
* fork = fork.restartSync(); | ||
* fork.get('page2'); // 'page2' gotten by restarted fork | ||
* | ||
* @throws {TypeError} Will throw an error if the control flow is not enabled | ||
* @returns {ProtractorBrowser} The restarted browser | ||
*/ | ||
restartSync() { | ||
return; | ||
} | ||
/** | ||
* Instead of using a single root element, search through all angular apps | ||
@@ -412,3 +325,3 @@ * available on the page when finding elements or waiting for stability. | ||
* @param {...*} var_args The arguments to pass to the script. | ||
* @returns {!webdriver.promise.Promise.<T>} A promise that will resolve to | ||
* @returns {!Promise<T>} A promise that will resolve to | ||
* the scripts return value. | ||
@@ -421,5 +334,7 @@ * @template T | ||
} | ||
return this.driver.schedule(new Command(CommandName.EXECUTE_SCRIPT) | ||
// TODO(selenium4): schedule does not exist on driver. Should use execute instead. | ||
return this.driver | ||
.execute(new Command(CommandName.EXECUTE_SCRIPT) | ||
.setParameter('script', script) | ||
.setParameter('args', scriptArgs), description); | ||
.setParameter('args', scriptArgs)); | ||
} | ||
@@ -434,3 +349,3 @@ /** | ||
* @param {...*} var_args The arguments to pass to the script. | ||
* @returns {!webdriver.promise.Promise.<T>} A promise that will resolve to | ||
* @returns {!Promise<T>} A promise that will resolve to | ||
* the | ||
@@ -441,8 +356,11 @@ * scripts return value. | ||
executeAsyncScript_(script, description, ...scriptArgs) { | ||
// TODO(selenium4): decide what to do with description. | ||
if (typeof script === 'function') { | ||
script = 'return (' + script + ').apply(null, arguments);'; | ||
} | ||
return this.driver.schedule(new Command(CommandName.EXECUTE_ASYNC_SCRIPT) | ||
// TODO(selenium4): fix typings. driver.execute should exist | ||
return this.driver | ||
.execute(new Command(CommandName.EXECUTE_ASYNC_SCRIPT) | ||
.setParameter('script', script) | ||
.setParameter('args', scriptArgs), description); | ||
.setParameter('args', scriptArgs)); | ||
} | ||
@@ -457,76 +375,63 @@ /** | ||
* to webdriver logs. | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve to the | ||
* @returns {!Promise} A promise that will resolve to the | ||
* scripts return value. | ||
*/ | ||
waitForAngular(opt_description) { | ||
let description = opt_description ? ' - ' + opt_description : ''; | ||
if (this.ignoreSynchronization) { | ||
return this.driver.controlFlow().execute(() => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let description = opt_description ? ' - ' + opt_description : ''; | ||
if (!(yield this.waitForAngularEnabled())) { | ||
return true; | ||
}, 'Ignore Synchronization Protractor.waitForAngular()'); | ||
} | ||
let runWaitForAngularScript = () => { | ||
if (this.plugins_.skipAngularStability() || this.bpClient) { | ||
return this.driver.controlFlow().execute(() => { | ||
return selenium_webdriver_1.promise.when(null); | ||
}, 'bpClient or plugin stability override'); | ||
} | ||
else { | ||
// Need to wrap this so that we read rootEl in the control flow, not synchronously. | ||
return this.angularAppRoot().then((rootEl) => { | ||
return this.executeAsyncScript_(clientSideScripts.waitForAngular, 'Protractor.waitForAngular()' + description, rootEl); | ||
}); | ||
} | ||
}; | ||
return runWaitForAngularScript() | ||
.then((browserErr) => { | ||
if (browserErr) { | ||
throw new Error('Error while waiting for Protractor to ' + | ||
'sync with the page: ' + JSON.stringify(browserErr)); | ||
} | ||
}) | ||
.then(() => { | ||
return this.driver.controlFlow() | ||
.execute(() => { | ||
return this.plugins_.waitForPromise(this); | ||
}, 'Plugins.waitForPromise()') | ||
.then(() => { | ||
return this.driver.wait(() => { | ||
return this.plugins_.waitForCondition(this).then((results) => { | ||
return results.reduce((x, y) => x && y, true); | ||
}); | ||
}, this.allScriptsTimeout, 'Plugins.waitForCondition()'); | ||
let runWaitForAngularScript = () => __awaiter(this, void 0, void 0, function* () { | ||
if (this.plugins_.skipAngularStability() || this.bpClient) { | ||
return null; | ||
} | ||
else { | ||
let rootEl = yield this.angularAppRoot(); | ||
return this.executeAsyncScript_(clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); | ||
} | ||
}); | ||
}, (err) => { | ||
let timeout; | ||
if (/asynchronous script timeout/.test(err.message)) { | ||
// Timeout on Chrome | ||
timeout = /-?[\d\.]*\ seconds/.exec(err.message); | ||
try { | ||
let browserErr = yield runWaitForAngularScript(); | ||
if (browserErr) { | ||
throw new Error('Error while waiting for Protractor to ' + | ||
'sync with the page: ' + JSON.stringify(browserErr)); | ||
} | ||
yield this.plugins_.waitForPromise(this); | ||
yield this.driver.wait(() => __awaiter(this, void 0, void 0, function* () { | ||
let results = yield this.plugins_.waitForCondition(this); | ||
return results.reduce((x, y) => x && y, true); | ||
}), this.allScriptsTimeout, 'Plugins.waitForCondition()'); | ||
} | ||
else if (/Timed out waiting for async script/.test(err.message)) { | ||
// Timeout on Firefox | ||
timeout = /-?[\d\.]*ms/.exec(err.message); | ||
} | ||
else if (/Timed out waiting for an asynchronous script/.test(err.message)) { | ||
// Timeout on Safari | ||
timeout = /-?[\d\.]*\ ms/.exec(err.message); | ||
} | ||
if (timeout) { | ||
let errMsg = `Timed out waiting for asynchronous Angular tasks to finish after ` + | ||
`${timeout}. This may be because the current page is not an Angular ` + | ||
`application. Please see the FAQ for more details: ` + | ||
`https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular`; | ||
if (description.indexOf(' - Locator: ') == 0) { | ||
errMsg += '\nWhile waiting for element with locator' + description; | ||
catch (err) { | ||
let timeout; | ||
if (/asynchronous script timeout/.test(err.message)) { | ||
// Timeout on Chrome | ||
timeout = /-?[\d\.]*\ seconds/.exec(err.message); | ||
} | ||
let pendingTimeoutsPromise; | ||
if (this.trackOutstandingTimeouts_) { | ||
pendingTimeoutsPromise = this.executeScriptWithDescription('return window.NG_PENDING_TIMEOUTS', 'Protractor.waitForAngular() - getting pending timeouts' + description); | ||
else if (/Timed out waiting for async script/.test(err.message)) { | ||
// Timeout on Firefox | ||
timeout = /-?[\d\.]*ms/.exec(err.message); | ||
} | ||
else { | ||
pendingTimeoutsPromise = selenium_webdriver_1.promise.when({}); | ||
else if (/Timed out waiting for an asynchronous script/.test(err.message)) { | ||
// Timeout on Safari | ||
timeout = /-?[\d\.]*\ ms/.exec(err.message); | ||
} | ||
let pendingHttpsPromise = this.executeScriptWithDescription(clientSideScripts.getPendingHttpRequests, 'Protractor.waitForAngular() - getting pending https' + description, this.internalRootEl); | ||
return selenium_webdriver_1.promise.all([pendingTimeoutsPromise, pendingHttpsPromise]) | ||
.then((arr) => { | ||
if (timeout) { | ||
let errMsg = `Timed out waiting for asynchronous Angular tasks to finish after ` + | ||
`${timeout}. This may be because the current page is not an Angular ` + | ||
`application. Please see the FAQ for more details: ` + | ||
`https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular`; | ||
if (description.indexOf(' - Locator: ') == 0) { | ||
errMsg += '\nWhile waiting for element with locator' + description; | ||
} | ||
let pendingTimeoutsPromise; | ||
if (this.trackOutstandingTimeouts_) { | ||
pendingTimeoutsPromise = this.executeScriptWithDescription('return window.NG_PENDING_TIMEOUTS', 'Protractor.waitForAngular() - getting pending timeouts' + description); | ||
} | ||
else { | ||
pendingTimeoutsPromise = Promise.resolve(); | ||
} | ||
let pendingHttpsPromise = this.executeScriptWithDescription(clientSideScripts.getPendingHttpRequests, 'Protractor.waitForAngular() - getting pending https' + description, this.internalRootEl); | ||
let arr = yield Promise.all([pendingTimeoutsPromise, pendingHttpsPromise]); | ||
let pendingTimeouts = arr[0] || []; | ||
@@ -548,9 +453,3 @@ let pendingHttps = arr[1] || []; | ||
err.message = errMsg; | ||
throw err; | ||
}, () => { | ||
err.message = errMsg; | ||
throw err; | ||
}); | ||
} | ||
else { | ||
} | ||
throw err; | ||
@@ -572,3 +471,3 @@ } | ||
* @see webdriver.WebDriver.findElements | ||
* @returns {!webdriver.promise.Promise} A promise that will be resolved to an | ||
* @returns {!Promise} A promise that will be resolved to an | ||
* array of the located {@link webdriver.WebElement}s. | ||
@@ -582,3 +481,3 @@ */ | ||
* @see webdriver.WebDriver.isElementPresent | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve to whether | ||
* @returns {!Promise} A promise that will resolve to whether | ||
* the element is present on the page. | ||
@@ -650,3 +549,2 @@ */ | ||
} | ||
; | ||
/** | ||
@@ -669,4 +567,4 @@ * Add the base mock modules used for all Protractor tests. | ||
* @example | ||
* browser.get('https://angularjs.org/'); | ||
* expect(browser.getCurrentUrl()).toBe('https://angularjs.org/'); | ||
* await browser.get('https://angularjs.org/'); | ||
* expect(await browser.getCurrentUrl()).toBe('https://angularjs.org/'); | ||
* | ||
@@ -678,36 +576,24 @@ * @param {string} destination Destination URL. | ||
get(destination, timeout = this.getPageTimeout) { | ||
destination = this.baseUrl.indexOf('file://') === 0 ? this.baseUrl + destination : | ||
url.resolve(this.baseUrl, destination); | ||
if (this.ignoreSynchronization) { | ||
return this.driver.get(destination) | ||
.then(() => this.driver.controlFlow().execute(() => this.plugins_.onPageLoad(this))) | ||
.then(() => null); | ||
} | ||
let msg = (str) => { | ||
return 'Protractor.get(' + destination + ') - ' + str; | ||
}; | ||
return this.driver.controlFlow() | ||
.execute(() => { | ||
return selenium_webdriver_1.promise.when(null); | ||
}) | ||
.then(() => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
destination = this.baseUrl.indexOf('file://') === 0 ? this.baseUrl + destination : | ||
url.resolve(this.baseUrl, destination); | ||
if (!(yield this.waitForAngularEnabled())) { | ||
yield this.driver.get(destination); | ||
yield this.plugins_.onPageLoad(this); | ||
return; | ||
} | ||
let msg = (str) => { | ||
return 'Protractor.get(' + destination + ') - ' + str; | ||
}; | ||
if (this.bpClient) { | ||
return this.driver.controlFlow().execute(() => { | ||
return this.bpClient.setWaitEnabled(false); | ||
}); | ||
yield this.bpClient.setWaitEnabled(false); | ||
} | ||
}) | ||
.then(() => { | ||
// Go to reset url | ||
return this.driver.get(this.resetUrl); | ||
}) | ||
.then(() => { | ||
yield this.driver.get(this.resetUrl); | ||
// Set defer label and navigate | ||
return this.executeScriptWithDescription('window.name = "' + DEFER_LABEL + '" + window.name;' + | ||
yield this.executeScriptWithDescription('window.name = "' + DEFER_LABEL + '" + window.name;' + | ||
'window.location.replace("' + destination + '");', msg('reset url')); | ||
}) | ||
.then(() => { | ||
// We need to make sure the new url has loaded before | ||
// we try to execute any asynchronous scripts. | ||
return this.driver.wait(() => { | ||
yield this.driver.wait(() => { | ||
return this.executeScriptWithDescription('return window.location.href;', msg('get url')) | ||
@@ -731,15 +617,9 @@ .then((url) => { | ||
}, timeout, 'waiting for page to load for ' + timeout + 'ms'); | ||
}) | ||
.then(() => { | ||
// Run Plugins | ||
return this.driver.controlFlow().execute(() => { | ||
return this.plugins_.onPageLoad(this); | ||
}); | ||
}) | ||
.then(() => { | ||
// Make sure the page is an Angular page. | ||
return this | ||
.executeAsyncScript_(clientSideScripts.testForAngular, msg('test for angular'), Math.floor(timeout / 1000), this.ng12Hybrid) | ||
.then((angularTestResult) => { | ||
let angularVersion = angularTestResult.ver; | ||
yield this.plugins_.onPageLoad(this); | ||
let angularVersion; | ||
try { | ||
// Make sure the page is an Angular page. | ||
const angularTestResult = yield this.executeAsyncScript_(clientSideScripts.testForAngular, msg('test for angular'), Math.floor(timeout / 1000), this.ng12Hybrid); | ||
angularVersion = angularTestResult.ver; | ||
if (!angularVersion) { | ||
@@ -750,11 +630,9 @@ let message = angularTestResult.message; | ||
`If this is not an Angular application, you may need to turn off waiting for Angular. | ||
Please see | ||
https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load`); | ||
Please see | ||
https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load`); | ||
} | ||
return angularVersion; | ||
}, (err) => { | ||
} | ||
catch (err) { | ||
throw new Error('Error while running testForAngular: ' + err.message); | ||
}); | ||
}) | ||
.then((angularVersion) => { | ||
} | ||
// Load Angular Mocks | ||
@@ -764,13 +642,12 @@ if (angularVersion === 1) { | ||
let moduleNames = []; | ||
let modulePromise = selenium_webdriver_1.promise.when(null); | ||
for (const { name, script, args } of this.mockModules_) { | ||
moduleNames.push(name); | ||
let executeScriptArgs = [script, msg('add mock module ' + name), ...args]; | ||
modulePromise = modulePromise.then(() => this.executeScriptWithDescription.apply(this, executeScriptArgs) | ||
yield this.executeScriptWithDescription.apply(this, executeScriptArgs) | ||
.then(null, (err) => { | ||
throw new Error('Error while running module script ' + name + ': ' + err.message); | ||
})); | ||
}); | ||
} | ||
return modulePromise.then(() => this.executeScriptWithDescription('window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' + | ||
'angular.resumeBootstrap(arguments[0]);', msg('resume bootstrap'), moduleNames)); | ||
yield this.executeScriptWithDescription('window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' + | ||
'angular.resumeBootstrap(arguments[0]);', msg('resume bootstrap'), moduleNames); | ||
} | ||
@@ -784,18 +661,9 @@ else { | ||
} | ||
}) | ||
.then(() => { | ||
// Reset bpClient sync | ||
if (this.bpClient) { | ||
return this.driver.controlFlow().execute(() => { | ||
return this.bpClient.setWaitEnabled(!this.internalIgnoreSynchronization); | ||
}); | ||
yield this.bpClient.setWaitEnabled(!this.internalIgnoreSynchronization); | ||
} | ||
}) | ||
.then(() => { | ||
// Run Plugins | ||
return this.driver.controlFlow().execute(() => { | ||
return this.plugins_.onPageStable(this); | ||
}); | ||
}) | ||
.then(() => null); | ||
yield this.plugins_.onPageStable(this); | ||
}); | ||
} | ||
@@ -813,8 +681,7 @@ /** | ||
refresh(opt_timeout) { | ||
if (this.ignoreSynchronization) { | ||
return this.driver.navigate().refresh(); | ||
} | ||
return this | ||
.executeScriptWithDescription('return window.location.href', 'Protractor.refresh() - getUrl') | ||
.then((href) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!(yield this.waitForAngularEnabled())) { | ||
return this.driver.navigate().refresh(); | ||
} | ||
const href = yield this.executeScriptWithDescription('return window.location.href', 'Protractor.refresh() - getUrl'); | ||
return this.get(href, opt_timeout); | ||
@@ -836,21 +703,20 @@ }); | ||
* @example | ||
* browser.get('http://angular.github.io/protractor/#/tutorial'); | ||
* browser.setLocation('api'); | ||
* expect(browser.getCurrentUrl()) | ||
* await browser.get('http://angular.github.io/protractor/#/tutorial'); | ||
* await browser.setLocation('api'); | ||
* expect(await browser.getCurrentUrl()) | ||
* .toBe('http://angular.github.io/protractor/#/api'); | ||
* | ||
* @param {string} url In page URL using the same syntax as $location.url() | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve once | ||
* @returns {!Promise} A promise that will resolve once | ||
* page has been changed. | ||
*/ | ||
setLocation(url) { | ||
return this.waitForAngular() | ||
.then(() => this.angularAppRoot()) | ||
.then((rootEl) => this.executeScriptWithDescription(clientSideScripts.setLocation, 'Protractor.setLocation()', rootEl, url) | ||
.then((browserErr) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.waitForAngular(); | ||
const rootEl = yield this.angularAppRoot(); | ||
const browserErr = yield this.executeScriptWithDescription(clientSideScripts.setLocation, 'Protractor.setLocation()', rootEl, url); | ||
if (browserErr) { | ||
throw 'Error while navigating to \'' + url + | ||
'\' : ' + JSON.stringify(browserErr); | ||
throw 'Error while navigating to \'' + url + '\' : ' + JSON.stringify(browserErr); | ||
} | ||
})); | ||
}); | ||
} | ||
@@ -866,121 +732,17 @@ /** | ||
* @example | ||
* browser.get('http://angular.github.io/protractor/#/api'); | ||
* expect(browser.getLocationAbsUrl()) | ||
* await browser.get('http://angular.github.io/protractor/#/api'); | ||
* expect(await browser.getLocationAbsUrl()) | ||
* .toBe('http://angular.github.io/protractor/#/api'); | ||
* @returns {webdriver.promise.Promise<string>} The current absolute url from | ||
* @returns {Promise<string>} The current absolute url from | ||
* AngularJS. | ||
*/ | ||
getLocationAbsUrl() { | ||
logger.warn('`browser.getLocationAbsUrl()` is deprecated, please use `browser.getCurrentUrl` instead.'); | ||
return this.waitForAngular() | ||
.then(() => this.angularAppRoot()) | ||
.then((rootEl) => this.executeScriptWithDescription(clientSideScripts.getLocationAbsUrl, 'Protractor.getLocationAbsUrl()', rootEl)); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
logger.warn('`browser.getLocationAbsUrl()` is deprecated, please use `browser.getCurrentUrl` instead.'); | ||
yield this.waitForAngular(); | ||
const rootEl = yield this.angularAppRoot(); | ||
return yield this.executeScriptWithDescription(clientSideScripts.getLocationAbsUrl, 'Protractor.getLocationAbsUrl()', rootEl); | ||
}); | ||
} | ||
/** | ||
* Adds a task to the control flow to pause the test and inject helper | ||
* functions | ||
* into the browser, so that debugging may be done in the browser console. | ||
* | ||
* This should be used under node in debug mode, i.e. with | ||
* protractor debug <configuration.js> | ||
* | ||
* @example | ||
* While in the debugger, commands can be scheduled through webdriver by | ||
* entering the repl: | ||
* debug> repl | ||
* > element(by.input('user')).sendKeys('Laura'); | ||
* > browser.debugger(); | ||
* Press Ctrl + c to leave debug repl | ||
* debug> c | ||
* | ||
* This will run the sendKeys command as the next task, then re-enter the | ||
* debugger. | ||
*/ | ||
debugger() { | ||
// jshint debug: true | ||
return this.driver.executeScript(clientSideScripts.installInBrowser) | ||
.then(() => selenium_webdriver_1.promise.controlFlow().execute(() => { | ||
debugger; | ||
}, 'add breakpoint to control flow')); | ||
} | ||
/** | ||
* See browser.explore(). | ||
*/ | ||
enterRepl(opt_debugPort) { | ||
return this.explore(opt_debugPort); | ||
} | ||
/** | ||
* Beta (unstable) explore function for entering the repl loop from | ||
* any point in the control flow. Use browser.explore() in your test. | ||
* Does not require changes to the command line (no need to add 'debug'). | ||
* Note, if you are wrapping your own instance of Protractor, you must | ||
* expose globals 'browser' and 'protractor' for pause to work. | ||
* | ||
* @example | ||
* element(by.id('foo')).click(); | ||
* browser.explore(); | ||
* // Execution will stop before the next click action. | ||
* element(by.id('bar')).click(); | ||
* | ||
* @param {number=} opt_debugPort Optional port to use for the debugging | ||
* process | ||
*/ | ||
explore(opt_debugPort) { | ||
let debuggerClientPath = __dirname + '/debugger/clients/explorer.js'; | ||
let onStartFn = (firstTime) => { | ||
logger.info(); | ||
if (firstTime) { | ||
logger.info('------- Element Explorer -------'); | ||
logger.info('Starting WebDriver debugger in a child process. Element ' + | ||
'Explorer is still beta, please report issues at ' + | ||
'github.com/angular/protractor'); | ||
logger.info(); | ||
logger.info('Type <tab> to see a list of locator strategies.'); | ||
logger.info('Use the `list` helper function to find elements by strategy:'); | ||
logger.info(' e.g., list(by.binding(\'\')) gets all bindings.'); | ||
logger.info(); | ||
} | ||
}; | ||
this.debugHelper.initBlocking(debuggerClientPath, onStartFn, opt_debugPort); | ||
} | ||
/** | ||
* Beta (unstable) pause function for debugging webdriver tests. Use | ||
* browser.pause() in your test to enter the protractor debugger from that | ||
* point in the control flow. | ||
* Does not require changes to the command line (no need to add 'debug'). | ||
* Note, if you are wrapping your own instance of Protractor, you must | ||
* expose globals 'browser' and 'protractor' for pause to work. | ||
* | ||
* @example | ||
* element(by.id('foo')).click(); | ||
* browser.pause(); | ||
* // Execution will stop before the next click action. | ||
* element(by.id('bar')).click(); | ||
* | ||
* @param {number=} opt_debugPort Optional port to use for the debugging | ||
* process | ||
*/ | ||
pause(opt_debugPort) { | ||
if (this.debugHelper.isAttached()) { | ||
logger.info('Encountered browser.pause(), but debugger already attached.'); | ||
return selenium_webdriver_1.promise.when(true); | ||
} | ||
let debuggerClientPath = __dirname + '/debugger/clients/wddebugger.js'; | ||
let onStartFn = (firstTime) => { | ||
logger.info(); | ||
logger.info('Encountered browser.pause(). Attaching debugger...'); | ||
if (firstTime) { | ||
logger.info(); | ||
logger.info('------- WebDriver Debugger -------'); | ||
logger.info('Starting WebDriver debugger in a child process. Pause is ' + | ||
'still beta, please report issues at github.com/angular/protractor'); | ||
logger.info(); | ||
logger.info('press c to continue to the next webdriver command'); | ||
logger.info('press ^D to detach debugger and resume code execution'); | ||
logger.info(); | ||
} | ||
}; | ||
this.debugHelper.init(debuggerClientPath, onStartFn, opt_debugPort); | ||
} | ||
/** | ||
* Determine if the control flow is enabled. | ||
@@ -987,0 +749,0 @@ * |
@@ -194,3 +194,2 @@ "use strict"; | ||
} | ||
; | ||
if (argv.specs) { | ||
@@ -197,0 +196,0 @@ argv.specs = processFilePatterns_(argv.specs); |
@@ -1,2 +0,1 @@ | ||
import { WebDriver } from 'selenium-webdriver'; | ||
import { PluginConfig } from './plugins'; | ||
@@ -192,3 +191,2 @@ export interface Config { | ||
firefoxPath?: string; | ||
seleniumWebDriver?: WebDriver; | ||
/** | ||
@@ -617,2 +615,6 @@ * Use default globals: 'protractor', 'browser', '$', '$$', 'element', 'by'. | ||
frameworkPath?: string; | ||
/** | ||
* Deprecated: Element explorer depends on the WebDriver control flow, and | ||
* thus is no longer supported. | ||
*/ | ||
elementExplorer?: any; | ||
@@ -619,0 +621,0 @@ debug?: boolean; |
@@ -28,3 +28,3 @@ import { Config } from './config'; | ||
*/ | ||
private addConfig_(additionalConfig, relativeTo); | ||
private addConfig_; | ||
/** | ||
@@ -31,0 +31,0 @@ * Public function specialized towards merging in a file's config |
@@ -1,4 +0,2 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { promise as wdpromise, WebDriver } from 'selenium-webdriver'; | ||
import { WebDriver } from 'selenium-webdriver'; | ||
import { Config } from '../config'; | ||
@@ -10,6 +8,6 @@ import { DriverProvider } from './driverProvider'; | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
/** | ||
@@ -21,3 +19,3 @@ * Getting a new driver by attaching an existing session. | ||
*/ | ||
getNewDriver(): WebDriver; | ||
getNewDriver(): Promise<WebDriver>; | ||
/** | ||
@@ -28,3 +26,3 @@ * Maintains the existing session and does not quit the driver. | ||
*/ | ||
quitDriver(): wdpromise.Promise<void>; | ||
quitDriver(): Promise<void>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,3 +16,2 @@ /* | ||
*/ | ||
const q = require("q"); | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
@@ -21,9 +28,10 @@ const logger_1 = require("../logger"); | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
logger.info('Using the selenium server at ' + this.config_.seleniumAddress); | ||
logger.info('Using session id - ' + this.config_.seleniumSessionId); | ||
return q(undefined); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
logger.info('Using the selenium server at ' + this.config_.seleniumAddress); | ||
logger.info('Using session id - ' + this.config_.seleniumSessionId); | ||
}); | ||
} | ||
@@ -37,7 +45,10 @@ /** | ||
getNewDriver() { | ||
const httpClient = new http.HttpClient(this.config_.seleniumAddress); | ||
const executor = new http.Executor(httpClient); | ||
const newDriver = selenium_webdriver_1.WebDriver.attachToSession(executor, this.config_.seleniumSessionId); | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const httpClient = new http.HttpClient(this.config_.seleniumAddress); | ||
const executor = new http.Executor(httpClient); | ||
const session = new selenium_webdriver_1.Session(this.config_.seleniumSessionId, null); | ||
const newDriver = new selenium_webdriver_1.WebDriver(session, executor); | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
}); | ||
} | ||
@@ -50,3 +61,3 @@ /** | ||
quitDriver() { | ||
return selenium_webdriver_1.promise.when(undefined); | ||
return __awaiter(this, void 0, void 0, function* () { }); | ||
} | ||
@@ -53,0 +64,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -12,11 +10,11 @@ import { DriverProvider } from './driverProvider'; | ||
* @param {Object} update | ||
* @return {q.promise} A promise that will resolve when the update is complete. | ||
* @return {Promise} A promise that will resolve when the update is complete. | ||
*/ | ||
updateJob(update: any): q.Promise<any>; | ||
updateJob(update: any): Promise<any>; | ||
/** | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const q = require("q"); | ||
const util = require("util"); | ||
@@ -18,8 +25,8 @@ const exitCodes_1 = require("../exitCodes"); | ||
* @param {Object} update | ||
* @return {q.promise} A promise that will resolve when the update is complete. | ||
* @return {Promise} A promise that will resolve when the update is complete. | ||
*/ | ||
updateJob(update) { | ||
let deferredArray = this.drivers_.map((driver) => { | ||
let deferred = q.defer(); | ||
driver.getSession().then((session) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let mappedDrivers = this.drivers_.map((driver) => __awaiter(this, void 0, void 0, function* () { | ||
let session = yield driver.getSession(); | ||
// Fetching BrowserStack session details. | ||
@@ -50,34 +57,31 @@ this.browserstackClient.getSession(session.getId(), function (error, automate_session) { | ||
logger.info(automate_session); | ||
deferred.resolve(); | ||
} | ||
}); | ||
}); | ||
return deferred.promise; | ||
})); | ||
return Promise.all(mappedDrivers); | ||
}); | ||
return q.all(deferredArray); | ||
} | ||
/** | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
let deferred = q.defer(); | ||
this.config_.capabilities['browserstack.user'] = this.config_.browserstackUser; | ||
this.config_.capabilities['browserstack.key'] = this.config_.browserstackKey; | ||
this.config_.seleniumAddress = 'http://hub.browserstack.com/wd/hub'; | ||
this.browserstackClient = BrowserstackClient.createAutomateClient({ | ||
username: this.config_.browserstackUser, | ||
password: this.config_.browserstackKey, | ||
proxy: this.config_.browserstackProxy | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.config_.capabilities['browserstack.user'] = this.config_.browserstackUser; | ||
this.config_.capabilities['browserstack.key'] = this.config_.browserstackKey; | ||
this.config_.seleniumAddress = 'http://hub.browserstack.com/wd/hub'; | ||
this.browserstackClient = BrowserstackClient.createAutomateClient({ | ||
username: this.config_.browserstackUser, | ||
password: this.config_.browserstackKey, | ||
proxy: this.config_.browserstackProxy | ||
}); | ||
// Append filename to capabilities.name so that it's easier to identify | ||
// tests. | ||
if (this.config_.capabilities.name && this.config_.capabilities.shardTestFiles) { | ||
this.config_.capabilities.name += | ||
(':' + this.config_.specs.toString().replace(/^.*[\\\/]/, '')); | ||
} | ||
logger.info(`Using BrowserStack selenium server at ${this.config_.seleniumAddress}`); | ||
}); | ||
// Append filename to capabilities.name so that it's easier to identify | ||
// tests. | ||
if (this.config_.capabilities.name && this.config_.capabilities.shardTestFiles) { | ||
this.config_.capabilities.name += | ||
(':' + this.config_.specs.toString().replace(/^.*[\\\/]/, '')); | ||
} | ||
logger.info('Using BrowserStack selenium server at ' + this.config_.seleniumAddress); | ||
deferred.resolve(); | ||
return deferred.promise; | ||
} | ||
@@ -84,0 +88,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { WebDriver } from 'selenium-webdriver'; | ||
@@ -10,6 +8,6 @@ import { Config } from '../config'; | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
/** | ||
@@ -22,3 +20,3 @@ * Create a new driver. | ||
*/ | ||
getNewDriver(): WebDriver; | ||
getNewDriver(): Promise<WebDriver>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -9,10 +17,9 @@ /* | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const q = require("q"); | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
const chrome_1 = require("selenium-webdriver/chrome"); | ||
const firefox_1 = require("selenium-webdriver/firefox"); | ||
const webdriver_manager_1 = require("webdriver-manager"); | ||
const exitCodes_1 = require("../exitCodes"); | ||
const logger_1 = require("../logger"); | ||
const driverProvider_1 = require("./driverProvider"); | ||
const SeleniumConfig = require('webdriver-manager/built/lib/config').Config; | ||
let logger = new logger_1.Logger('direct'); | ||
@@ -25,18 +32,19 @@ class Direct extends driverProvider_1.DriverProvider { | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
switch (this.config_.capabilities.browserName) { | ||
case 'chrome': | ||
logger.info('Using ChromeDriver directly...'); | ||
break; | ||
case 'firefox': | ||
logger.info('Using FirefoxDriver directly...'); | ||
break; | ||
default: | ||
throw new exitCodes_1.BrowserError(logger, 'browserName ' + this.config_.capabilities.browserName + | ||
' is not supported with directConnect.'); | ||
} | ||
return q.fcall(function () { }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
switch (this.config_.capabilities.browserName) { | ||
case 'chrome': | ||
logger.info('Using ChromeDriver directly...'); | ||
break; | ||
case 'firefox': | ||
logger.info('Using FirefoxDriver directly...'); | ||
break; | ||
default: | ||
throw new exitCodes_1.BrowserError(logger, 'browserName ' + this.config_.capabilities.browserName + | ||
' is not supported with directConnect.'); | ||
} | ||
}); | ||
} | ||
@@ -51,66 +59,52 @@ /** | ||
getNewDriver() { | ||
let driver; | ||
switch (this.config_.capabilities.browserName) { | ||
case 'chrome': | ||
let chromeDriverFile; | ||
if (this.config_.chromeDriver) { | ||
chromeDriverFile = this.config_.chromeDriver; | ||
} | ||
else { | ||
try { | ||
let updateJson = path.resolve(SeleniumConfig.getSeleniumDir(), 'update-config.json'); | ||
let updateConfig = JSON.parse(fs.readFileSync(updateJson).toString()); | ||
chromeDriverFile = updateConfig.chrome.last; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let driver; | ||
switch (this.config_.capabilities.browserName) { | ||
case 'chrome': | ||
let chromeDriverFile; | ||
if (this.config_.chromeDriver) { | ||
chromeDriverFile = this.config_.chromeDriver; | ||
} | ||
catch (e) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find update-config.json. ' + | ||
'Run \'webdriver-manager update\' to download binaries.'); | ||
else { | ||
try { | ||
chromeDriverFile = new webdriver_manager_1.ChromeDriver().getBinaryPath(); | ||
} | ||
catch (e) { | ||
throw new exitCodes_1.BrowserError(logger, 'Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
} | ||
} | ||
if (!fs.existsSync(chromeDriverFile)) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find chromedriver at ' + chromeDriverFile + | ||
'. Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
let chromeService = new chrome_1.ServiceBuilder(chromeDriverFile).build(); | ||
// driver = ChromeDriver.createSession(new Capabilities(this.config_.capabilities), | ||
// chromeService); | ||
// TODO(ralphj): fix typings | ||
driver = | ||
require('selenium-webdriver/chrome') | ||
.Driver.createSession(new selenium_webdriver_1.Capabilities(this.config_.capabilities), chromeService); | ||
break; | ||
case 'firefox': | ||
let geckoDriverFile; | ||
if (this.config_.geckoDriver) { | ||
geckoDriverFile = this.config_.geckoDriver; | ||
} | ||
else { | ||
try { | ||
let updateJson = path.resolve(SeleniumConfig.getSeleniumDir(), 'update-config.json'); | ||
let updateConfig = JSON.parse(fs.readFileSync(updateJson).toString()); | ||
geckoDriverFile = updateConfig.gecko.last; | ||
if (!fs.existsSync(chromeDriverFile)) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find chromedriver at ' + chromeDriverFile + | ||
'. Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
catch (e) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find update-config.json. ' + | ||
'Run \'webdriver-manager update\' to download binaries.'); | ||
let chromeService = new chrome_1.ServiceBuilder(chromeDriverFile).build(); | ||
driver = yield chrome_1.Driver.createSession(new selenium_webdriver_1.Capabilities(this.config_.capabilities), chromeService); | ||
break; | ||
case 'firefox': | ||
let geckoDriverFile; | ||
if (this.config_.geckoDriver) { | ||
geckoDriverFile = this.config_.geckoDriver; | ||
} | ||
} | ||
if (!fs.existsSync(geckoDriverFile)) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find geckodriver at ' + geckoDriverFile + | ||
'. Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
// TODO (mgiambalvo): Turn this into an import when the selenium typings are updated. | ||
const FirefoxServiceBuilder = require('selenium-webdriver/firefox').ServiceBuilder; | ||
let firefoxService = new FirefoxServiceBuilder(geckoDriverFile).build(); | ||
// TODO(mgiambalvo): Fix typings. | ||
driver = | ||
require('selenium-webdriver/firefox') | ||
.Driver.createSession(new selenium_webdriver_1.Capabilities(this.config_.capabilities), firefoxService); | ||
break; | ||
default: | ||
throw new exitCodes_1.BrowserError(logger, 'browserName ' + this.config_.capabilities.browserName + | ||
' is not supported with directConnect.'); | ||
} | ||
this.drivers_.push(driver); | ||
return driver; | ||
else { | ||
try { | ||
geckoDriverFile = new webdriver_manager_1.GeckoDriver().getBinaryPath(); | ||
} | ||
catch (e) { | ||
throw new exitCodes_1.BrowserError(logger, 'Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
} | ||
if (!fs.existsSync(geckoDriverFile)) { | ||
throw new exitCodes_1.BrowserError(logger, 'Could not find geckodriver at ' + geckoDriverFile + | ||
'. Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
let firefoxService = new firefox_1.ServiceBuilder(geckoDriverFile).build(); | ||
driver = yield firefox_1.Driver.createSession(new selenium_webdriver_1.Capabilities(this.config_.capabilities), firefoxService); | ||
break; | ||
default: | ||
throw new exitCodes_1.BrowserError(logger, 'browserName ' + this.config_.capabilities.browserName + | ||
' is not supported with directConnect.'); | ||
} | ||
this.drivers_.push(driver); | ||
return driver; | ||
}); | ||
} | ||
@@ -117,0 +111,0 @@ } |
@@ -1,2 +0,1 @@ | ||
/// <reference types="q" /> | ||
/** | ||
@@ -7,4 +6,3 @@ * This is a base driver provider class. | ||
*/ | ||
import * as q from 'q'; | ||
import { promise as wdpromise, WebDriver } from 'selenium-webdriver'; | ||
import { WebDriver } from 'selenium-webdriver'; | ||
import { Config } from '../config'; | ||
@@ -30,3 +28,3 @@ export declare abstract class DriverProvider { | ||
*/ | ||
getNewDriver(): WebDriver; | ||
getNewDriver(): Promise<WebDriver>; | ||
/** | ||
@@ -38,3 +36,3 @@ * Quit a driver. | ||
*/ | ||
quitDriver(driver: WebDriver): wdpromise.Promise<void>; | ||
quitDriver(driver: WebDriver): Promise<void>; | ||
/** | ||
@@ -45,3 +43,3 @@ * Quits an array of drivers and returns a q promise instead of a webdriver one | ||
*/ | ||
static quitDrivers(provider: DriverProvider, drivers: WebDriver[]): q.Promise<void>; | ||
static quitDrivers(provider: DriverProvider, drivers: WebDriver[]): Promise<void>; | ||
/** | ||
@@ -51,7 +49,7 @@ * Default update job method. | ||
*/ | ||
updateJob(update: any): q.Promise<any>; | ||
updateJob(update: any): Promise<any>; | ||
/** | ||
* Default setup environment method, common to all driver providers. | ||
*/ | ||
setupEnv(): q.Promise<any>; | ||
setupEnv(): Promise<any>; | ||
/** | ||
@@ -61,3 +59,3 @@ * Set up environment specific to a particular driver provider. Overridden | ||
*/ | ||
protected abstract setupDriverEnv(): q.Promise<any>; | ||
protected abstract setupDriverEnv(): Promise<any>; | ||
/** | ||
@@ -68,5 +66,5 @@ * Teardown and destroy the environment and do any associated cleanup. | ||
* @public | ||
* @return {q.Promise<any>} A promise which will resolve when the environment is down. | ||
* @return {Promise<any>} A promise which will resolve when the environment is down. | ||
*/ | ||
teardownEnv(): q.Promise<any>; | ||
teardownEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,5 +16,7 @@ /** | ||
*/ | ||
const q = require("q"); | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
const bpRunner_1 = require("../bpRunner"); | ||
const exitCodes_1 = require("../exitCodes"); | ||
const logger_1 = require("../logger"); | ||
let logger = new logger_1.Logger('driverProvider'); | ||
class DriverProvider { | ||
@@ -40,19 +50,27 @@ constructor(config) { | ||
getNewDriver() { | ||
let builder; | ||
if (this.config_.useBlockingProxy) { | ||
builder = | ||
new selenium_webdriver_1.Builder().usingServer(this.getBPUrl()).withCapabilities(this.config_.capabilities); | ||
} | ||
else { | ||
builder = new selenium_webdriver_1.Builder() | ||
.usingServer(this.config_.seleniumAddress) | ||
.usingWebDriverProxy(this.config_.webDriverProxy) | ||
.withCapabilities(this.config_.capabilities); | ||
} | ||
if (this.config_.disableEnvironmentOverrides === true) { | ||
builder.disableEnvironmentOverrides(); | ||
} | ||
let newDriver = builder.build(); | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let builder; | ||
if (this.config_.useBlockingProxy) { | ||
builder = | ||
new selenium_webdriver_1.Builder().usingServer(this.getBPUrl()).withCapabilities(this.config_.capabilities); | ||
} | ||
else { | ||
builder = new selenium_webdriver_1.Builder() | ||
.usingServer(this.config_.seleniumAddress) | ||
.usingWebDriverProxy(this.config_.webDriverProxy) | ||
.withCapabilities(this.config_.capabilities); | ||
} | ||
if (this.config_.disableEnvironmentOverrides === true) { | ||
builder.disableEnvironmentOverrides(); | ||
} | ||
let newDriver; | ||
try { | ||
newDriver = yield builder.build(); | ||
} | ||
catch (e) { | ||
throw new exitCodes_1.BrowserError(logger, e.message); | ||
} | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
}); | ||
} | ||
@@ -66,18 +84,17 @@ /** | ||
quitDriver(driver) { | ||
let driverIndex = this.drivers_.indexOf(driver); | ||
if (driverIndex >= 0) { | ||
this.drivers_.splice(driverIndex, 1); | ||
} | ||
if (driver.getSession() === undefined) { | ||
return selenium_webdriver_1.promise.when(undefined); | ||
} | ||
else { | ||
return driver.getSession() | ||
.then((session_) => { | ||
if (session_) { | ||
return driver.quit(); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let driverIndex = this.drivers_.indexOf(driver); | ||
if (driverIndex >= 0) { | ||
this.drivers_.splice(driverIndex, 1); | ||
try { | ||
yield driver.close(); | ||
yield driver.quit(); | ||
} | ||
}) | ||
.catch(function (err) { }); | ||
} | ||
catch (err) { | ||
// This happens when Protractor keeps track of all the webdrivers | ||
// created and calls quit. If a user calls driver.quit, then this will | ||
// throw an error. This catch will swallow the error. | ||
} | ||
} | ||
}); | ||
} | ||
@@ -90,13 +107,7 @@ /** | ||
static quitDrivers(provider, drivers) { | ||
let deferred = q.defer(); | ||
selenium_webdriver_1.promise | ||
.all(drivers.map((driver) => { | ||
return provider.quitDriver(driver); | ||
})) | ||
.then(() => { | ||
deferred.resolve(); | ||
}, () => { | ||
deferred.resolve(); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield Promise.all(drivers.map((driver) => { | ||
return provider.quitDriver(driver); | ||
})); | ||
}); | ||
return deferred.promise; | ||
} | ||
@@ -108,5 +119,4 @@ /** | ||
updateJob(update) { | ||
return q.fcall(function () { }); | ||
return __awaiter(this, void 0, void 0, function* () { }); | ||
} | ||
; | ||
/** | ||
@@ -116,10 +126,9 @@ * Default setup environment method, common to all driver providers. | ||
setupEnv() { | ||
let driverPromise = this.setupDriverEnv(); | ||
if (this.config_.useBlockingProxy && !this.config_.blockingProxyUrl) { | ||
// TODO(heathkit): If set, pass the webDriverProxy to BP. | ||
return driverPromise.then(() => this.bpRunner.start()); | ||
} | ||
return driverPromise; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.setupDriverEnv(); | ||
if (this.config_.useBlockingProxy && !this.config_.blockingProxyUrl) { | ||
yield this.bpRunner.start(); | ||
} | ||
}); | ||
} | ||
; | ||
/** | ||
@@ -130,6 +139,8 @@ * Teardown and destroy the environment and do any associated cleanup. | ||
* @public | ||
* @return {q.Promise<any>} A promise which will resolve when the environment is down. | ||
* @return {Promise<any>} A promise which will resolve when the environment is down. | ||
*/ | ||
teardownEnv() { | ||
return DriverProvider.quitDrivers(this, this.drivers_); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield DriverProvider.quitDrivers(this, this.drivers_); | ||
}); | ||
} | ||
@@ -136,0 +147,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -10,6 +8,6 @@ import { DriverProvider } from './driverProvider'; | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
* This is an implementation of the Hosted Driver Provider. | ||
* It is responsible for setting up the account object, tearing | ||
* it down, and setting up the driver correctly. | ||
*/ | ||
const q = require("q"); | ||
const logger_1 = require("../logger"); | ||
@@ -19,8 +21,9 @@ const driverProvider_1 = require("./driverProvider"); | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
logger.info('Using the selenium server at ' + this.config_.seleniumAddress); | ||
return q.fcall(function () { }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
logger.info('Using the selenium server at ' + this.config_.seleniumAddress); | ||
}); | ||
} | ||
@@ -27,0 +30,0 @@ } |
@@ -11,3 +11,2 @@ export * from './attachSession'; | ||
export * from './kobiton'; | ||
export * from './useExistingWebDriver'; | ||
import { DriverProvider } from './driverProvider'; | ||
@@ -14,0 +13,0 @@ import { Config } from '../config'; |
@@ -16,3 +16,2 @@ "use strict"; | ||
__export(require("./kobiton")); | ||
__export(require("./useExistingWebDriver")); | ||
const attachSession_1 = require("./attachSession"); | ||
@@ -27,3 +26,2 @@ const browserStack_1 = require("./browserStack"); | ||
const kobiton_1 = require("./kobiton"); | ||
const useExistingWebDriver_1 = require("./useExistingWebDriver"); | ||
const logger_1 = require("../logger"); | ||
@@ -37,6 +35,2 @@ let logger = new logger_1.Logger('driverProviders'); | ||
} | ||
else if (config.seleniumWebDriver) { | ||
driverProvider = new useExistingWebDriver_1.UseExistingWebDriver(config); | ||
exports.logWarnings('useExistingWebDriver', config); | ||
} | ||
else if (config.seleniumAddress) { | ||
@@ -125,5 +119,2 @@ if (config.seleniumSessionId) { | ||
} | ||
if ('useExistingWebDriver' !== providerType && config.seleniumWebDriver) { | ||
warnList.push('seleniumWebDriver'); | ||
} | ||
if (warnList.length !== 0) { | ||
@@ -130,0 +121,0 @@ logger.warn(warnInto + warnList.join(', ')); |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -9,6 +7,6 @@ import { DriverProvider } from './driverProvider'; | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
* This is an implementation of the Kobiton Driver Provider. | ||
* It is responsible for setting up the account object, tearing | ||
* it down, and setting up the driver correctly. | ||
*/ | ||
const q = require("q"); | ||
const logger_1 = require("../logger"); | ||
@@ -18,14 +20,13 @@ const driverProvider_1 = require("./driverProvider"); | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
let deferred = q.defer(); | ||
this.config_.capabilities['kobitonUser'] = this.config_.kobitonUser; | ||
this.config_.capabilities['kobitonKey'] = this.config_.kobitonKey; | ||
this.config_.seleniumAddress = 'https://' + this.config_.kobitonUser + ':' + | ||
this.config_.kobitonKey + '@api.kobiton.com/wd/hub'; | ||
logger.info('Using Kobiton selenium server at ' + this.config_.seleniumAddress); | ||
deferred.resolve(); | ||
return deferred.promise; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.config_.capabilities['kobitonUser'] = this.config_.kobitonUser; | ||
this.config_.capabilities['kobitonKey'] = this.config_.kobitonKey; | ||
this.config_.seleniumAddress = 'https://' + this.config_.kobitonUser + ':' + | ||
this.config_.kobitonKey + '@api.kobiton.com/wd/hub'; | ||
logger.info('Using Kobiton selenium server at ' + this.config_.seleniumAddress); | ||
}); | ||
} | ||
@@ -32,0 +33,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -16,16 +14,6 @@ import { DriverProvider } from './driverProvider'; | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv(): q.Promise<any>; | ||
/** | ||
* Teardown and destroy the environment and do any associated cleanup. | ||
* Shuts down the drivers and server. | ||
* | ||
* @public | ||
* @override | ||
* @return {q.promise} A promise which will resolve when the environment | ||
* is down. | ||
*/ | ||
teardownEnv(): q.Promise<any>; | ||
setupDriverEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -12,9 +20,7 @@ /* | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const q = require("q"); | ||
const remote_1 = require("selenium-webdriver/remote"); | ||
const webdriver_manager_1 = require("webdriver-manager"); | ||
const exitCodes_1 = require("../exitCodes"); | ||
const logger_1 = require("../logger"); | ||
const driverProvider_1 = require("./driverProvider"); | ||
const SeleniumConfig = require('webdriver-manager/built/lib/config').Config; | ||
const remote = require('selenium-webdriver/remote'); | ||
let logger = new logger_1.Logger('local'); | ||
@@ -35,9 +41,6 @@ class Local extends driverProvider_1.DriverProvider { | ||
try { | ||
let updateJson = path.resolve(SeleniumConfig.getSeleniumDir(), 'update-config.json'); | ||
let updateConfig = JSON.parse(fs.readFileSync(updateJson).toString()); | ||
this.config_.seleniumServerJar = updateConfig.standalone.last; | ||
this.config_.seleniumServerJar = new webdriver_manager_1.SeleniumServer().getBinaryPath(); | ||
} | ||
catch (err) { | ||
throw new exitCodes_1.BrowserError(logger, 'No update-config.json found.' + | ||
' Run \'webdriver-manager update\' to download binaries.'); | ||
throw new exitCodes_1.BrowserError(logger, 'Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
@@ -54,9 +57,6 @@ } | ||
try { | ||
let updateJson = path.resolve(SeleniumConfig.getSeleniumDir(), 'update-config.json'); | ||
let updateConfig = JSON.parse(fs.readFileSync(updateJson).toString()); | ||
this.config_.chromeDriver = updateConfig.chrome.last; | ||
this.config_.chromeDriver = new webdriver_manager_1.ChromeDriver().getBinaryPath(); | ||
} | ||
catch (err) { | ||
throw new exitCodes_1.BrowserError(logger, 'No update-config.json found. ' + | ||
'Run \'webdriver-manager update\' to download binaries.'); | ||
throw new exitCodes_1.BrowserError(logger, 'Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
@@ -80,9 +80,6 @@ } | ||
try { | ||
let updateJson = path.resolve(SeleniumConfig.getSeleniumDir(), 'update-config.json'); | ||
let updateConfig = JSON.parse(fs.readFileSync(updateJson).toString()); | ||
this.config_.geckoDriver = updateConfig.gecko.last; | ||
this.config_.geckoDriver = new webdriver_manager_1.GeckoDriver().getBinaryPath(); | ||
} | ||
catch (err) { | ||
throw new exitCodes_1.BrowserError(logger, 'No update-config.json found. ' + | ||
'Run \'webdriver-manager update\' to download binaries.'); | ||
throw new exitCodes_1.BrowserError(logger, 'Run \'webdriver-manager update\' to download binaries.'); | ||
} | ||
@@ -105,66 +102,43 @@ } | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
this.addDefaultBinaryLocs_(); | ||
logger.info('Starting selenium standalone server...'); | ||
let serverConf = this.config_.localSeleniumStandaloneOpts || {}; | ||
// If args or port is not set use seleniumArgs and seleniumPort | ||
// for backward compatibility | ||
if (serverConf.args === undefined) { | ||
serverConf.args = this.config_.seleniumArgs || []; | ||
} | ||
if (serverConf.jvmArgs === undefined) { | ||
serverConf.jvmArgs = this.config_.jvmArgs || []; | ||
} | ||
else { | ||
if (!Array.isArray(serverConf.jvmArgs)) { | ||
throw new exitCodes_1.ConfigError(logger, 'jvmArgs should be an array.'); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.addDefaultBinaryLocs_(); | ||
logger.info('Starting selenium standalone server...'); | ||
let serverConf = this.config_.localSeleniumStandaloneOpts || {}; | ||
// If args or port is not set use seleniumArgs and seleniumPort | ||
// for backward compatibility | ||
if (serverConf.args === undefined) { | ||
serverConf.args = this.config_.seleniumArgs || []; | ||
} | ||
} | ||
if (serverConf.port === undefined) { | ||
serverConf.port = this.config_.seleniumPort; | ||
} | ||
// configure server | ||
if (this.config_.chromeDriver) { | ||
serverConf.jvmArgs.push('-Dwebdriver.chrome.driver=' + this.config_.chromeDriver); | ||
} | ||
if (this.config_.geckoDriver) { | ||
serverConf.jvmArgs.push('-Dwebdriver.gecko.driver=' + this.config_.geckoDriver); | ||
} | ||
this.server_ = new remote.SeleniumServer(this.config_.seleniumServerJar, serverConf); | ||
let deferred = q.defer(); | ||
// start local server, grab hosted address, and resolve promise | ||
this.server_.start(this.config_.seleniumServerStartTimeout) | ||
.then((url) => { | ||
if (serverConf.jvmArgs === undefined) { | ||
serverConf.jvmArgs = this.config_.jvmArgs || []; | ||
} | ||
else { | ||
if (!Array.isArray(serverConf.jvmArgs)) { | ||
throw new exitCodes_1.ConfigError(logger, 'jvmArgs should be an array.'); | ||
} | ||
} | ||
if (serverConf.port === undefined) { | ||
serverConf.port = this.config_.seleniumPort; | ||
} | ||
// configure server | ||
if (this.config_.chromeDriver) { | ||
serverConf.jvmArgs.push('-Dwebdriver.chrome.driver=' + this.config_.chromeDriver); | ||
} | ||
if (this.config_.geckoDriver) { | ||
serverConf.jvmArgs.push('-Dwebdriver.gecko.driver=' + this.config_.geckoDriver); | ||
} | ||
this.server_ = new remote_1.SeleniumServer(this.config_.seleniumServerJar, serverConf); | ||
// start local server, grab hosted address, and resolve promise | ||
const url = yield this.server_.start(this.config_.seleniumServerStartTimeout); | ||
logger.info('Selenium standalone server started at ' + url); | ||
return this.server_.address(); | ||
}) | ||
.then((address) => { | ||
const address = yield this.server_.address(); | ||
this.config_.seleniumAddress = address; | ||
deferred.resolve(); | ||
}) | ||
.catch((err) => { | ||
deferred.reject(err); | ||
}); | ||
return deferred.promise; | ||
} | ||
/** | ||
* Teardown and destroy the environment and do any associated cleanup. | ||
* Shuts down the drivers and server. | ||
* | ||
* @public | ||
* @override | ||
* @return {q.promise} A promise which will resolve when the environment | ||
* is down. | ||
*/ | ||
teardownEnv() { | ||
return super.teardownEnv().then(() => { | ||
logger.info('Shutting down selenium standalone server.'); | ||
return this.server_.stop(); | ||
}); | ||
} | ||
} | ||
exports.Local = Local; | ||
//# sourceMappingURL=local.js.map |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { WebDriver } from 'selenium-webdriver'; | ||
@@ -14,9 +12,9 @@ import { Config } from '../config'; | ||
*/ | ||
execute(): q.Promise<any>; | ||
execute(): Promise<any>; | ||
/** | ||
* Configure and launch (if applicable) the object's environment. | ||
* @public | ||
* @return {q.promise} A promise which will resolve immediately. | ||
* @return {Promise} A promise which will resolve immediately. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
/** | ||
@@ -29,3 +27,3 @@ * Create a new driver. | ||
*/ | ||
getNewDriver(): WebDriver; | ||
getNewDriver(): Promise<WebDriver>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,3 +16,2 @@ /* | ||
*/ | ||
const q = require("q"); | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
@@ -24,5 +31,5 @@ const driverProvider_1 = require("./driverProvider"); | ||
execute() { | ||
let deferred = q.defer(); | ||
deferred.resolve({ value: 'test_response' }); | ||
return deferred.promise; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return { value: 'test_response' }; | ||
}); | ||
} | ||
@@ -32,6 +39,6 @@ /** | ||
* @public | ||
* @return {q.promise} A promise which will resolve immediately. | ||
* @return {Promise} A promise which will resolve immediately. | ||
*/ | ||
setupDriverEnv() { | ||
return q.fcall(function () { }); | ||
return __awaiter(this, void 0, void 0, function* () { }); | ||
} | ||
@@ -46,6 +53,8 @@ /** | ||
getNewDriver() { | ||
let mockSession = new selenium_webdriver_1.Session('test_session_id', {}); | ||
let newDriver = new selenium_webdriver_1.WebDriver(mockSession, new MockExecutor()); | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let mockSession = new selenium_webdriver_1.Session('test_session_id', {}); | ||
let newDriver = new selenium_webdriver_1.WebDriver(mockSession, new MockExecutor()); | ||
this.drivers_.push(newDriver); | ||
return newDriver; | ||
}); | ||
} | ||
@@ -52,0 +61,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -12,12 +10,12 @@ import { DriverProvider } from './driverProvider'; | ||
* @param {Object} update | ||
* @return {q.promise} A promise that will resolve when the update is complete. | ||
* @return {Promise} A promise that will resolve when the update is complete. | ||
*/ | ||
updateJob(update: any): q.Promise<any>; | ||
updateJob(update: any): Promise<any>; | ||
/** | ||
* Configure and launch (if applicable) the object's environment. | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
/** | ||
@@ -29,3 +27,3 @@ * Get the Sauce Labs endpoint | ||
*/ | ||
private getSauceEndpoint(region); | ||
private getSauceEndpoint; | ||
} |
@@ -7,4 +7,11 @@ "use strict"; | ||
*/ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const q = require("q"); | ||
const util = require("util"); | ||
@@ -27,7 +34,6 @@ const logger_1 = require("../logger"); | ||
* @param {Object} update | ||
* @return {q.promise} A promise that will resolve when the update is complete. | ||
* @return {Promise} A promise that will resolve when the update is complete. | ||
*/ | ||
updateJob(update) { | ||
let deferredArray = this.drivers_.map((driver) => { | ||
let deferred = q.defer(); | ||
let mappedDrivers = this.drivers_.map((driver) => { | ||
driver.getSession().then((session) => { | ||
@@ -39,8 +45,6 @@ logger.info('SauceLabs results available at http://saucelabs.com/jobs/' + session.getId()); | ||
} | ||
deferred.resolve(); | ||
}); | ||
}); | ||
return deferred.promise; | ||
}); | ||
return q.all(deferredArray); | ||
return Promise.all(mappedDrivers); | ||
} | ||
@@ -50,33 +54,32 @@ /** | ||
* @public | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
let deferred = q.defer(); | ||
this.sauceServer_ = new SauceLabs({ | ||
hostname: this.getSauceEndpoint(this.config_.sauceRegion), | ||
username: this.config_.sauceUser, | ||
password: this.config_.sauceKey, | ||
agent: this.config_.sauceAgent, | ||
proxy: this.config_.sauceProxy | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.sauceServer_ = new SauceLabs({ | ||
hostname: this.getSauceEndpoint(this.config_.sauceRegion), | ||
username: this.config_.sauceUser, | ||
password: this.config_.sauceKey, | ||
agent: this.config_.sauceAgent, | ||
proxy: this.config_.sauceProxy | ||
}); | ||
this.config_.capabilities['username'] = this.config_.sauceUser; | ||
this.config_.capabilities['accessKey'] = this.config_.sauceKey; | ||
this.config_.capabilities['build'] = this.config_.sauceBuild; | ||
let protocol = this.config_.sauceSeleniumUseHttp ? 'http://' : 'https://'; | ||
let auth = protocol + this.config_.sauceUser + ':' + this.config_.sauceKey + '@'; | ||
this.config_.seleniumAddress = auth + | ||
(this.config_.sauceSeleniumAddress ? | ||
this.config_.sauceSeleniumAddress : | ||
`ondemand.${this.getSauceEndpoint(this.config_.sauceRegion)}:443/wd/hub`); | ||
// Append filename to capabilities.name so that it's easier to identify | ||
// tests. | ||
if (this.config_.capabilities.name && this.config_.capabilities.shardTestFiles) { | ||
this.config_.capabilities.name += | ||
(':' + this.config_.specs.toString().replace(/^.*[\\\/]/, '')); | ||
} | ||
logger.info('Using SauceLabs selenium server at ' + | ||
this.config_.seleniumAddress.replace(/\/\/.+@/, '//')); | ||
}); | ||
this.config_.capabilities['username'] = this.config_.sauceUser; | ||
this.config_.capabilities['accessKey'] = this.config_.sauceKey; | ||
this.config_.capabilities['build'] = this.config_.sauceBuild; | ||
let protocol = this.config_.sauceSeleniumUseHttp ? 'http://' : 'https://'; | ||
let auth = protocol + this.config_.sauceUser + ':' + this.config_.sauceKey + '@'; | ||
this.config_.seleniumAddress = auth + | ||
(this.config_.sauceSeleniumAddress ? | ||
this.config_.sauceSeleniumAddress : | ||
`ondemand.${this.getSauceEndpoint(this.config_.sauceRegion)}:443/wd/hub`); | ||
// Append filename to capabilities.name so that it's easier to identify | ||
// tests. | ||
if (this.config_.capabilities.name && this.config_.capabilities.shardTestFiles) { | ||
this.config_.capabilities.name += | ||
(':' + this.config_.specs.toString().replace(/^.*[\\\/]/, '')); | ||
} | ||
logger.info('Using SauceLabs selenium server at ' + | ||
this.config_.seleniumAddress.replace(/\/\/.+@/, '//')); | ||
deferred.resolve(); | ||
return deferred.promise; | ||
} | ||
@@ -83,0 +86,0 @@ /** |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import { Config } from '../config'; | ||
@@ -9,6 +7,6 @@ import { DriverProvider } from './driverProvider'; | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
protected setupDriverEnv(): q.Promise<any>; | ||
protected setupDriverEnv(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
* This is an implementation of the TestObject Driver Provider. | ||
* It is responsible for setting up the account object, tearing | ||
* it down, and setting up the driver correctly. | ||
*/ | ||
const q = require("q"); | ||
const logger_1 = require("../logger"); | ||
@@ -18,13 +20,12 @@ const driverProvider_1 = require("./driverProvider"); | ||
* Configure and launch (if applicable) the object's environment. | ||
* @return {q.promise} A promise which will resolve when the environment is | ||
* @return {Promise} A promise which will resolve when the environment is | ||
* ready to test. | ||
*/ | ||
setupDriverEnv() { | ||
let deferred = q.defer(); | ||
this.config_.capabilities['testobject.user'] = this.config_.testobjectUser; | ||
this.config_.capabilities['testobject_api_key'] = this.config_.testobjectKey; | ||
this.config_.seleniumAddress = 'https://us1.appium.testobject.com/wd/hub'; | ||
logger.info('Using TestObject selenium server at ' + this.config_.seleniumAddress); | ||
deferred.resolve(); | ||
return deferred.promise; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.config_.capabilities['testobject.user'] = this.config_.testobjectUser; | ||
this.config_.capabilities['testobject_api_key'] = this.config_.testobjectKey; | ||
this.config_.seleniumAddress = 'https://us1.appium.testobject.com/wd/hub'; | ||
logger.info('Using TestObject selenium server at ' + this.config_.seleniumAddress); | ||
}); | ||
} | ||
@@ -31,0 +32,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { By, promise as wdpromise, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
import { By, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
import { ElementHelper, ProtractorBrowser } from './browser'; | ||
@@ -46,13 +46,11 @@ import { Locator } from './locators'; | ||
* @example | ||
* element.all(by.css('.items li')).then(function(items) { | ||
* expect(items.length).toBe(3); | ||
* expect(items[0].getText()).toBe('First'); | ||
* }); | ||
* const items = await element.all(by.css('.items li')); | ||
* expect(items.length).toBe(3); | ||
* expect(await items[0].getText()).toBe('First'); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').then(function(items) { | ||
* expect(items.length).toBe(3); | ||
* expect(items[0].getText()).toBe('First'); | ||
* }); | ||
* const items = await $$('.items li'); | ||
* expect(items.length).toBe(3); | ||
* expect(await items[0].getText()).toBe('First'); | ||
* | ||
@@ -63,5 +61,5 @@ * @constructor | ||
* that returns a list of the underlying Web Elements. | ||
* @param {webdriver.Locator} locator The most relevant locator. It is only | ||
* @param {Locator} locator The most relevant locator. It is only | ||
* used for error reporting and ElementArrayFinder.locator. | ||
* @param {Array.<webdriver.promise.Promise>} opt_actionResults An array | ||
* @param {Array<Promise>} opt_actionResults An array | ||
* of promises which will be retrieved with then. Resolves to the latest | ||
@@ -73,6 +71,6 @@ * action result, or null if no action has been called. | ||
browser_: ProtractorBrowser; | ||
getWebElements: () => wdpromise.Promise<WebElement[]>; | ||
locator_: any; | ||
actionResults_: wdpromise.Promise<any>; | ||
constructor(browser_: ProtractorBrowser, getWebElements?: () => wdpromise.Promise<WebElement[]>, locator_?: any, actionResults_?: wdpromise.Promise<any>); | ||
getWebElements: () => Promise<WebElement[]>; | ||
locator_?: any; | ||
actionResults_: Promise<any>; | ||
constructor(browser_: ProtractorBrowser, getWebElements?: () => Promise<WebElement[]>, locator_?: any, actionResults_?: Promise<any>); | ||
/** | ||
@@ -107,8 +105,8 @@ * Create a shallow copy of ElementArrayFinder. | ||
* let foo = element.all(by.css('.parent')).all(by.css('.foo')); | ||
* expect(foo.getText()).toEqual(['1a', '2a']); | ||
* expect(await foo.getText()).toEqual(['1a', '2a']); | ||
* let baz = element.all(by.css('.parent')).all(by.css('.baz')); | ||
* expect(baz.getText()).toEqual(['1b']); | ||
* expect(await baz.getText()).toEqual(['1b']); | ||
* let nonexistent = element.all(by.css('.parent')) | ||
* .all(by.css('.NONEXISTENT')); | ||
* expect(nonexistent.getText()).toEqual(['']); | ||
* expect(await nonexistent.getText()).toEqual(['']); | ||
* | ||
@@ -118,9 +116,9 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let foo = $$('.parent').$$('.foo'); | ||
* expect(foo.getText()).toEqual(['1a', '2a']); | ||
* expect(await foo.getText()).toEqual(['1a', '2a']); | ||
* let baz = $$('.parent').$$('.baz'); | ||
* expect(baz.getText()).toEqual(['1b']); | ||
* expect(await baz.getText()).toEqual(['1b']); | ||
* let nonexistent = $$('.parent').$$('.NONEXISTENT'); | ||
* expect(nonexistent.getText()).toEqual(['']); | ||
* expect(await nonexistent.getText()).toEqual(['']); | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} locator | ||
* @returns {ElementArrayFinder} | ||
@@ -145,21 +143,18 @@ */ | ||
* @example | ||
* element.all(by.css('.items li')).filter(function(elem, index) { | ||
* return elem.getText().then(function(text) { | ||
* return text === 'Third'; | ||
* }); | ||
* }).first().click(); | ||
* await element.all(by.css('.items li')) | ||
* .filter(async (elem, index) => await elem.getText() === 'Third') | ||
* .first() | ||
* .click(); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').filter(function(elem, index) { | ||
* return elem.getText().then(function(text) { | ||
* return text === 'Third'; | ||
* }); | ||
* }).first().click(); | ||
* await $$('.items li') | ||
* .filter(async (elem, index) => await elem.getText() === 'Third') | ||
* .first() | ||
* .click(); | ||
* | ||
* @param {function(ElementFinder, number): webdriver.WebElement.Promise} | ||
* filterFn | ||
* @param {function(ElementFinder, number): boolean|Promise<boolean>} filterFn | ||
* Filter function that will test if an element should be returned. | ||
* filterFn can either return a boolean or a promise that resolves to a | ||
* boolean | ||
* boolean. | ||
* @returns {!ElementArrayFinder} A ElementArrayFinder that represents an | ||
@@ -169,6 +164,6 @@ * array | ||
*/ | ||
filter(filterFn: (element: ElementFinder, index?: number) => boolean | wdpromise.Promise<boolean>): ElementArrayFinder; | ||
filter(filterFn: (element: ElementFinder, index?: number) => boolean | Promise<boolean>): ElementArrayFinder; | ||
/** | ||
* Get an element within the ElementArrayFinder by index. The index starts at 0. | ||
* Negative indices are wrapped (i.e. -i means ith element from last) | ||
* Get an element within the ElementArrayFinder by index. The index starts at | ||
* 0. Negative indices are wrapped (i.e. -i means ith element from last) | ||
* This does not actually retrieve the underlying element. | ||
@@ -186,4 +181,4 @@ * | ||
* let list = element.all(by.css('.items li')); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -193,9 +188,9 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.items li'); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
* @param {number|webdriver.promise.Promise} index Element index. | ||
* @param {number|Promise} indexPromise Element index. | ||
* @returns {ElementFinder} finder representing element at the given index. | ||
*/ | ||
get(index: number | wdpromise.Promise<number>): ElementFinder; | ||
get(indexPromise: number | Promise<number>): ElementFinder; | ||
/** | ||
@@ -215,3 +210,3 @@ * Get the first matching element for the ElementArrayFinder. This does not | ||
* let first = element.all(by.css('.items li')).first(); | ||
* expect(first.getText()).toBe('First'); | ||
* expect(await first.getText()).toBe('First'); | ||
* | ||
@@ -221,3 +216,3 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let first = $$('.items li').first(); | ||
* expect(first.getText()).toBe('First'); | ||
* expect(await first.getText()).toBe('First'); | ||
* | ||
@@ -241,3 +236,3 @@ * @returns {ElementFinder} finder representing the first matching element | ||
* let last = element.all(by.css('.items li')).last(); | ||
* expect(last.getText()).toBe('Third'); | ||
* expect(await last.getText()).toBe('Third'); | ||
* | ||
@@ -247,3 +242,3 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let last = $$('.items li').last(); | ||
* expect(last.getText()).toBe('Third'); | ||
* expect(await last.getText()).toBe('Third'); | ||
* | ||
@@ -267,5 +262,5 @@ * @returns {ElementFinder} finder representing the last matching element | ||
* let list = element.all(by.css('.count span')); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -275,5 +270,5 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.count span'); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -307,3 +302,3 @@ * @param {string} selector a css selector | ||
* let list = element.all(by.css('.items li')); | ||
* expect(list.count()).toBe(3); | ||
* expect(await list.count()).toBe(3); | ||
* | ||
@@ -313,8 +308,8 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.items li'); | ||
* expect(list.count()).toBe(3); | ||
* expect(await list.count()).toBe(3); | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise which resolves to the | ||
* @returns {!Promise} A promise which resolves to the | ||
* number of elements matching the locator. | ||
*/ | ||
count(): wdpromise.Promise<number>; | ||
count(): Promise<number>; | ||
/** | ||
@@ -326,7 +321,7 @@ * Returns true if there are any elements present that match the finder. | ||
* @example | ||
* expect($('.item').isPresent()).toBeTruthy(); | ||
* expect(await $('.item').isPresent()).toBeTruthy(); | ||
* | ||
* @returns {Promise<boolean>} | ||
*/ | ||
isPresent(): wdpromise.Promise<boolean>; | ||
isPresent(): Promise<boolean>; | ||
/** | ||
@@ -345,3 +340,3 @@ * Returns the most relevant locator. | ||
* | ||
* @returns {webdriver.Locator} | ||
* @returns {Locator} | ||
*/ | ||
@@ -359,10 +354,10 @@ locator(): Locator; | ||
*/ | ||
private applyAction_(actionFn); | ||
private applyAction_; | ||
/** | ||
* Represents the ElementArrayFinder as an array of ElementFinders. | ||
* | ||
* @returns {Array.<ElementFinder>} Return a promise, which resolves to a list | ||
* of ElementFinders specified by the locator. | ||
* @returns {Promise<ElementFinder[]>} Return a promise, which resolves to a | ||
* list of ElementFinders specified by the locator. | ||
*/ | ||
asElementFinders_(): wdpromise.Promise<ElementFinder[]>; | ||
asElementFinders_(): Promise<ElementFinder[]>; | ||
/** | ||
@@ -382,11 +377,9 @@ * Retrieve the elements represented by the ElementArrayFinder. The input | ||
* @example | ||
* element.all(by.css('.items li')).then(function(arr) { | ||
* expect(arr.length).toEqual(3); | ||
* }); | ||
* const arr = await element.all(by.css('.items li')); | ||
* expect(arr.length).toEqual(3); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').then(function(arr) { | ||
* expect(arr.length).toEqual(3); | ||
* }); | ||
* const arr = $$('.items li'); | ||
* expect(arr.length).toEqual(3); | ||
* | ||
@@ -396,6 +389,6 @@ * @param {function(Array.<ElementFinder>)} fn | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise which will resolve to | ||
* @returns {!Promise} A promise which will resolve to | ||
* an array of ElementFinders represented by the ElementArrayFinder. | ||
*/ | ||
then<T>(fn?: (value: ElementFinder[] | any[]) => T | wdpromise.IThenable<T>, errorFn?: (error: any) => any): wdpromise.Promise<T>; | ||
then<T>(fn?: (value: ElementFinder[] | any[]) => T | Promise<T>, errorFn?: (error: any) => any): Promise<T>; | ||
/** | ||
@@ -414,7 +407,5 @@ * Calls the input function on each ElementFinder represented by the | ||
* @example | ||
* element.all(by.css('.items li')).each(function(element, index) { | ||
* await element.all(by.css('.items li')).each(async (element, index) => { | ||
* // Will print 0 First, 1 Second, 2 Third. | ||
* element.getText().then(function (text) { | ||
* console.log(index, text); | ||
* }); | ||
* console.log(index, await element.getText()); | ||
* }); | ||
@@ -424,7 +415,5 @@ * | ||
* | ||
* $$('.items li').each(function(element, index) { | ||
* $$('.items li').each(async (element, index) => { | ||
* // Will print 0 First, 1 Second, 2 Third. | ||
* element.getText().then(function (text) { | ||
* console.log(index, text); | ||
* }); | ||
* console.log(index, await element.getText()); | ||
* }); | ||
@@ -434,7 +423,7 @@ * | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve when the | ||
* @returns {!Promise} A promise that will resolve when the | ||
* function has been called on all the ElementFinders. The promise will | ||
* resolve to null. | ||
*/ | ||
each(fn: (elementFinder?: ElementFinder, index?: number) => any): wdpromise.Promise<any>; | ||
each(fn: (elementFinder?: ElementFinder, index?: number) => any): Promise<any>; | ||
/** | ||
@@ -454,9 +443,10 @@ * Apply a map function to each element within the ElementArrayFinder. The | ||
* @example | ||
* let items = element.all(by.css('.items li')).map(function(elm, index) { | ||
* return { | ||
* index: index, | ||
* text: elm.getText(), | ||
* class: elm.getAttribute('class') | ||
* }; | ||
* }); | ||
* let items = await element.all(by.css('.items li')) | ||
* .map(async (elm, index) => { | ||
* return { | ||
* index: index, | ||
* text: await elm.getText(), | ||
* class: await elm.getAttribute('class') | ||
* }; | ||
* }); | ||
* expect(items).toEqual([ | ||
@@ -470,7 +460,7 @@ * {index: 0, text: 'First', class: 'one'}, | ||
* | ||
* let items = $$('.items li').map(function(elm, index) { | ||
* let items = await $$('.items li').map(async (elm, index) => { | ||
* return { | ||
* index: index, | ||
* text: elm.getText(), | ||
* class: elm.getAttribute('class') | ||
* text: await elm.getText(), | ||
* class: await elm.getAttribute('class') | ||
* }; | ||
@@ -486,6 +476,6 @@ * }); | ||
* will be applied to each element. | ||
* @returns {!webdriver.promise.Promise} A promise that resolves to an array | ||
* @returns {!Promise} A promise that resolves to an array | ||
* of values returned by the map function. | ||
*/ | ||
map<T>(mapFn: (elementFinder?: ElementFinder, index?: number) => T | any): wdpromise.Promise<T[]>; | ||
map<T>(mapFn: (elementFinder?: ElementFinder, index?: number) => T | any): Promise<T[]>; | ||
/** | ||
@@ -508,7 +498,4 @@ * Apply a reduce function against an accumulator and every element found | ||
* @example | ||
* let value = element.all(by.css('.items li')).reduce(function(acc, elem) { | ||
* return elem.getText().then(function(text) { | ||
* return acc + text + ' '; | ||
* }); | ||
* }, ''); | ||
* let value = await element.all(by.css('.items li')) | ||
* .reduce(async (acc, elem) => acc + (await elem.getText()) + ' ', ''); | ||
* | ||
@@ -519,7 +506,4 @@ * expect(value).toEqual('First Second Third '); | ||
* | ||
* let value = $$('.items li').reduce(function(acc, elem) { | ||
* return elem.getText().then(function(text) { | ||
* return acc + text + ' '; | ||
* }); | ||
* }, ''); | ||
* let value = await $$('.items li') | ||
* .reduce(async (acc, elem) => acc + (await elem.getText()) + ' ', ''); | ||
* | ||
@@ -532,6 +516,6 @@ * expect(value).toEqual('First Second Third '); | ||
* @param {*} initialValue Initial value of the accumulator. | ||
* @returns {!webdriver.promise.Promise} A promise that resolves to the final | ||
* @returns {!Promise} A promise that resolves to the final | ||
* value of the accumulator. | ||
*/ | ||
reduce(reduceFn: Function, initialValue: any): wdpromise.Promise<any>; | ||
reduce(reduceFn: Function, initialValue: any): Promise<any>; | ||
/** | ||
@@ -604,13 +588,13 @@ * Evaluates the input as if it were on the scope of the current underlying | ||
* // Find element with {{scopelet}} syntax. | ||
* element(by.binding('person.name')).getText().then(function(name) { | ||
* expect(name).toBe('Foo'); | ||
* }); | ||
* const name = await element(by.binding('person.name')).getText(); | ||
* expect(name).toBe('Foo'); | ||
* | ||
* // Find element with ng-bind="scopelet" syntax. | ||
* expect(element(by.binding('person.email')).getText()).toBe('foo@bar.com'); | ||
* const email = await element(by.binding('person.email')).getText(); | ||
* expect(email).toBe('foo@bar.com'); | ||
* | ||
* // Find by model. | ||
* let input = element(by.model('person.name')); | ||
* input.sendKeys('123'); | ||
* expect(input.getAttribute('value')).toBe('Foo123'); | ||
* await input.sendKeys('123'); | ||
* expect(await input.getAttribute('value')).toBe('Foo123'); | ||
* | ||
@@ -628,3 +612,3 @@ * @constructor | ||
elementArrayFinder_: ElementArrayFinder; | ||
then?: (fn: (value: any) => any | wdpromise.IThenable<any>, errorFn?: (error: any) => any) => wdpromise.Promise<any>; | ||
then?: (fn: (value: any) => any | Promise<any>, errorFn?: (error: any) => any) => Promise<any>; | ||
constructor(browser_: ProtractorBrowser, elementArrayFinder: ElementArrayFinder); | ||
@@ -641,3 +625,3 @@ static fromWebElement_(browser: ProtractorBrowser, webElem: WebElement, locator?: Locator): ElementFinder; | ||
* | ||
* @returns {webdriver.Locator} | ||
* @returns {Locator} | ||
*/ | ||
@@ -662,3 +646,3 @@ locator(): any; | ||
* | ||
* @returns {webdriver.WebElementPromise} | ||
* @returns {webdriver.WebElement} | ||
*/ | ||
@@ -687,3 +671,3 @@ getWebElement(): WebElementPromise; | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} subLocator | ||
* @returns {ElementArrayFinder} | ||
@@ -708,3 +692,3 @@ */ | ||
* element(by.css('.child')); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -715,3 +699,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -722,3 +706,3 @@ * // Or using the shortcut $() notation instead of element(by.css()): | ||
* let child = $('.parent').$('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -728,5 +712,5 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} subLocator | ||
* @returns {ElementFinder} | ||
@@ -776,3 +760,3 @@ */ | ||
* $('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -783,3 +767,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -790,3 +774,3 @@ * // Or using the shortcut $() notation instead of element(by.css()): | ||
* let child = $('.parent').$('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -796,3 +780,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -811,11 +795,11 @@ * @param {string} selector A css selector | ||
* // Element exists. | ||
* expect(element(by.binding('person.name')).isPresent()).toBe(true); | ||
* expect(await element(by.binding('person.name')).isPresent()).toBe(true); | ||
* | ||
* // Element not present. | ||
* expect(element(by.binding('notPresent')).isPresent()).toBe(false); | ||
* expect(await element(by.binding('notPresent')).isPresent()).toBe(false); | ||
* | ||
* @returns {webdriver.promise.Promise<boolean>} which resolves to whether | ||
* @returns {Promise<boolean>} which resolves to whether | ||
* the element is present on the page. | ||
*/ | ||
isPresent(): wdpromise.Promise<boolean>; | ||
isPresent(): Promise<boolean>; | ||
/** | ||
@@ -834,7 +818,7 @@ * Same as ElementFinder.isPresent(), except this checks whether the element | ||
* | ||
* @param {webdriver.Locator} subLocator Locator for element to look for. | ||
* @returns {webdriver.promise.Promise<boolean>} which resolves to whether | ||
* @param {Locator} subLocator Locator for element to look for. | ||
* @returns {Promise<boolean>} which resolves to whether | ||
* the subelement is present on the page. | ||
*/ | ||
isElementPresent(subLocator: Locator): wdpromise.Promise<boolean>; | ||
isElementPresent(subLocator: Locator): Promise<boolean>; | ||
/** | ||
@@ -865,8 +849,8 @@ * Evaluates the input as if it were on the scope of the current element. | ||
* | ||
* @param {!ElementFinder|!webdriver.WebElement} The element to compare to. | ||
* @param {!ElementFinder|!webdriver.WebElement} element The element to compare to. | ||
* | ||
* @returns {!webdriver.promise.Promise.<boolean>} A promise that will be | ||
* @returns {!Promise<boolean>} A promise that will be | ||
* resolved to whether the two WebElements are equal. | ||
*/ | ||
equals(element: ElementFinder | WebElement): wdpromise.Promise<any>; | ||
equals(element: ElementFinder | WebElement): Promise<boolean>; | ||
} | ||
@@ -886,3 +870,3 @@ /** | ||
* let item = $('.count .two'); | ||
* expect(item.getText()).toBe('Second'); | ||
* expect(await item.getText()).toBe('Second'); | ||
* | ||
@@ -893,3 +877,3 @@ * @param {string} selector A css selector | ||
*/ | ||
export declare let build$: (element: ElementHelper, by: typeof By) => (selector: string) => ElementFinder; | ||
export declare const build$: (element: ElementHelper, by: typeof By) => (selector: string) => ElementFinder; | ||
/** | ||
@@ -909,8 +893,8 @@ * Shortcut for querying the document directly with css. | ||
* let list = element.all(by.css('.count span')); | ||
* expect(list.count()).toBe(2); | ||
* expect(await list.count()).toBe(2); | ||
* | ||
* list = $$('.count span'); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -921,2 +905,2 @@ * @param {string} selector a css selector | ||
*/ | ||
export declare let build$$: (element: ElementHelper, by: typeof By) => (selector: string) => ElementArrayFinder; | ||
export declare const build$$: (element: ElementHelper, by: typeof By) => (selector: string) => ElementArrayFinder; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -54,13 +62,11 @@ const selenium_webdriver_1 = require("selenium-webdriver"); | ||
* @example | ||
* element.all(by.css('.items li')).then(function(items) { | ||
* expect(items.length).toBe(3); | ||
* expect(items[0].getText()).toBe('First'); | ||
* }); | ||
* const items = await element.all(by.css('.items li')); | ||
* expect(items.length).toBe(3); | ||
* expect(await items[0].getText()).toBe('First'); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').then(function(items) { | ||
* expect(items.length).toBe(3); | ||
* expect(items[0].getText()).toBe('First'); | ||
* }); | ||
* const items = await $$('.items li'); | ||
* expect(items.length).toBe(3); | ||
* expect(await items[0].getText()).toBe('First'); | ||
* | ||
@@ -71,5 +77,5 @@ * @constructor | ||
* that returns a list of the underlying Web Elements. | ||
* @param {webdriver.Locator} locator The most relevant locator. It is only | ||
* @param {Locator} locator The most relevant locator. It is only | ||
* used for error reporting and ElementArrayFinder.locator. | ||
* @param {Array.<webdriver.promise.Promise>} opt_actionResults An array | ||
* @param {Array<Promise>} opt_actionResults An array | ||
* of promises which will be retrieved with then. Resolves to the latest | ||
@@ -131,8 +137,8 @@ * action result, or null if no action has been called. | ||
* let foo = element.all(by.css('.parent')).all(by.css('.foo')); | ||
* expect(foo.getText()).toEqual(['1a', '2a']); | ||
* expect(await foo.getText()).toEqual(['1a', '2a']); | ||
* let baz = element.all(by.css('.parent')).all(by.css('.baz')); | ||
* expect(baz.getText()).toEqual(['1b']); | ||
* expect(await baz.getText()).toEqual(['1b']); | ||
* let nonexistent = element.all(by.css('.parent')) | ||
* .all(by.css('.NONEXISTENT')); | ||
* expect(nonexistent.getText()).toEqual(['']); | ||
* expect(await nonexistent.getText()).toEqual(['']); | ||
* | ||
@@ -142,46 +148,41 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let foo = $$('.parent').$$('.foo'); | ||
* expect(foo.getText()).toEqual(['1a', '2a']); | ||
* expect(await foo.getText()).toEqual(['1a', '2a']); | ||
* let baz = $$('.parent').$$('.baz'); | ||
* expect(baz.getText()).toEqual(['1b']); | ||
* expect(await baz.getText()).toEqual(['1b']); | ||
* let nonexistent = $$('.parent').$$('.NONEXISTENT'); | ||
* expect(nonexistent.getText()).toEqual(['']); | ||
* expect(await nonexistent.getText()).toEqual(['']); | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} locator | ||
* @returns {ElementArrayFinder} | ||
*/ | ||
all(locator) { | ||
let ptor = this.browser_; | ||
let getWebElements = () => { | ||
const ptor = this.browser_; | ||
const getWebElements = () => __awaiter(this, void 0, void 0, function* () { | ||
if (this.getWebElements === null) { | ||
// This is the first time we are looking for an element | ||
return ptor.waitForAngular('Locator: ' + locator) | ||
.then(() => { | ||
if (locators_1.isProtractorLocator(locator)) { | ||
return locator.findElementsOverride(ptor.driver, null, ptor.rootEl); | ||
} | ||
else { | ||
return ptor.driver.findElements(locator); | ||
} | ||
}); | ||
yield ptor.waitForAngular('Locator: ' + locator); | ||
if (locators_1.isProtractorLocator(locator)) { | ||
return locator.findElementsOverride(ptor.driver, null, ptor.rootEl); | ||
} | ||
else { | ||
return ptor.driver.findElements(locator); | ||
} | ||
} | ||
else { | ||
return this.getWebElements().then((parentWebElements) => { | ||
// For each parent web element, find their children and construct | ||
// a list of Promise<List<child_web_element>> | ||
let childrenPromiseList = parentWebElements.map((parentWebElement) => { | ||
return locators_1.isProtractorLocator(locator) ? | ||
locator.findElementsOverride(ptor.driver, parentWebElement, ptor.rootEl) : | ||
parentWebElement.findElements(locator); | ||
}); | ||
// Resolve the list of Promise<List<child_web_elements>> and merge | ||
// into a single list | ||
return selenium_webdriver_1.promise.all(childrenPromiseList) | ||
.then((resolved) => { | ||
return resolved.reduce((childrenList, resolvedE) => { | ||
return childrenList.concat(resolvedE); | ||
}, []); | ||
}); | ||
const parentWebElements = yield this.getWebElements(); | ||
// For each parent web element, find their children and construct | ||
// a list of Promise<List<child_web_element>> | ||
const childrenPromiseList = parentWebElements.map((parentWebElement) => { | ||
return locators_1.isProtractorLocator(locator) ? | ||
locator.findElementsOverride(ptor.driver, parentWebElement, ptor.rootEl) : | ||
parentWebElement.findElements(locator); | ||
}); | ||
// Resolve the list of Promise<List<child_web_elements>> and merge | ||
// into a single list | ||
const resolved = yield Promise.all(childrenPromiseList); | ||
return resolved.reduce((childrenList, resolvedE) => { | ||
return childrenList.concat(resolvedE); | ||
}, []); | ||
} | ||
}; | ||
}); | ||
return new ElementArrayFinder(this.browser_, getWebElements, locator); | ||
@@ -205,21 +206,18 @@ } | ||
* @example | ||
* element.all(by.css('.items li')).filter(function(elem, index) { | ||
* return elem.getText().then(function(text) { | ||
* return text === 'Third'; | ||
* }); | ||
* }).first().click(); | ||
* await element.all(by.css('.items li')) | ||
* .filter(async (elem, index) => await elem.getText() === 'Third') | ||
* .first() | ||
* .click(); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').filter(function(elem, index) { | ||
* return elem.getText().then(function(text) { | ||
* return text === 'Third'; | ||
* }); | ||
* }).first().click(); | ||
* await $$('.items li') | ||
* .filter(async (elem, index) => await elem.getText() === 'Third') | ||
* .first() | ||
* .click(); | ||
* | ||
* @param {function(ElementFinder, number): webdriver.WebElement.Promise} | ||
* filterFn | ||
* @param {function(ElementFinder, number): boolean|Promise<boolean>} filterFn | ||
* Filter function that will test if an element should be returned. | ||
* filterFn can either return a boolean or a promise that resolves to a | ||
* boolean | ||
* boolean. | ||
* @returns {!ElementArrayFinder} A ElementArrayFinder that represents an | ||
@@ -230,20 +228,18 @@ * array | ||
filter(filterFn) { | ||
let getWebElements = () => { | ||
return this.getWebElements().then((parentWebElements) => { | ||
let list = parentWebElements.map((parentWebElement, index) => { | ||
let elementFinder = ElementFinder.fromWebElement_(this.browser_, parentWebElement, this.locator_); | ||
return filterFn(elementFinder, index); | ||
}); | ||
return selenium_webdriver_1.promise.all(list).then((resolvedList) => { | ||
return parentWebElements.filter((parentWebElement, index) => { | ||
return resolvedList[index]; | ||
}); | ||
}); | ||
const getWebElements = () => __awaiter(this, void 0, void 0, function* () { | ||
const parentWebElements = yield this.getWebElements(); | ||
const list = parentWebElements.map((parentWebElement, index) => { | ||
let elementFinder = ElementFinder.fromWebElement_(this.browser_, parentWebElement, this.locator_); | ||
return filterFn(elementFinder, index); | ||
}); | ||
}; | ||
const resolvedList = yield Promise.all(list); | ||
return parentWebElements.filter((_, index) => { | ||
return resolvedList[index]; | ||
}); | ||
}); | ||
return new ElementArrayFinder(this.browser_, getWebElements, this.locator_); | ||
} | ||
/** | ||
* Get an element within the ElementArrayFinder by index. The index starts at 0. | ||
* Negative indices are wrapped (i.e. -i means ith element from last) | ||
* Get an element within the ElementArrayFinder by index. The index starts at | ||
* 0. Negative indices are wrapped (i.e. -i means ith element from last) | ||
* This does not actually retrieve the underlying element. | ||
@@ -261,4 +257,4 @@ * | ||
* let list = element.all(by.css('.items li')); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -268,22 +264,22 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.items li'); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
* @param {number|webdriver.promise.Promise} index Element index. | ||
* @param {number|Promise} indexPromise Element index. | ||
* @returns {ElementFinder} finder representing element at the given index. | ||
*/ | ||
get(index) { | ||
let getWebElements = () => { | ||
return selenium_webdriver_1.promise.all([index, this.getWebElements()]).then(([i, parentWebElements]) => { | ||
if (i < 0) { | ||
i += parentWebElements.length; | ||
} | ||
if (i < 0 || i >= parentWebElements.length) { | ||
throw new selenium_webdriver_1.error.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]]; | ||
}); | ||
}; | ||
get(indexPromise) { | ||
const getWebElements = () => __awaiter(this, void 0, void 0, function* () { | ||
let index = yield indexPromise; | ||
const parentWebElements = yield this.getWebElements(); | ||
if (index < 0) { | ||
index += parentWebElements.length; | ||
} | ||
if (index < 0 || index >= parentWebElements.length) { | ||
throw new selenium_webdriver_1.error.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[index]]; | ||
}); | ||
return new ElementArrayFinder(this.browser_, getWebElements, this.locator_).toElementFinder_(); | ||
@@ -305,3 +301,3 @@ } | ||
* let first = element.all(by.css('.items li')).first(); | ||
* expect(first.getText()).toBe('First'); | ||
* expect(await first.getText()).toBe('First'); | ||
* | ||
@@ -311,3 +307,3 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let first = $$('.items li').first(); | ||
* expect(first.getText()).toBe('First'); | ||
* expect(await first.getText()).toBe('First'); | ||
* | ||
@@ -319,3 +315,2 @@ * @returns {ElementFinder} finder representing the first matching element | ||
} | ||
; | ||
/** | ||
@@ -335,3 +330,3 @@ * Get the last matching element for the ElementArrayFinder. This does not | ||
* let last = element.all(by.css('.items li')).last(); | ||
* expect(last.getText()).toBe('Third'); | ||
* expect(await last.getText()).toBe('Third'); | ||
* | ||
@@ -341,3 +336,3 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let last = $$('.items li').last(); | ||
* expect(last.getText()).toBe('Third'); | ||
* expect(await last.getText()).toBe('Third'); | ||
* | ||
@@ -363,5 +358,5 @@ * @returns {ElementFinder} finder representing the last matching element | ||
* let list = element.all(by.css('.count span')); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -371,5 +366,5 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.count span'); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -407,3 +402,3 @@ * @param {string} selector a css selector | ||
* let list = element.all(by.css('.items li')); | ||
* expect(list.count()).toBe(3); | ||
* expect(await list.count()).toBe(3); | ||
* | ||
@@ -413,16 +408,20 @@ * // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* let list = $$('.items li'); | ||
* expect(list.count()).toBe(3); | ||
* expect(await list.count()).toBe(3); | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise which resolves to the | ||
* @returns {!Promise} A promise which resolves to the | ||
* number of elements matching the locator. | ||
*/ | ||
count() { | ||
return this.getWebElements().then((arr) => { | ||
return arr.length; | ||
}, (err) => { | ||
if (err instanceof selenium_webdriver_1.error.NoSuchElementError) { | ||
return 0; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const arr = yield this.getWebElements(); | ||
return arr.length; | ||
} | ||
else { | ||
throw err; | ||
catch (err) { | ||
if (err instanceof selenium_webdriver_1.error.NoSuchElementError) { | ||
return 0; | ||
} | ||
else { | ||
throw err; | ||
} | ||
} | ||
@@ -437,3 +436,3 @@ }); | ||
* @example | ||
* expect($('.item').isPresent()).toBeTruthy(); | ||
* expect(await $('.item').isPresent()).toBeTruthy(); | ||
* | ||
@@ -443,3 +442,4 @@ * @returns {Promise<boolean>} | ||
isPresent() { | ||
return this.count().then((count) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const count = yield this.count(); | ||
return count > 0; | ||
@@ -461,3 +461,3 @@ }); | ||
* | ||
* @returns {webdriver.Locator} | ||
* @returns {Locator} | ||
*/ | ||
@@ -479,11 +479,11 @@ locator() { | ||
applyAction_(actionFn) { | ||
let callerError = new Error(); | ||
const callerError = new Error(); | ||
let actionResults = this.getWebElements() | ||
.then((arr) => selenium_webdriver_1.promise.all(arr.map(actionFn))) | ||
.then((arr) => Promise.all(arr.map(actionFn))) | ||
.then((value) => { | ||
return { passed: true, value: value }; | ||
return { passed: true, value }; | ||
}, (error) => { | ||
return { passed: false, value: error }; | ||
}); | ||
let getWebElements = () => actionResults.then(() => this.getWebElements()); | ||
const getWebElements = () => actionResults.then(() => this.getWebElements()); | ||
actionResults = actionResults.then((result) => { | ||
@@ -511,7 +511,8 @@ if (result.passed) { | ||
* | ||
* @returns {Array.<ElementFinder>} Return a promise, which resolves to a list | ||
* of ElementFinders specified by the locator. | ||
* @returns {Promise<ElementFinder[]>} Return a promise, which resolves to a | ||
* list of ElementFinders specified by the locator. | ||
*/ | ||
asElementFinders_() { | ||
return this.getWebElements().then((arr) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const arr = yield this.getWebElements(); | ||
return arr.map((webElem) => { | ||
@@ -536,11 +537,9 @@ return ElementFinder.fromWebElement_(this.browser_, webElem, this.locator_); | ||
* @example | ||
* element.all(by.css('.items li')).then(function(arr) { | ||
* expect(arr.length).toEqual(3); | ||
* }); | ||
* const arr = await element.all(by.css('.items li')); | ||
* expect(arr.length).toEqual(3); | ||
* | ||
* // Or using the shortcut $$() notation instead of element.all(by.css()): | ||
* | ||
* $$('.items li').then(function(arr) { | ||
* expect(arr.length).toEqual(3); | ||
* }); | ||
* const arr = $$('.items li'); | ||
* expect(arr.length).toEqual(3); | ||
* | ||
@@ -550,3 +549,3 @@ * @param {function(Array.<ElementFinder>)} fn | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise which will resolve to | ||
* @returns {!Promise} A promise which will resolve to | ||
* an array of ElementFinders represented by the ElementArrayFinder. | ||
@@ -575,7 +574,5 @@ */ | ||
* @example | ||
* element.all(by.css('.items li')).each(function(element, index) { | ||
* await element.all(by.css('.items li')).each(async (element, index) => { | ||
* // Will print 0 First, 1 Second, 2 Third. | ||
* element.getText().then(function (text) { | ||
* console.log(index, text); | ||
* }); | ||
* console.log(index, await element.getText()); | ||
* }); | ||
@@ -585,7 +582,5 @@ * | ||
* | ||
* $$('.items li').each(function(element, index) { | ||
* $$('.items li').each(async (element, index) => { | ||
* // Will print 0 First, 1 Second, 2 Third. | ||
* element.getText().then(function (text) { | ||
* console.log(index, text); | ||
* }); | ||
* console.log(index, await element.getText()); | ||
* }); | ||
@@ -595,3 +590,3 @@ * | ||
* | ||
* @returns {!webdriver.promise.Promise} A promise that will resolve when the | ||
* @returns {!Promise} A promise that will resolve when the | ||
* function has been called on all the ElementFinders. The promise will | ||
@@ -601,4 +596,4 @@ * resolve to null. | ||
each(fn) { | ||
return this.map(fn).then(() => { | ||
return null; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.map(fn); | ||
}); | ||
@@ -620,9 +615,10 @@ } | ||
* @example | ||
* let items = element.all(by.css('.items li')).map(function(elm, index) { | ||
* return { | ||
* index: index, | ||
* text: elm.getText(), | ||
* class: elm.getAttribute('class') | ||
* }; | ||
* }); | ||
* let items = await element.all(by.css('.items li')) | ||
* .map(async (elm, index) => { | ||
* return { | ||
* index: index, | ||
* text: await elm.getText(), | ||
* class: await elm.getAttribute('class') | ||
* }; | ||
* }); | ||
* expect(items).toEqual([ | ||
@@ -636,7 +632,7 @@ * {index: 0, text: 'First', class: 'one'}, | ||
* | ||
* let items = $$('.items li').map(function(elm, index) { | ||
* let items = await $$('.items li').map(async (elm, index) => { | ||
* return { | ||
* index: index, | ||
* text: elm.getText(), | ||
* class: elm.getAttribute('class') | ||
* text: await elm.getText(), | ||
* class: await elm.getAttribute('class') | ||
* }; | ||
@@ -652,16 +648,16 @@ * }); | ||
* will be applied to each element. | ||
* @returns {!webdriver.promise.Promise} A promise that resolves to an array | ||
* @returns {!Promise} A promise that resolves to an array | ||
* of values returned by the map function. | ||
*/ | ||
map(mapFn) { | ||
return this.asElementFinders_().then((arr) => { | ||
let list = arr.map((elementFinder, index) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const arr = yield this.asElementFinders_(); | ||
const list = arr.map((elementFinder, index) => __awaiter(this, void 0, void 0, function* () { | ||
let mapResult = mapFn(elementFinder, index); | ||
// All nested arrays and objects will also be fully resolved. | ||
return selenium_webdriver_1.promise.fullyResolved(mapResult); | ||
}); | ||
return selenium_webdriver_1.promise.all(list); | ||
return yield mapResult; | ||
})); | ||
return Promise.all(list); | ||
}); | ||
} | ||
; | ||
/** | ||
@@ -684,7 +680,4 @@ * Apply a reduce function against an accumulator and every element found | ||
* @example | ||
* let value = element.all(by.css('.items li')).reduce(function(acc, elem) { | ||
* return elem.getText().then(function(text) { | ||
* return acc + text + ' '; | ||
* }); | ||
* }, ''); | ||
* let value = await element.all(by.css('.items li')) | ||
* .reduce(async (acc, elem) => acc + (await elem.getText()) + ' ', ''); | ||
* | ||
@@ -695,7 +688,4 @@ * expect(value).toEqual('First Second Third '); | ||
* | ||
* let value = $$('.items li').reduce(function(acc, elem) { | ||
* return elem.getText().then(function(text) { | ||
* return acc + text + ' '; | ||
* }); | ||
* }, ''); | ||
* let value = await $$('.items li') | ||
* .reduce(async (acc, elem) => acc + (await elem.getText()) + ' ', ''); | ||
* | ||
@@ -708,13 +698,12 @@ * expect(value).toEqual('First Second Third '); | ||
* @param {*} initialValue Initial value of the accumulator. | ||
* @returns {!webdriver.promise.Promise} A promise that resolves to the final | ||
* @returns {!Promise} A promise that resolves to the final | ||
* value of the accumulator. | ||
*/ | ||
reduce(reduceFn, initialValue) { | ||
let valuePromise = selenium_webdriver_1.promise.when(initialValue); | ||
return this.asElementFinders_().then((arr) => { | ||
return arr.reduce((valuePromise, elementFinder, index) => { | ||
return valuePromise.then((value) => { | ||
return reduceFn(value, elementFinder, index, arr); | ||
}); | ||
}, valuePromise); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const valuePromise = yield initialValue; | ||
const arr = yield this.asElementFinders_(); | ||
return arr.reduce((valuePromise, elementFinder, index) => __awaiter(this, void 0, void 0, function* () { | ||
return reduceFn(yield valuePromise, elementFinder, index, arr); | ||
}), valuePromise); | ||
}); | ||
@@ -746,3 +735,3 @@ } | ||
evaluate(expression) { | ||
let evaluationFn = (webElem) => { | ||
const evaluationFn = (webElem) => { | ||
return webElem.getDriver().executeScript(clientSideScripts.evaluate, webElem, expression); | ||
@@ -768,3 +757,3 @@ }; | ||
allowAnimations(value) { | ||
let allowAnimationsTestFn = (webElem) => { | ||
const allowAnimationsTestFn = (webElem) => { | ||
return webElem.getDriver().executeScript(clientSideScripts.allowAnimations, webElem, value); | ||
@@ -802,13 +791,13 @@ }; | ||
* // Find element with {{scopelet}} syntax. | ||
* element(by.binding('person.name')).getText().then(function(name) { | ||
* expect(name).toBe('Foo'); | ||
* }); | ||
* const name = await element(by.binding('person.name')).getText(); | ||
* expect(name).toBe('Foo'); | ||
* | ||
* // Find element with ng-bind="scopelet" syntax. | ||
* expect(element(by.binding('person.email')).getText()).toBe('foo@bar.com'); | ||
* const email = await element(by.binding('person.email')).getText(); | ||
* expect(email).toBe('foo@bar.com'); | ||
* | ||
* // Find by model. | ||
* let input = element(by.model('person.name')); | ||
* input.sendKeys('123'); | ||
* expect(input.getAttribute('value')).toBe('Foo123'); | ||
* await input.sendKeys('123'); | ||
* expect(await input.getAttribute('value')).toBe('Foo123'); | ||
* | ||
@@ -835,11 +824,10 @@ * @constructor | ||
// Access the underlying actionResult of ElementFinder. | ||
this.then = | ||
(fn, errorFn) => { | ||
return this.elementArrayFinder_.then((actionResults) => { | ||
if (!fn) { | ||
return actionResults[0]; | ||
} | ||
return fn(actionResults[0]); | ||
}, errorFn); | ||
}; | ||
this.then = (fn, errorFn) => { | ||
return this.elementArrayFinder_.then((actionResults) => { | ||
if (!fn) { | ||
return actionResults[0]; | ||
} | ||
return fn(actionResults[0]); | ||
}, errorFn); | ||
}; | ||
} | ||
@@ -849,16 +837,15 @@ // This filter verifies that there is only 1 element returned by the | ||
// throw an error if there are no elements. | ||
let getWebElements = () => { | ||
return elementArrayFinder.getWebElements().then((webElements) => { | ||
if (webElements.length === 0) { | ||
throw new selenium_webdriver_1.error.NoSuchElementError('No element found using locator: ' + elementArrayFinder.locator().toString()); | ||
const getWebElements = () => __awaiter(this, void 0, void 0, function* () { | ||
const webElements = yield elementArrayFinder.getWebElements(); | ||
if (webElements.length === 0) { | ||
throw new selenium_webdriver_1.error.NoSuchElementError('No element found using locator: ' + elementArrayFinder.locator().toString()); | ||
} | ||
else { | ||
if (webElements.length > 1) { | ||
logger.warn('more than one element found for locator ' + elementArrayFinder.locator().toString() + | ||
' - the first result will be used'); | ||
} | ||
else { | ||
if (webElements.length > 1) { | ||
logger.warn('more than one element found for locator ' + | ||
elementArrayFinder.locator().toString() + ' - the first result will be used'); | ||
} | ||
return [webElements[0]]; | ||
} | ||
}); | ||
}; | ||
return [webElements[0]]; | ||
} | ||
}); | ||
// Store a copy of the underlying elementArrayFinder, but with the more | ||
@@ -876,4 +863,4 @@ // restrictive getWebElements (which checks that there is only 1 element). | ||
static fromWebElement_(browser, webElem, locator) { | ||
let getWebElements = () => { | ||
return selenium_webdriver_1.promise.when([webElem]); | ||
const getWebElements = () => { | ||
return Promise.resolve([webElem]); | ||
}; | ||
@@ -895,3 +882,3 @@ return new ElementArrayFinder(browser, getWebElements, locator).toElementFinder_(); | ||
* | ||
* @returns {webdriver.Locator} | ||
* @returns {Locator} | ||
*/ | ||
@@ -918,6 +905,6 @@ locator() { | ||
* | ||
* @returns {webdriver.WebElementPromise} | ||
* @returns {webdriver.WebElement} | ||
*/ | ||
getWebElement() { | ||
let id = this.elementArrayFinder_.getWebElements().then((parentWebElements) => { | ||
const id = this.elementArrayFinder_.getWebElements().then((parentWebElements) => { | ||
return parentWebElements[0]; | ||
@@ -948,3 +935,3 @@ }); | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} subLocator | ||
* @returns {ElementArrayFinder} | ||
@@ -971,3 +958,3 @@ */ | ||
* element(by.css('.child')); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -978,3 +965,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -985,3 +972,3 @@ * // Or using the shortcut $() notation instead of element(by.css()): | ||
* let child = $('.parent').$('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -991,5 +978,5 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
* @param {webdriver.Locator} subLocator | ||
* @param {Locator} subLocator | ||
* @returns {ElementFinder} | ||
@@ -1043,3 +1030,3 @@ */ | ||
* $('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -1050,3 +1037,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -1057,3 +1044,3 @@ * // Or using the shortcut $() notation instead of element(by.css()): | ||
* let child = $('.parent').$('.child'); | ||
* expect(child.getText()).toBe('Child text\n555-123-4567'); | ||
* expect(await child.getText()).toBe('Child text\n555-123-4567'); | ||
* | ||
@@ -1063,3 +1050,3 @@ * // Chain 3 element calls. | ||
* element(by.binding('person.phone')); | ||
* expect(triple.getText()).toBe('555-123-4567'); | ||
* expect(await triple.getText()).toBe('555-123-4567'); | ||
* | ||
@@ -1080,19 +1067,24 @@ * @param {string} selector A css selector | ||
* // Element exists. | ||
* expect(element(by.binding('person.name')).isPresent()).toBe(true); | ||
* expect(await element(by.binding('person.name')).isPresent()).toBe(true); | ||
* | ||
* // Element not present. | ||
* expect(element(by.binding('notPresent')).isPresent()).toBe(false); | ||
* expect(await element(by.binding('notPresent')).isPresent()).toBe(false); | ||
* | ||
* @returns {webdriver.promise.Promise<boolean>} which resolves to whether | ||
* @returns {Promise<boolean>} which resolves to whether | ||
* the element is present on the page. | ||
*/ | ||
isPresent() { | ||
return this.parentElementArrayFinder.getWebElements().then((arr) => { | ||
if (arr.length === 0) { | ||
return false; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const arr = yield this.parentElementArrayFinder.getWebElements(); | ||
if (arr.length === 0) { | ||
return false; | ||
} | ||
// is present, whether it is enabled or not | ||
return yield arr[0].isEnabled(); | ||
} | ||
return arr[0].isEnabled().then(() => { | ||
return true; // is present, whether it is enabled or not | ||
}, util_1.falseIfMissing); | ||
}, util_1.falseIfMissing); | ||
catch (err) { | ||
return util_1.falseIfMissing(err); | ||
} | ||
}); | ||
} | ||
@@ -1112,4 +1104,4 @@ /** | ||
* | ||
* @param {webdriver.Locator} subLocator Locator for element to look for. | ||
* @returns {webdriver.promise.Promise<boolean>} which resolves to whether | ||
* @param {Locator} subLocator Locator for element to look for. | ||
* @returns {Promise<boolean>} which resolves to whether | ||
* the subelement is present on the page. | ||
@@ -1154,10 +1146,16 @@ */ | ||
* | ||
* @param {!ElementFinder|!webdriver.WebElement} The element to compare to. | ||
* @param {!ElementFinder|!webdriver.WebElement} element The element to compare to. | ||
* | ||
* @returns {!webdriver.promise.Promise.<boolean>} A promise that will be | ||
* @returns {!Promise<boolean>} A promise that will be | ||
* resolved to whether the two WebElements are equal. | ||
*/ | ||
equals(element) { | ||
return selenium_webdriver_1.WebElement.equals(this.getWebElement(), element.getWebElement ? element.getWebElement() : | ||
element); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const a = yield this.getWebElement(); | ||
const b = element.getWebElement ? yield element.getWebElement() : | ||
element; | ||
// TODO(selenium4): Use `return WebElement.equals(a, b);` when | ||
// https://github.com/SeleniumHQ/selenium/pull/6749 is fixed. | ||
return a.getDriver().executeScript('return arguments[0] === arguments[1]', a, b); | ||
}); | ||
} | ||
@@ -1179,3 +1177,3 @@ } | ||
* let item = $('.count .two'); | ||
* expect(item.getText()).toBe('Second'); | ||
* expect(await item.getText()).toBe('Second'); | ||
* | ||
@@ -1205,8 +1203,8 @@ * @param {string} selector A css selector | ||
* let list = element.all(by.css('.count span')); | ||
* expect(list.count()).toBe(2); | ||
* expect(await list.count()).toBe(2); | ||
* | ||
* list = $$('.count span'); | ||
* expect(list.count()).toBe(2); | ||
* expect(list.get(0).getText()).toBe('First'); | ||
* expect(list.get(1).getText()).toBe('Second'); | ||
* expect(await list.count()).toBe(2); | ||
* expect(await list.get(0).getText()).toBe('First'); | ||
* expect(await list.get(1).getText()).toBe('Second'); | ||
* | ||
@@ -1213,0 +1211,0 @@ * @param {string} selector a css selector |
@@ -16,17 +16,15 @@ import { ProtractorBrowser } from './browser'; | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var button = $('#xyz'); | ||
* var isClickable = EC.elementToBeClickable(button); | ||
* const EC = protractor.ExpectedConditions; | ||
* const button = $('#xyz'); | ||
* const isClickable = EC.elementToBeClickable(button); | ||
* | ||
* browser.get(URL); | ||
* browser.wait(isClickable, 5000); //wait for an element to become clickable | ||
* button.click(); | ||
* await browser.get(URL); | ||
* await browser.wait(isClickable, 5000); //wait for an element to become clickable | ||
* await button.click(); | ||
* | ||
* // You can define your own expected condition, which is a function that | ||
* // takes no parameter and evaluates to a promise of a boolean. | ||
* var urlChanged = function() { | ||
* return browser.getCurrentUrl().then(function(url) { | ||
* return url === 'http://www.angularjs.org'; | ||
* }); | ||
* }; | ||
* const urlChanged = async () => { | ||
* return await browser.getCurrentUrl() === 'http://www.angularjs.org'; | ||
* } | ||
* | ||
@@ -36,7 +34,7 @@ * // You can customize the conditions with EC.and, EC.or, and EC.not. | ||
* // text 'bar', and button becomes clickable. | ||
* var condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), | ||
* const condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), | ||
* 'bar'), isClickable); | ||
* browser.get(URL); | ||
* browser.wait(condition, 5000); //wait for condition to be true. | ||
* button.click(); | ||
* await browser.get(URL); | ||
* await browser.wait(condition, 5000); //wait for condition to be true. | ||
* await button.click(); | ||
* | ||
@@ -53,6 +51,6 @@ * @alias ExpectedConditions | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleIsNotFoo = EC.not(EC.titleIs('Foo')); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleIsNotFoo = EC.not(EC.titleIs('Foo')); | ||
* // Waits for title to become something besides 'foo'. | ||
* browser.wait(titleIsNotFoo, 5000); | ||
* await browser.wait(titleIsNotFoo, 5000); | ||
* | ||
@@ -64,3 +62,3 @@ * @alias ExpectedConditions.not | ||
*/ | ||
not(expectedCondition: Function): Function; | ||
not(expectedCondition: Function): (() => Promise<boolean>); | ||
/** | ||
@@ -77,3 +75,3 @@ * Helper function that is equivalent to the logical_and if defaultRet==true, | ||
*/ | ||
logicalChain_(defaultRet: boolean, fns: Array<Function>): Function; | ||
logicalChain_(defaultRet: boolean, fns: Array<Function>): (() => Promise<boolean>); | ||
/** | ||
@@ -84,10 +82,10 @@ * Chain a number of expected conditions using logical_and, short circuiting | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleContainsFoo = EC.titleContains('Foo'); | ||
* var titleIsNotFooBar = EC.not(EC.titleIs('FooBar')); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleContainsFoo = EC.titleContains('Foo'); | ||
* const titleIsNotFooBar = EC.not(EC.titleIs('FooBar')); | ||
* // Waits for title to contain 'Foo', but is not 'FooBar' | ||
* browser.wait(EC.and(titleContainsFoo, titleIsNotFooBar), 5000); | ||
* await browser.wait(EC.and(titleContainsFoo, titleIsNotFooBar), 5000); | ||
* | ||
* @alias ExpectedConditions.and | ||
* @param {Array.<Function>} fns An array of expected conditions to 'and' | ||
* @param {Array.<Function>} args An array of expected conditions to 'and' | ||
* together. | ||
@@ -98,3 +96,3 @@ * | ||
*/ | ||
and(...args: Function[]): Function; | ||
and(...args: Function[]): (() => Promise<boolean>); | ||
/** | ||
@@ -106,9 +104,9 @@ * Chain a number of expected conditions using logical_or, short circuiting | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleContainsFoo = EC.titleContains('Foo'); | ||
* var titleContainsBar = EC.titleContains('Bar'); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleContainsFoo = EC.titleContains('Foo'); | ||
* const titleContainsBar = EC.titleContains('Bar'); | ||
* // Waits for title to contain either 'Foo' or 'Bar' | ||
* browser.wait(EC.or(titleContainsFoo, titleContainsBar), 5000); | ||
* await browser.wait(EC.or(titleContainsFoo, titleContainsBar), 5000); | ||
* | ||
* @param {Array.<Function>} fns An array of expected conditions to 'or' | ||
* @param {Array.<Function>} args An array of expected conditions to 'or' | ||
* together. | ||
@@ -119,3 +117,3 @@ * | ||
*/ | ||
or(...args: Function[]): Function; | ||
or(...args: Function[]): (() => Promise<boolean>); | ||
/** | ||
@@ -125,5 +123,5 @@ * Expect an alert to be present. | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for an alert pops up. | ||
* browser.wait(EC.alertIsPresent(), 5000); | ||
* await browser.wait(EC.alertIsPresent(), 5000); | ||
* | ||
@@ -134,3 +132,3 @@ * @alias ExpectedConditions.alertIsPresent | ||
*/ | ||
alertIsPresent(): Function; | ||
alertIsPresent(): (() => Promise<boolean>); | ||
/** | ||
@@ -141,5 +139,5 @@ * An Expectation for checking an element is visible and enabled such that you | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be clickable. | ||
* browser.wait(EC.elementToBeClickable($('#abc')), 5000); | ||
* await browser.wait(EC.elementToBeClickable($('#abc')), 5000); | ||
* | ||
@@ -152,3 +150,3 @@ * @alias ExpectedConditions.elementToBeClickable | ||
*/ | ||
elementToBeClickable(elementFinder: ElementFinder): Function; | ||
elementToBeClickable(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
/** | ||
@@ -159,5 +157,5 @@ * An expectation for checking if the given text is present in the | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to contain the text 'foo'. | ||
* browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000); | ||
* await browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000); | ||
* | ||
@@ -171,3 +169,3 @@ * @alias ExpectedConditions.textToBePresentInElement | ||
*/ | ||
textToBePresentInElement(elementFinder: ElementFinder, text: string): Function; | ||
textToBePresentInElement(elementFinder: ElementFinder, text: string): (() => Promise<boolean>); | ||
/** | ||
@@ -178,5 +176,5 @@ * An expectation for checking if the given text is present in the element’s | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'myInput' to contain the input 'foo'. | ||
* browser.wait(EC.textToBePresentInElementValue($('#myInput'), 'foo'), 5000); | ||
* await browser.wait(EC.textToBePresentInElementValue($('#myInput'), 'foo'), 5000); | ||
* | ||
@@ -190,3 +188,3 @@ * @alias ExpectedConditions.textToBePresentInElementValue | ||
*/ | ||
textToBePresentInElementValue(elementFinder: ElementFinder, text: string): Function; | ||
textToBePresentInElementValue(elementFinder: ElementFinder, text: string): (() => Promise<boolean>); | ||
/** | ||
@@ -197,5 +195,5 @@ * An expectation for checking that the title contains a case-sensitive | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the title to contain 'foo'. | ||
* browser.wait(EC.titleContains('foo'), 5000); | ||
* await browser.wait(EC.titleContains('foo'), 5000); | ||
* | ||
@@ -208,3 +206,3 @@ * @alias ExpectedConditions.titleContains | ||
*/ | ||
titleContains(title: string): Function; | ||
titleContains(title: string): (() => Promise<boolean>); | ||
/** | ||
@@ -214,5 +212,5 @@ * An expectation for checking the title of a page. | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the title to be 'foo'. | ||
* browser.wait(EC.titleIs('foo'), 5000); | ||
* await browser.wait(EC.titleIs('foo'), 5000); | ||
* | ||
@@ -225,3 +223,3 @@ * @alias ExpectedConditions.titleIs | ||
*/ | ||
titleIs(title: string): Function; | ||
titleIs(title: string): (() => Promise<boolean>); | ||
/** | ||
@@ -232,5 +230,5 @@ * An expectation for checking that the URL contains a case-sensitive | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the URL to contain 'foo'. | ||
* browser.wait(EC.urlContains('foo'), 5000); | ||
* await browser.wait(EC.urlContains('foo'), 5000); | ||
* | ||
@@ -243,3 +241,3 @@ * @alias ExpectedConditions.urlContains | ||
*/ | ||
urlContains(url: string): Function; | ||
urlContains(url: string): (() => Promise<boolean>); | ||
/** | ||
@@ -249,5 +247,5 @@ * An expectation for checking the URL of a page. | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the URL to be 'foo'. | ||
* browser.wait(EC.urlIs('foo'), 5000); | ||
* await browser.wait(EC.urlIs('foo'), 5000); | ||
* | ||
@@ -260,3 +258,3 @@ * @alias ExpectedConditions.urlIs | ||
*/ | ||
urlIs(url: string): Function; | ||
urlIs(url: string): (() => Promise<boolean>); | ||
/** | ||
@@ -268,5 +266,5 @@ * An expectation for checking that an element is present on the DOM | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be present on the dom. | ||
* browser.wait(EC.presenceOf($('#abc')), 5000); | ||
* await browser.wait(EC.presenceOf($('#abc')), 5000); | ||
* | ||
@@ -279,3 +277,3 @@ * @alias ExpectedConditions.presenceOf | ||
*/ | ||
presenceOf(elementFinder: ElementFinder): Function; | ||
presenceOf(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
/** | ||
@@ -286,5 +284,5 @@ * An expectation for checking that an element is not attached to the DOM | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be no longer present on the dom. | ||
* browser.wait(EC.stalenessOf($('#abc')), 5000); | ||
* await browser.wait(EC.stalenessOf($('#abc')), 5000); | ||
* | ||
@@ -297,3 +295,3 @@ * @alias ExpectedConditions.stalenessOf | ||
*/ | ||
stalenessOf(elementFinder: ElementFinder): Function; | ||
stalenessOf(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
/** | ||
@@ -307,5 +305,5 @@ * An expectation for checking that an element is present on the DOM of a | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be visible on the dom. | ||
* browser.wait(EC.visibilityOf($('#abc')), 5000); | ||
* await browser.wait(EC.visibilityOf($('#abc')), 5000); | ||
* | ||
@@ -318,3 +316,3 @@ * @alias ExpectedConditions.visibilityOf | ||
*/ | ||
visibilityOf(elementFinder: ElementFinder): Function; | ||
visibilityOf(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
/** | ||
@@ -325,5 +323,5 @@ * An expectation for checking that an element is either invisible or not | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be no longer visible on the dom. | ||
* browser.wait(EC.invisibilityOf($('#abc')), 5000); | ||
* await browser.wait(EC.invisibilityOf($('#abc')), 5000); | ||
* | ||
@@ -336,3 +334,3 @@ * @alias ExpectedConditions.invisibilityOf | ||
*/ | ||
invisibilityOf(elementFinder: ElementFinder): Function; | ||
invisibilityOf(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
/** | ||
@@ -342,5 +340,5 @@ * An expectation for checking the selection is selected. | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'myCheckbox' to be selected. | ||
* browser.wait(EC.elementToBeSelected($('#myCheckbox')), 5000); | ||
* await browser.wait(EC.elementToBeSelected($('#myCheckbox')), 5000); | ||
* | ||
@@ -353,3 +351,3 @@ * @alias ExpectedConditions.elementToBeSelected | ||
*/ | ||
elementToBeSelected(elementFinder: ElementFinder): Function; | ||
elementToBeSelected(elementFinder: ElementFinder): (() => Promise<boolean>); | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -18,17 +26,15 @@ const selenium_webdriver_1 = require("selenium-webdriver"); | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var button = $('#xyz'); | ||
* var isClickable = EC.elementToBeClickable(button); | ||
* const EC = protractor.ExpectedConditions; | ||
* const button = $('#xyz'); | ||
* const isClickable = EC.elementToBeClickable(button); | ||
* | ||
* browser.get(URL); | ||
* browser.wait(isClickable, 5000); //wait for an element to become clickable | ||
* button.click(); | ||
* await browser.get(URL); | ||
* await browser.wait(isClickable, 5000); //wait for an element to become clickable | ||
* await button.click(); | ||
* | ||
* // You can define your own expected condition, which is a function that | ||
* // takes no parameter and evaluates to a promise of a boolean. | ||
* var urlChanged = function() { | ||
* return browser.getCurrentUrl().then(function(url) { | ||
* return url === 'http://www.angularjs.org'; | ||
* }); | ||
* }; | ||
* const urlChanged = async () => { | ||
* return await browser.getCurrentUrl() === 'http://www.angularjs.org'; | ||
* } | ||
* | ||
@@ -38,7 +44,7 @@ * // You can customize the conditions with EC.and, EC.or, and EC.not. | ||
* // text 'bar', and button becomes clickable. | ||
* var condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), | ||
* const condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), | ||
* 'bar'), isClickable); | ||
* browser.get(URL); | ||
* browser.wait(condition, 5000); //wait for condition to be true. | ||
* button.click(); | ||
* await browser.get(URL); | ||
* await browser.wait(condition, 5000); //wait for condition to be true. | ||
* await button.click(); | ||
* | ||
@@ -52,3 +58,2 @@ * @alias ExpectedConditions | ||
} | ||
; | ||
/** | ||
@@ -58,6 +63,6 @@ * Negates the result of a promise. | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleIsNotFoo = EC.not(EC.titleIs('Foo')); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleIsNotFoo = EC.not(EC.titleIs('Foo')); | ||
* // Waits for title to become something besides 'foo'. | ||
* browser.wait(titleIsNotFoo, 5000); | ||
* await browser.wait(titleIsNotFoo, 5000); | ||
* | ||
@@ -70,7 +75,6 @@ * @alias ExpectedConditions.not | ||
not(expectedCondition) { | ||
return () => { | ||
return expectedCondition().then((bool) => { | ||
return !bool; | ||
}); | ||
}; | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
const bool = yield expectedCondition(); | ||
return !bool; | ||
}); | ||
} | ||
@@ -90,16 +94,15 @@ /** | ||
let self = this; | ||
return () => { | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
if (fns.length === 0) { | ||
return defaultRet; | ||
} | ||
let fn = fns[0]; | ||
return fn().then((bool) => { | ||
if (bool === defaultRet) { | ||
return self.logicalChain_(defaultRet, fns.slice(1))(); | ||
} | ||
else { | ||
return !defaultRet; | ||
} | ||
}); | ||
}; | ||
const fn = fns[0]; | ||
const bool = yield fn(); | ||
if (bool === defaultRet) { | ||
return self.logicalChain_(defaultRet, fns.slice(1))(); | ||
} | ||
else { | ||
return !defaultRet; | ||
} | ||
}); | ||
} | ||
@@ -111,10 +114,10 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleContainsFoo = EC.titleContains('Foo'); | ||
* var titleIsNotFooBar = EC.not(EC.titleIs('FooBar')); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleContainsFoo = EC.titleContains('Foo'); | ||
* const titleIsNotFooBar = EC.not(EC.titleIs('FooBar')); | ||
* // Waits for title to contain 'Foo', but is not 'FooBar' | ||
* browser.wait(EC.and(titleContainsFoo, titleIsNotFooBar), 5000); | ||
* await browser.wait(EC.and(titleContainsFoo, titleIsNotFooBar), 5000); | ||
* | ||
* @alias ExpectedConditions.and | ||
* @param {Array.<Function>} fns An array of expected conditions to 'and' | ||
* @param {Array.<Function>} args An array of expected conditions to 'and' | ||
* together. | ||
@@ -134,9 +137,9 @@ * | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* var titleContainsFoo = EC.titleContains('Foo'); | ||
* var titleContainsBar = EC.titleContains('Bar'); | ||
* const EC = protractor.ExpectedConditions; | ||
* const titleContainsFoo = EC.titleContains('Foo'); | ||
* const titleContainsBar = EC.titleContains('Bar'); | ||
* // Waits for title to contain either 'Foo' or 'Bar' | ||
* browser.wait(EC.or(titleContainsFoo, titleContainsBar), 5000); | ||
* await browser.wait(EC.or(titleContainsFoo, titleContainsBar), 5000); | ||
* | ||
* @param {Array.<Function>} fns An array of expected conditions to 'or' | ||
* @param {Array.<Function>} args An array of expected conditions to 'or' | ||
* together. | ||
@@ -154,5 +157,5 @@ * | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for an alert pops up. | ||
* browser.wait(EC.alertIsPresent(), 5000); | ||
* await browser.wait(EC.alertIsPresent(), 5000); | ||
* | ||
@@ -164,14 +167,16 @@ * @alias ExpectedConditions.alertIsPresent | ||
alertIsPresent() { | ||
return () => { | ||
return this.browser.driver.switchTo().alert().then(() => { | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
yield this.browser.driver.switchTo().alert(); | ||
return true; | ||
}, (err) => { | ||
if (err instanceof selenium_webdriver_1.error.NoSuchAlertError) { | ||
} | ||
catch (e) { | ||
if (e instanceof selenium_webdriver_1.error.NoSuchAlertError) { | ||
return false; | ||
} | ||
else { | ||
throw err; | ||
throw e; | ||
} | ||
}); | ||
}; | ||
} | ||
}); | ||
} | ||
@@ -183,5 +188,5 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be clickable. | ||
* browser.wait(EC.elementToBeClickable($('#abc')), 5000); | ||
* await browser.wait(EC.elementToBeClickable($('#abc')), 5000); | ||
* | ||
@@ -204,5 +209,5 @@ * @alias ExpectedConditions.elementToBeClickable | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to contain the text 'foo'. | ||
* browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000); | ||
* await browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000); | ||
* | ||
@@ -217,9 +222,13 @@ * @alias ExpectedConditions.textToBePresentInElement | ||
textToBePresentInElement(elementFinder, text) { | ||
let hasText = () => { | ||
return elementFinder.getText().then((actualText) => { | ||
let hasText = () => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const actualText = yield elementFinder.getText(); | ||
// MSEdge does not properly remove newlines, which causes false | ||
// negatives | ||
return actualText.replace(/\r?\n|\r/g, '').indexOf(text) > -1; | ||
}, util_1.falseIfMissing); | ||
}; | ||
} | ||
catch (e) { | ||
return util_1.falseIfMissing(e); | ||
} | ||
}); | ||
return this.and(this.presenceOf(elementFinder), hasText); | ||
@@ -232,5 +241,5 @@ } | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'myInput' to contain the input 'foo'. | ||
* browser.wait(EC.textToBePresentInElementValue($('#myInput'), 'foo'), 5000); | ||
* await browser.wait(EC.textToBePresentInElementValue($('#myInput'), 'foo'), 5000); | ||
* | ||
@@ -245,7 +254,11 @@ * @alias ExpectedConditions.textToBePresentInElementValue | ||
textToBePresentInElementValue(elementFinder, text) { | ||
let hasText = () => { | ||
return elementFinder.getAttribute('value').then((actualText) => { | ||
let hasText = () => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const actualText = yield elementFinder.getAttribute('value'); | ||
return actualText.indexOf(text) > -1; | ||
}, util_1.falseIfMissing); | ||
}; | ||
} | ||
catch (e) { | ||
return util_1.falseIfMissing(e); | ||
} | ||
}); | ||
return this.and(this.presenceOf(elementFinder), hasText); | ||
@@ -258,5 +271,5 @@ } | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the title to contain 'foo'. | ||
* browser.wait(EC.titleContains('foo'), 5000); | ||
* await browser.wait(EC.titleContains('foo'), 5000); | ||
* | ||
@@ -270,7 +283,6 @@ * @alias ExpectedConditions.titleContains | ||
titleContains(title) { | ||
return () => { | ||
return this.browser.driver.getTitle().then((actualTitle) => { | ||
return actualTitle.indexOf(title) > -1; | ||
}); | ||
}; | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
const actualTitle = yield this.browser.driver.getTitle(); | ||
return actualTitle.indexOf(title) > -1; | ||
}); | ||
} | ||
@@ -281,5 +293,5 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the title to be 'foo'. | ||
* browser.wait(EC.titleIs('foo'), 5000); | ||
* await browser.wait(EC.titleIs('foo'), 5000); | ||
* | ||
@@ -293,7 +305,6 @@ * @alias ExpectedConditions.titleIs | ||
titleIs(title) { | ||
return () => { | ||
return this.browser.driver.getTitle().then((actualTitle) => { | ||
return actualTitle === title; | ||
}); | ||
}; | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
const actualTitle = yield this.browser.driver.getTitle(); | ||
return actualTitle === title; | ||
}); | ||
} | ||
@@ -305,5 +316,5 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the URL to contain 'foo'. | ||
* browser.wait(EC.urlContains('foo'), 5000); | ||
* await browser.wait(EC.urlContains('foo'), 5000); | ||
* | ||
@@ -317,7 +328,6 @@ * @alias ExpectedConditions.urlContains | ||
urlContains(url) { | ||
return () => { | ||
return this.browser.driver.getCurrentUrl().then((actualUrl) => { | ||
return actualUrl.indexOf(url) > -1; | ||
}); | ||
}; | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
const actualUrl = yield this.browser.driver.getCurrentUrl(); | ||
return actualUrl.indexOf(url) > -1; | ||
}); | ||
} | ||
@@ -328,5 +338,5 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the URL to be 'foo'. | ||
* browser.wait(EC.urlIs('foo'), 5000); | ||
* await browser.wait(EC.urlIs('foo'), 5000); | ||
* | ||
@@ -340,7 +350,6 @@ * @alias ExpectedConditions.urlIs | ||
urlIs(url) { | ||
return () => { | ||
return this.browser.driver.getCurrentUrl().then((actualUrl) => { | ||
return actualUrl === url; | ||
}); | ||
}; | ||
return () => __awaiter(this, void 0, void 0, function* () { | ||
const actualUrl = yield this.browser.driver.getCurrentUrl(); | ||
return actualUrl === url; | ||
}); | ||
} | ||
@@ -353,5 +362,5 @@ /** | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be present on the dom. | ||
* browser.wait(EC.presenceOf($('#abc')), 5000); | ||
* await browser.wait(EC.presenceOf($('#abc')), 5000); | ||
* | ||
@@ -367,3 +376,2 @@ * @alias ExpectedConditions.presenceOf | ||
} | ||
; | ||
/** | ||
@@ -374,5 +382,5 @@ * An expectation for checking that an element is not attached to the DOM | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be no longer present on the dom. | ||
* browser.wait(EC.stalenessOf($('#abc')), 5000); | ||
* await browser.wait(EC.stalenessOf($('#abc')), 5000); | ||
* | ||
@@ -396,5 +404,5 @@ * @alias ExpectedConditions.stalenessOf | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be visible on the dom. | ||
* browser.wait(EC.visibilityOf($('#abc')), 5000); | ||
* await browser.wait(EC.visibilityOf($('#abc')), 5000); | ||
* | ||
@@ -417,5 +425,5 @@ * @alias ExpectedConditions.visibilityOf | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'abc' to be no longer visible on the dom. | ||
* browser.wait(EC.invisibilityOf($('#abc')), 5000); | ||
* await browser.wait(EC.invisibilityOf($('#abc')), 5000); | ||
* | ||
@@ -435,5 +443,5 @@ * @alias ExpectedConditions.invisibilityOf | ||
* @example | ||
* var EC = protractor.ExpectedConditions; | ||
* const EC = protractor.ExpectedConditions; | ||
* // Waits for the element with id 'myCheckbox' to be selected. | ||
* browser.wait(EC.elementToBeSelected($('#myCheckbox')), 5000); | ||
* await browser.wait(EC.elementToBeSelected($('#myCheckbox')), 5000); | ||
* | ||
@@ -440,0 +448,0 @@ * @alias ExpectedConditions.elementToBeSelected |
@@ -1,7 +0,6 @@ | ||
var util = require('util'), | ||
q = require('q'), | ||
Logger = require('../logger').Logger; | ||
var logger = new Logger('debugger'); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = require("util"); | ||
const logger_1 = require("../logger"); | ||
const logger = new logger_1.Logger('debugger'); | ||
/** | ||
@@ -13,11 +12,10 @@ * A debug framework which does not actually run any tests, just spits | ||
* @param {Array} specs Array of Directory Path Strings. | ||
* @return {q.Promise} Promise resolved with the test results | ||
* @return {Promise} Promise resolved with the test results | ||
*/ | ||
exports.run = function(runner, specs) { | ||
return q.promise(function(resolve) { | ||
logger.info('Resolved spec files: ' + util.inspect(specs)); | ||
resolve({ | ||
failedCount: 0 | ||
exports.run = (runner, specs) => { | ||
return new Promise(resolve => { | ||
logger.info(`Resolved spec files: ${util.inspect(specs)}`); | ||
resolve({ failedCount: 0 }); | ||
}); | ||
}); | ||
}; | ||
//# sourceMappingURL=debugprint.js.map |
@@ -1,5 +0,2 @@ | ||
var q = require('q'); | ||
var webdriver = require('selenium-webdriver'); | ||
var RunnerReporter = function(emitter) { | ||
let RunnerReporter = function(emitter) { | ||
this.emitter = emitter; | ||
@@ -21,3 +18,3 @@ this.testResult = [], | ||
RunnerReporter.prototype.specDone = function(result) { | ||
var specInfo = { | ||
const specInfo = { | ||
name: result.description, | ||
@@ -33,3 +30,3 @@ category: result.fullName.slice(0, -result.description.length).trim() | ||
var entry = { | ||
const entry = { | ||
description: result.fullName, | ||
@@ -46,3 +43,3 @@ assertions: [], | ||
result.failedExpectations.forEach(function(item) { | ||
result.failedExpectations.forEach(item => { | ||
entry.assertions.push({ | ||
@@ -62,13 +59,10 @@ passed: item.passed, | ||
* @param {Array} specs Array of Directory Path Strings. | ||
* @return {q.Promise} Promise resolved with the test results | ||
* @return {Promise} Promise resolved with the test results | ||
*/ | ||
exports.run = function(runner, specs) { | ||
var JasmineRunner = require('jasmine'); | ||
var jrunner = new JasmineRunner(); | ||
/* global jasmine */ | ||
exports.run = async function(runner, specs) { | ||
const JasmineRunner = require('jasmine'); | ||
const jrunner = new JasmineRunner(); | ||
require('jasminewd2').init(webdriver.promise.controlFlow(), webdriver); | ||
const jasmineNodeOpts = runner.getConfig().jasmineNodeOpts; | ||
var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts; | ||
// On timeout, the flow should be reset. This will prevent webdriver tasks | ||
@@ -79,3 +73,3 @@ // from overflowing into the next test and causing it to fail or timeout | ||
// get to complete first. | ||
var reporter = new RunnerReporter(runner); | ||
const reporter = new RunnerReporter(runner); | ||
jasmine.getEnv().addReporter(reporter); | ||
@@ -108,34 +102,30 @@ | ||
return runner.runTestPreparer().then(function() { | ||
return q.promise(function(resolve, reject) { | ||
if (jasmineNodeOpts && jasmineNodeOpts.defaultTimeoutInterval) { | ||
jasmine.DEFAULT_TIMEOUT_INTERVAL = jasmineNodeOpts.defaultTimeoutInterval; | ||
} | ||
await runner.runTestPreparer(); | ||
return new Promise((resolve, reject) => { | ||
if (jasmineNodeOpts && jasmineNodeOpts.defaultTimeoutInterval) { | ||
jasmine.DEFAULT_TIMEOUT_INTERVAL = jasmineNodeOpts.defaultTimeoutInterval; | ||
} | ||
var originalOnComplete = runner.getConfig().onComplete; | ||
const originalOnComplete = runner.getConfig().onComplete; | ||
jrunner.onComplete(function(passed) { | ||
try { | ||
var completed = q(); | ||
if (originalOnComplete) { | ||
completed = q(originalOnComplete(passed)); | ||
} | ||
completed.then(function() { | ||
resolve({ | ||
failedCount: reporter.failedCount, | ||
specResults: reporter.testResult | ||
}); | ||
}); | ||
} catch (err) { | ||
reject(err); | ||
jrunner.onComplete(async(passed) => { | ||
try { | ||
if (originalOnComplete) { | ||
await originalOnComplete(passed); | ||
} | ||
}); | ||
resolve({ | ||
failedCount: reporter.failedCount, | ||
specResults: reporter.testResult | ||
}); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}); | ||
jrunner.configureDefaultReporter(jasmineNodeOpts); | ||
jrunner.projectBaseDir = ''; | ||
jrunner.specDir = ''; | ||
jrunner.addSpecFiles(specs); | ||
jrunner.execute(); | ||
}); | ||
jrunner.configureDefaultReporter(jasmineNodeOpts); | ||
jrunner.projectBaseDir = ''; | ||
jrunner.specDir = ''; | ||
jrunner.addSpecFiles(specs); | ||
jrunner.execute(); | ||
}); | ||
}; |
@@ -1,3 +0,1 @@ | ||
var q = require('q'); | ||
/** | ||
@@ -10,5 +8,5 @@ * Execute the Runner's test cases through Mocha. | ||
*/ | ||
exports.run = function(runner, specs) { | ||
var Mocha = require('mocha'), | ||
mocha = new Mocha(runner.getConfig().mochaOpts); | ||
exports.run = (runner, specs) => { | ||
const Mocha = require('mocha'); | ||
const mocha = new Mocha(runner.getConfig().mochaOpts); | ||
@@ -18,125 +16,61 @@ // Add hooks for afterEach | ||
var deferred = q.defer(); | ||
return new Promise(async (resolve, reject) => { | ||
mocha.loadFiles(); | ||
// Mocha doesn't set up the ui until the pre-require event, so | ||
// wait until then to load mocha-webdriver adapters as well. | ||
mocha.suite.on('pre-require', function() { | ||
try { | ||
// We need to re-wrap all of the global functions, which `selenium-webdriver/testing` only | ||
// does when it is required. So first we must remove it from the cache. | ||
delete require.cache[require.resolve('selenium-webdriver/testing')]; | ||
var seleniumAdapter = require('selenium-webdriver/testing'); | ||
// Save unwrapped version | ||
var unwrappedFns = {}; | ||
['after', 'afterEach', 'before', 'beforeEach', 'it', 'xit', 'iit'].forEach(function(fnName) { | ||
unwrappedFns[fnName] = global[fnName] || Mocha[fnName]; | ||
await runner.runTestPreparer(); | ||
specs.forEach((file) => { | ||
mocha.addFile(file); | ||
}); | ||
let testResult = []; | ||
var wrapFn = function(seleniumWrappedFn, opt_fnName) { | ||
// This does not work on functions that can be nested (e.g. `describe`) | ||
return function() { | ||
// Set globals to unwrapped version to avoid circular reference | ||
var wrappedFns = {}; | ||
for (var fnName in unwrappedFns) { | ||
wrappedFns[fnName] = global[fnName]; | ||
global[fnName] = unwrappedFns[fnName]; | ||
const mochaRunner = mocha.run(async (failures) => { | ||
try { | ||
if (runner.getConfig().onComplete) { | ||
await runner.getConfig().onComplete(); | ||
} | ||
var args = arguments; | ||
// Allow before/after hooks to use names | ||
if (opt_fnName && (arguments.length > 1) && (seleniumWrappedFn.length < 2)) { | ||
global[opt_fnName] = global[opt_fnName].bind(this, args[0]); | ||
args = Array.prototype.slice.call(arguments, 1); | ||
} | ||
try { | ||
seleniumWrappedFn.apply(this, args); | ||
} finally { | ||
// Restore wrapped version | ||
for (fnName in wrappedFns) { | ||
global[fnName] = wrappedFns[fnName]; | ||
} | ||
} | ||
}; | ||
}; | ||
// Wrap functions | ||
global.after = wrapFn(seleniumAdapter.after, 'after'); | ||
global.afterEach = wrapFn(seleniumAdapter.afterEach, 'afterEach'); | ||
global.before = wrapFn(seleniumAdapter.before, 'before'); | ||
global.beforeEach = wrapFn(seleniumAdapter.beforeEach, 'beforeEach'); | ||
global.it = wrapFn(seleniumAdapter.it); | ||
global.iit = wrapFn(seleniumAdapter.it.only); | ||
global.xit = wrapFn(seleniumAdapter.xit); | ||
global.it.only = wrapFn(seleniumAdapter.it.only); | ||
global.it.skip = wrapFn(seleniumAdapter.it.skip); | ||
} catch (err) { | ||
deferred.reject(err); | ||
} | ||
}); | ||
mocha.loadFiles(); | ||
runner.runTestPreparer().then(function() { | ||
specs.forEach(function(file) { | ||
mocha.addFile(file); | ||
}); | ||
var testResult = []; | ||
var mochaRunner = mocha.run(function(failures) { | ||
try { | ||
var completed = q(); | ||
if (runner.getConfig().onComplete) { | ||
completed = q(runner.getConfig().onComplete()); | ||
} | ||
completed.then(function() { | ||
deferred.resolve({ | ||
resolve({ | ||
failedCount: failures, | ||
specResults: testResult | ||
}); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}); | ||
mochaRunner.on('pass', (test) => { | ||
const testInfo = { | ||
name: test.title, | ||
category: test.fullTitle().slice(0, -test.title.length).trim() | ||
}; | ||
runner.emit('testPass', testInfo); | ||
testResult.push({ | ||
description: test.title, | ||
assertions: [{ | ||
passed: true | ||
}], | ||
duration: test.duration | ||
}); | ||
} catch (err) { | ||
deferred.reject(err); | ||
} | ||
}); | ||
mochaRunner.on('pass', function(test) { | ||
var testInfo = { | ||
name: test.title, | ||
category: test.fullTitle().slice(0, -test.title.length).trim() | ||
}; | ||
runner.emit('testPass', testInfo); | ||
testResult.push({ | ||
description: test.title, | ||
assertions: [{ | ||
passed: true | ||
}], | ||
duration: test.duration | ||
}); | ||
}); | ||
mochaRunner.on('fail', function(test) { | ||
var testInfo = { | ||
name: test.title, | ||
category: test.fullTitle().slice(0, -test.title.length).trim() | ||
}; | ||
runner.emit('testFail', testInfo); | ||
testResult.push({ | ||
description: test.title, | ||
assertions: [{ | ||
passed: false, | ||
errorMsg: test.err.message, | ||
stackTrace: test.err.stack | ||
}], | ||
duration: test.duration | ||
mochaRunner.on('fail', (test) => { | ||
const testInfo = { | ||
name: test.title, | ||
category: test.fullTitle().slice(0, -test.title.length).trim() | ||
}; | ||
runner.emit('testFail', testInfo); | ||
testResult.push({ | ||
description: test.title, | ||
assertions: [{ | ||
passed: false, | ||
errorMsg: test.err.message, | ||
stackTrace: test.err.stack | ||
}], | ||
duration: test.duration | ||
}); | ||
}); | ||
}); | ||
}).catch (function(reason) { | ||
deferred.reject(reason); | ||
}); | ||
return deferred.promise; | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}); | ||
}; |
@@ -7,3 +7,3 @@ import { ElementHelper, ProtractorBrowser } from './browser'; | ||
import { Ptor } from './ptor'; | ||
export { ActionSequence, Browser, Builder, Button, Capabilities, Capability, error, EventEmitter, FileDetector, Key, logging, promise, Session, until, WebDriver, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
export { /*Actions,*/ Browser, Builder, Button, Capabilities, Capability, error, EventEmitter, FileDetector, Key, logging, promise, Session, until, WebDriver, WebElement, WebElementPromise } from 'selenium-webdriver'; | ||
export { ElementHelper, ProtractorBrowser } from './browser'; | ||
@@ -10,0 +10,0 @@ export { Config } from './config'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
// Re-export selenium-webdriver types. | ||
// TODO(selenium4): Actions class typings missing. ActionSequence is deprecated. | ||
var selenium_webdriver_1 = require("selenium-webdriver"); | ||
exports.ActionSequence = selenium_webdriver_1.ActionSequence; | ||
exports.Browser = selenium_webdriver_1.Browser; | ||
@@ -7,0 +7,0 @@ exports.Builder = selenium_webdriver_1.Builder; |
import { Config } from './config'; | ||
export declare let init: (configFile: string, additionalConfig: Config) => void; | ||
export declare let init: (configFile: string, additionalConfig: Config) => Promise<void>; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -8,10 +16,8 @@ /** | ||
const fs = require("fs"); | ||
const q = require("q"); | ||
const configParser_1 = require("./configParser"); | ||
const exitCodes_1 = require("./exitCodes"); | ||
const logger_1 = require("./logger"); | ||
const runner_1 = require("./runner"); | ||
const taskRunner_1 = require("./taskRunner"); | ||
const taskScheduler_1 = require("./taskScheduler"); | ||
const helper = require("./util"); | ||
const util_1 = require("./util"); | ||
let logger = new logger_1.Logger('launcher'); | ||
@@ -92,85 +98,53 @@ let RUNNERS_FAILED_EXIT_CODE = 100; | ||
let initFn = function (configFile, additionalConfig) { | ||
let configParser = new configParser_1.ConfigParser(); | ||
if (configFile) { | ||
configParser.addFileConfig(configFile); | ||
} | ||
if (additionalConfig) { | ||
configParser.addConfig(additionalConfig); | ||
} | ||
let config = configParser.getConfig(); | ||
logger_1.Logger.set(config); | ||
logger.debug('Running with --troubleshoot'); | ||
logger.debug('Protractor version: ' + require('../package.json').version); | ||
logger.debug('Your base url for tests is ' + config.baseUrl); | ||
// Run beforeLaunch | ||
helper.runFilenameOrFn_(config.configDir, config.beforeLaunch) | ||
.then(() => { | ||
return q | ||
.Promise((resolve, reject) => { | ||
// 1) If getMultiCapabilities is set, resolve that as | ||
// `multiCapabilities`. | ||
if (config.getMultiCapabilities && | ||
typeof config.getMultiCapabilities === 'function') { | ||
if (config.multiCapabilities.length || config.capabilities) { | ||
logger.warn('getMultiCapabilities() will override both capabilities ' + | ||
'and multiCapabilities'); | ||
} | ||
// If getMultiCapabilities is defined and a function, use this. | ||
q(config.getMultiCapabilities()) | ||
.then((multiCapabilities) => { | ||
config.multiCapabilities = multiCapabilities; | ||
config.capabilities = null; | ||
}) | ||
.then(() => { | ||
resolve(); | ||
}) | ||
.catch(err => { | ||
reject(err); | ||
}); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let configParser = new configParser_1.ConfigParser(); | ||
if (configFile) { | ||
configParser.addFileConfig(configFile); | ||
} | ||
if (additionalConfig) { | ||
configParser.addConfig(additionalConfig); | ||
} | ||
let config = configParser.getConfig(); | ||
logger_1.Logger.set(config); | ||
logger.debug('Running with --troubleshoot'); | ||
logger.debug('Protractor version: ' + require('../package.json').version); | ||
logger.debug('Your base url for tests is ' + config.baseUrl); | ||
// Run beforeLaunch | ||
yield util_1.runFilenameOrFn_(config.configDir, config.beforeLaunch); | ||
// 1) If getMultiCapabilities is set, resolve that as | ||
// `multiCapabilities`. | ||
if (config.getMultiCapabilities && typeof config.getMultiCapabilities === 'function') { | ||
if (config.multiCapabilities.length || config.capabilities) { | ||
logger.warn('getMultiCapabilities() will override both capabilities ' + | ||
'and multiCapabilities'); | ||
} | ||
else { | ||
resolve(); | ||
// If getMultiCapabilities is defined and a function, use this. | ||
const waitMultiConfig = yield config.getMultiCapabilities(); | ||
config.multiCapabilities = waitMultiConfig; | ||
config.capabilities = null; | ||
} | ||
// 2) Set `multicapabilities` using `capabilities`, | ||
// `multicapabilities`, or default | ||
if (config.capabilities) { | ||
if (config.multiCapabilities.length) { | ||
logger.warn('You have specified both capabilities and ' + | ||
'multiCapabilities. This will result in capabilities being ' + | ||
'ignored'); | ||
} | ||
}) | ||
.then(() => { | ||
// 2) Set `multicapabilities` using `capabilities`, | ||
// `multicapabilities`, | ||
// or default | ||
if (config.capabilities) { | ||
if (config.multiCapabilities.length) { | ||
logger.warn('You have specified both capabilities and ' + | ||
'multiCapabilities. This will result in capabilities being ' + | ||
'ignored'); | ||
} | ||
else { | ||
// Use capabilities if multiCapabilities is empty. | ||
config.multiCapabilities = [config.capabilities]; | ||
} | ||
} | ||
else if (!config.multiCapabilities.length) { | ||
// Default to chrome if no capabilities given | ||
config.multiCapabilities = [{ browserName: 'chrome' }]; | ||
} | ||
}); | ||
}) | ||
.then(() => { | ||
// 3) If we're in `elementExplorer` mode, run only that. | ||
if (config.elementExplorer || config.framework === 'explorer') { | ||
if (config.multiCapabilities.length != 1) { | ||
throw new Error('Must specify only 1 browser while using elementExplorer'); | ||
} | ||
else { | ||
config.capabilities = config.multiCapabilities[0]; | ||
// Use capabilities if multiCapabilities is empty. | ||
config.multiCapabilities = [config.capabilities]; | ||
} | ||
config.framework = 'explorer'; | ||
let runner = new runner_1.Runner(config); | ||
return runner.run().then((exitCode) => { | ||
process.exit(exitCode); | ||
}, (err) => { | ||
logger.error(err); | ||
process.exit(1); | ||
}); | ||
} | ||
}) | ||
.then(() => { | ||
else if (!config.multiCapabilities.length) { | ||
// Default to chrome if no capabilities given | ||
config.multiCapabilities = [{ browserName: 'chrome' }]; | ||
} | ||
// 3) If we're in `elementExplorer` mode, throw an error and exit. | ||
if (config.elementExplorer || config.framework === 'explorer') { | ||
const err = new Error('Deprecated: Element explorer depends on the ' + | ||
'WebDriver control flow, and thus is no longer supported.'); | ||
logger.error(err); | ||
process.exit(1); | ||
} | ||
// 4) Run tests. | ||
@@ -187,14 +161,21 @@ let scheduler = new taskScheduler_1.TaskScheduler(config); | ||
} | ||
let errorCode = exitCodes_1.ErrorHandler.parseError(e); | ||
if (errorCode) { | ||
logger.error(e.message); | ||
logger.error(e.stack); | ||
if (e instanceof exitCodes_1.ProtractorError) { | ||
let protractorError = e; | ||
exitCodes_1.ProtractorError.log(logger, errorCode, protractorError.message, protractorError.stack); | ||
process.exit(errorCode); | ||
process.exit(protractorError.code); | ||
} | ||
else { | ||
logger.error(e.message); | ||
logger.error(e.stack); | ||
process.exit(exitCodes_1.ProtractorError.CODE); | ||
process.exit(1); | ||
} | ||
}); | ||
process.on('unhandledRejection', (reason, p) => { | ||
if (reason.stack.match('angular testability are undefined') || | ||
reason.stack.match('angular is not defined')) { | ||
logger.warn('Unhandled promise rejection error: This is usually occurs ' + | ||
'when a browser.get call is made and a previous async call was ' + | ||
'not awaited'); | ||
} | ||
logger.warn(p); | ||
}); | ||
process.on('exit', (code) => { | ||
@@ -205,4 +186,3 @@ if (code) { | ||
else if (scheduler.numTasksOutstanding() > 0) { | ||
logger.error('BUG: launcher exited with ' + scheduler.numTasksOutstanding() + | ||
' tasks remaining'); | ||
logger.error('BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining'); | ||
process.exit(RUNNERS_FAILED_EXIT_CODE); | ||
@@ -212,5 +192,5 @@ } | ||
// Run afterlaunch and exit | ||
let cleanUpAndExit = (exitCode) => { | ||
return helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]) | ||
.then((returned) => { | ||
const cleanUpAndExit = (exitCode) => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const returned = yield util_1.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]); | ||
if (typeof returned === 'number') { | ||
@@ -222,10 +202,11 @@ process.exit(returned); | ||
} | ||
}, (err) => { | ||
} | ||
catch (err) { | ||
logger.error('Error:', err); | ||
process.exit(1); | ||
}); | ||
}; | ||
let totalTasks = scheduler.numTasksOutstanding(); | ||
} | ||
}); | ||
const totalTasks = scheduler.numTasksOutstanding(); | ||
let forkProcess = false; | ||
if (totalTasks > 1) { | ||
if (totalTasks > 1) { // Start new processes only if there are >1 tasks. | ||
forkProcess = true; | ||
@@ -236,57 +217,57 @@ if (config.debug) { | ||
} | ||
let deferred = q.defer(); // Resolved when all tasks are completed | ||
let createNextTaskRunner = () => { | ||
let task = scheduler.nextTask(); | ||
if (task) { | ||
let taskRunner = new taskRunner_1.TaskRunner(configFile, additionalConfig, task, forkProcess); | ||
taskRunner.run() | ||
.then((result) => { | ||
if (result.exitCode && !result.failedCount) { | ||
logger.error('Runner process exited unexpectedly with error code: ' + result.exitCode); | ||
const createNextTaskRunner = () => __awaiter(this, void 0, void 0, function* () { | ||
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { | ||
const task = scheduler.nextTask(); | ||
if (task) { | ||
const taskRunner = new taskRunner_1.TaskRunner(configFile, additionalConfig, task, forkProcess); | ||
try { | ||
const result = yield taskRunner.run(); | ||
if (result.exitCode && !result.failedCount) { | ||
logger.error('Runner process exited unexpectedly with error code: ' + result.exitCode); | ||
} | ||
taskResults_.add(result); | ||
task.done(); | ||
yield createNextTaskRunner(); | ||
// If all tasks are finished | ||
if (scheduler.numTasksOutstanding() === 0) { | ||
resolve(); | ||
} | ||
logger.info(scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); | ||
} | ||
taskResults_.add(result); | ||
task.done(); | ||
createNextTaskRunner(); | ||
// If all tasks are finished | ||
if (scheduler.numTasksOutstanding() === 0) { | ||
deferred.resolve(); | ||
catch (err) { | ||
const errorCode = exitCodes_1.ErrorHandler.parseError(err); | ||
logger.error('Error:', err.stack || err.message || err); | ||
yield cleanUpAndExit(errorCode ? errorCode : RUNNERS_FAILED_EXIT_CODE); | ||
} | ||
logger.info(scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); | ||
}) | ||
.catch((err) => { | ||
logger.error('Error:', err.stack || err.message || err); | ||
cleanUpAndExit(RUNNERS_FAILED_EXIT_CODE); | ||
}); | ||
} | ||
}; | ||
// Start `scheduler.maxConcurrentTasks()` workers for handling tasks in | ||
// the beginning. As a worker finishes a task, it will pick up the next | ||
// task | ||
// from the scheduler's queue until all tasks are gone. | ||
for (let i = 0; i < scheduler.maxConcurrentTasks(); ++i) { | ||
createNextTaskRunner(); | ||
} | ||
else { | ||
resolve(); | ||
} | ||
})); | ||
}); | ||
const maxConcurrentTasks = scheduler.maxConcurrentTasks(); | ||
for (let i = 0; i < maxConcurrentTasks; ++i) { | ||
yield createNextTaskRunner(); | ||
} | ||
logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver'); | ||
// By now all runners have completed. | ||
deferred.promise | ||
.then(function () { | ||
// Save results if desired | ||
if (config.resultJsonOutputFile) { | ||
taskResults_.saveResults(config.resultJsonOutputFile); | ||
} | ||
taskResults_.reportSummary(); | ||
let exitCode = 0; | ||
if (taskResults_.totalProcessFailures() > 0) { | ||
exitCode = RUNNERS_FAILED_EXIT_CODE; | ||
} | ||
else if (taskResults_.totalSpecFailures() > 0) { | ||
exitCode = 1; | ||
} | ||
return cleanUpAndExit(exitCode); | ||
}) | ||
.done(); | ||
}) | ||
.done(); | ||
// Save results if desired | ||
if (config.resultJsonOutputFile) { | ||
taskResults_.saveResults(config.resultJsonOutputFile); | ||
} | ||
taskResults_.reportSummary(); | ||
let exitCode = 0; | ||
if (taskResults_.totalProcessFailures() > 0) { | ||
exitCode = RUNNERS_FAILED_EXIT_CODE; | ||
} | ||
else if (taskResults_.totalSpecFailures() > 0) { | ||
exitCode = 1; | ||
} | ||
yield cleanUpAndExit(exitCode); | ||
// Start `const maxConcurrentTasks` workers for handling tasks in | ||
// the beginning. As a worker finishes a task, it will pick up the next | ||
// task from the scheduler's queue until all tasks are gone. | ||
}); | ||
}; | ||
exports.init = initFn; | ||
//# sourceMappingURL=launcher.js.map |
@@ -1,2 +0,2 @@ | ||
import { By, ByHash, promise as wdpromise, WebDriver, WebElement } from 'selenium-webdriver'; | ||
import { By, ByHash, WebDriver, WebElement } from 'selenium-webdriver'; | ||
export declare class WebdriverBy { | ||
@@ -15,3 +15,3 @@ className: (className: string) => By; | ||
export interface ProtractorLocator { | ||
findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string) => wdpromise.Promise<WebElement[]>; | ||
findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string) => Promise<WebElement[]>; | ||
row?: (index: number) => Locator; | ||
@@ -56,3 +56,3 @@ column?: (index: string) => Locator; | ||
* // Use the custom locator. | ||
* element(by.buttonTextSimple('Go!')).click(); | ||
* await element(by.buttonTextSimple('Go!')).click(); | ||
* | ||
@@ -83,10 +83,10 @@ * @alias by.addLocator(locatorName, functionOrScript) | ||
* var span1 = element(by.binding('person.name')); | ||
* expect(span1.getText()).toBe('Foo'); | ||
* expect(await span1.getText()).toBe('Foo'); | ||
* | ||
* var span2 = element(by.binding('person.email')); | ||
* expect(span2.getText()).toBe('foo@bar.com'); | ||
* expect(await span2.getText()).toBe('foo@bar.com'); | ||
* | ||
* // You can also use a substring for a partial match | ||
* var span1alt = element(by.binding('name')); | ||
* expect(span1alt.getText()).toBe('Foo'); | ||
* expect(await span1alt.getText()).toBe('Foo'); | ||
* | ||
@@ -109,8 +109,8 @@ * // This works for sites using Angular 1.2 but NOT 1.3 | ||
* @example | ||
* expect(element(by.exactBinding('person.name')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person-email')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person')).isPresent()).toBe(false); | ||
* expect(element(by.exactBinding('person_phone')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('phone')).isPresent()).toBe(false); | ||
* expect(await element(by.exactBinding('person.name')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person-email')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person')).isPresent()).toBe(false); | ||
* expect(await element(by.exactBinding('person_phone')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('phone')).isPresent()).toBe(false); | ||
* | ||
@@ -130,4 +130,4 @@ * @param {string} bindingDescriptor | ||
* var input = element(by.model('person.name')); | ||
* input.sendKeys('123'); | ||
* expect(input.getAttribute('value')).toBe('Foo123'); | ||
* await input.sendKeys('123'); | ||
* expect(await input.getAttribute('value')).toBe('Foo123'); | ||
* | ||
@@ -164,3 +164,3 @@ * @param {string} model ng-model expression. | ||
partialButtonText(searchText: string): ProtractorLocator; | ||
private byRepeaterInner(exact, repeatDescriptor); | ||
private byRepeaterInner; | ||
/** | ||
@@ -185,11 +185,10 @@ * Find elements inside an ng-repeat. | ||
* // Returns the DIV for the second cat. | ||
* var secondCat = element(by.repeater('cat in pets').row(1)); | ||
* let secondCat = element(by.repeater('cat in pets').row(1)); | ||
* | ||
* // Returns the SPAN for the first cat's name. | ||
* var firstCatName = element(by.repeater('cat in pets'). | ||
* let firstCatName = element(by.repeater('cat in pets'). | ||
* row(0).column('cat.name')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements from a column | ||
* var ages = element.all( | ||
* by.repeater('cat in pets').column('cat.age')); | ||
* let ages = element.all(by.repeater('cat in pets').column('cat.age')); | ||
* | ||
@@ -199,14 +198,14 @@ * // Returns a promise that resolves to an array of WebElements containing | ||
* // resolves to an array of 2 elements. | ||
* var rows = element.all(by.repeater('cat in pets')); | ||
* let rows = element.all(by.repeater('cat in pets')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements containing | ||
* // all the elements with a binding to the book's name. | ||
* var divs = element.all(by.repeater('book in library').column('book.name')); | ||
* let divs = element.all(by.repeater('book in library').column('book.name')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements containing | ||
* // the DIVs for the second book. | ||
* var bookInfo = element.all(by.repeater('book in library').row(1)); | ||
* let bookInfo = element.all(by.repeater('book in library').row(1)); | ||
* | ||
* // Returns the H4 for the first book's name. | ||
* var firstBookName = element(by.repeater('book in library'). | ||
* let firstBookName = element(by.repeater('book in library'). | ||
* row(0).column('book.name')); | ||
@@ -217,3 +216,3 @@ * | ||
* // resolves to an array of 4 elements. | ||
* var divs = element.all(by.repeater('book in library')); | ||
* let divs = element.all(by.repeater('book in library')); | ||
* | ||
@@ -232,8 +231,5 @@ * @param {string} repeatDescriptor | ||
* @example | ||
* expect(element(by.exactRepeater('person in | ||
* peopleWithRedHair')).isPresent()) | ||
* .toBe(true); | ||
* expect(element(by.exactRepeater('person in | ||
* people')).isPresent()).toBe(false); | ||
* expect(element(by.exactRepeater('car in cars')).isPresent()).toBe(true); | ||
* expect(await element(by.exactRepeater('person in peopleWithRedHair')).isPresent()).toBe(true); | ||
* expect(await element(by.exactRepeater('person in people')).isPresent()).toBe(false); | ||
* expect(await element(by.exactRepeater('car in cars')).isPresent()).toBe(true); | ||
* | ||
@@ -258,3 +254,3 @@ * @param {string} repeatDescriptor | ||
* @param {string} cssSelector css selector | ||
* @param {string|RegExp} searchString text search | ||
* @param {string|RegExp} searchText text search | ||
* @returns {ProtractorLocator} location strategy | ||
@@ -275,5 +271,5 @@ */ | ||
* var allOptions = element.all(by.options('c for c in colors')); | ||
* expect(allOptions.count()).toEqual(2); | ||
* expect(await allOptions.count()).toEqual(2); | ||
* var firstOption = allOptions.first(); | ||
* expect(firstOption.getText()).toEqual('red'); | ||
* expect(await firstOption.getText()).toEqual('red'); | ||
* | ||
@@ -300,3 +296,3 @@ * @param {string} optionsDescriptor ng-options expression. | ||
* var spans = element.all(by.deepCss('span')); | ||
* expect(spans.count()).toEqual(3); | ||
* expect(await spans.count()).toEqual(3); | ||
* | ||
@@ -303,0 +299,0 @@ * @param {string} selector a css selector within the Shadow DOM. |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -58,3 +66,3 @@ const selenium_webdriver_1 = require("selenium-webdriver"); | ||
* // Use the custom locator. | ||
* element(by.buttonTextSimple('Go!')).click(); | ||
* await element(by.buttonTextSimple('Go!')).click(); | ||
* | ||
@@ -71,5 +79,5 @@ * @alias by.addLocator(locatorName, functionOrScript) | ||
this[name] = (...args) => { | ||
let locatorArguments = args; | ||
const locatorArguments = args; | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
let findElementArguments = [script]; | ||
@@ -81,4 +89,4 @@ for (let i = 0; i < locatorArguments.length; i++) { | ||
findElementArguments.push(rootSelector); | ||
return driver.findElements(selenium_webdriver_1.By.js.apply(selenium_webdriver_1.By, findElementArguments)); | ||
}, | ||
return yield driver.findElements(selenium_webdriver_1.By.js.apply(selenium_webdriver_1.By, findElementArguments)); | ||
}), | ||
toString: () => { | ||
@@ -90,3 +98,2 @@ return 'by.' + name + '("' + Array.prototype.join.call(locatorArguments, '", "') + '")'; | ||
} | ||
; | ||
/** | ||
@@ -107,10 +114,10 @@ * Find an element by text binding. Does a partial match, so any elements | ||
* var span1 = element(by.binding('person.name')); | ||
* expect(span1.getText()).toBe('Foo'); | ||
* expect(await span1.getText()).toBe('Foo'); | ||
* | ||
* var span2 = element(by.binding('person.email')); | ||
* expect(span2.getText()).toBe('foo@bar.com'); | ||
* expect(await span2.getText()).toBe('foo@bar.com'); | ||
* | ||
* // You can also use a substring for a partial match | ||
* var span1alt = element(by.binding('name')); | ||
* expect(span1alt.getText()).toBe('Foo'); | ||
* expect(await span1alt.getText()).toBe('Foo'); | ||
* | ||
@@ -125,5 +132,5 @@ * // This works for sites using Angular 1.2 but NOT 1.3 | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findBindings, bindingDescriptor, false, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findBindings, bindingDescriptor, false, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -134,3 +141,2 @@ return 'by.binding("' + bindingDescriptor + '")'; | ||
} | ||
; | ||
/** | ||
@@ -145,8 +151,8 @@ * Find an element by exact binding. | ||
* @example | ||
* expect(element(by.exactBinding('person.name')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person-email')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person')).isPresent()).toBe(false); | ||
* expect(element(by.exactBinding('person_phone')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true); | ||
* expect(element(by.exactBinding('phone')).isPresent()).toBe(false); | ||
* expect(await element(by.exactBinding('person.name')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person-email')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person')).isPresent()).toBe(false); | ||
* expect(await element(by.exactBinding('person_phone')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true); | ||
* expect(await element(by.exactBinding('phone')).isPresent()).toBe(false); | ||
* | ||
@@ -158,5 +164,5 @@ * @param {string} bindingDescriptor | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findBindings, bindingDescriptor, true, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findBindings, bindingDescriptor, true, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -167,3 +173,2 @@ return 'by.exactBinding("' + bindingDescriptor + '")'; | ||
} | ||
; | ||
/** | ||
@@ -178,4 +183,4 @@ * Find an element by ng-model expression. | ||
* var input = element(by.model('person.name')); | ||
* input.sendKeys('123'); | ||
* expect(input.getAttribute('value')).toBe('Foo123'); | ||
* await input.sendKeys('123'); | ||
* expect(await input.getAttribute('value')).toBe('Foo123'); | ||
* | ||
@@ -187,5 +192,5 @@ * @param {string} model ng-model expression. | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByModel, model, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByModel, model, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -196,3 +201,2 @@ return 'by.model("' + model + '")'; | ||
} | ||
; | ||
/** | ||
@@ -212,5 +216,5 @@ * Find a button by text. | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByButtonText, searchText, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -221,3 +225,2 @@ return 'by.buttonText("' + searchText + '")'; | ||
} | ||
; | ||
/** | ||
@@ -237,5 +240,5 @@ * Find a button by partial text. | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByPartialButtonText, searchText, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -246,3 +249,2 @@ return 'by.partialButtonText("' + searchText + '")'; | ||
} | ||
; | ||
// Generate either by.repeater or by.exactRepeater | ||
@@ -252,5 +254,5 @@ byRepeaterInner(exact, repeatDescriptor) { | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findAllRepeaterRows, repeatDescriptor, exact, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -261,5 +263,5 @@ return name + '("' + repeatDescriptor + '")'; | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findRepeaterRows, repeatDescriptor, exact, index, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findRepeaterRows, repeatDescriptor, exact, index, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -270,5 +272,5 @@ return name + '(' + repeatDescriptor + '").row("' + index + '")"'; | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findRepeaterElement, repeatDescriptor, exact, index, binding, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -284,5 +286,5 @@ return name + '("' + repeatDescriptor + '").row("' + index + '").column("' + | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findRepeaterColumn, repeatDescriptor, exact, binding, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -293,5 +295,5 @@ return name + '("' + repeatDescriptor + '").column("' + binding + '")'; | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findRepeaterElement, repeatDescriptor, exact, index, binding, using, rootSelector)); | ||
}, | ||
}), | ||
toString: () => { | ||
@@ -326,11 +328,10 @@ return name + '("' + repeatDescriptor + '").column("' + binding + '").row("' + | ||
* // Returns the DIV for the second cat. | ||
* var secondCat = element(by.repeater('cat in pets').row(1)); | ||
* let secondCat = element(by.repeater('cat in pets').row(1)); | ||
* | ||
* // Returns the SPAN for the first cat's name. | ||
* var firstCatName = element(by.repeater('cat in pets'). | ||
* let firstCatName = element(by.repeater('cat in pets'). | ||
* row(0).column('cat.name')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements from a column | ||
* var ages = element.all( | ||
* by.repeater('cat in pets').column('cat.age')); | ||
* let ages = element.all(by.repeater('cat in pets').column('cat.age')); | ||
* | ||
@@ -340,14 +341,14 @@ * // Returns a promise that resolves to an array of WebElements containing | ||
* // resolves to an array of 2 elements. | ||
* var rows = element.all(by.repeater('cat in pets')); | ||
* let rows = element.all(by.repeater('cat in pets')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements containing | ||
* // all the elements with a binding to the book's name. | ||
* var divs = element.all(by.repeater('book in library').column('book.name')); | ||
* let divs = element.all(by.repeater('book in library').column('book.name')); | ||
* | ||
* // Returns a promise that resolves to an array of WebElements containing | ||
* // the DIVs for the second book. | ||
* var bookInfo = element.all(by.repeater('book in library').row(1)); | ||
* let bookInfo = element.all(by.repeater('book in library').row(1)); | ||
* | ||
* // Returns the H4 for the first book's name. | ||
* var firstBookName = element(by.repeater('book in library'). | ||
* let firstBookName = element(by.repeater('book in library'). | ||
* row(0).column('book.name')); | ||
@@ -358,3 +359,3 @@ * | ||
* // resolves to an array of 4 elements. | ||
* var divs = element.all(by.repeater('book in library')); | ||
* let divs = element.all(by.repeater('book in library')); | ||
* | ||
@@ -375,8 +376,5 @@ * @param {string} repeatDescriptor | ||
* @example | ||
* expect(element(by.exactRepeater('person in | ||
* peopleWithRedHair')).isPresent()) | ||
* .toBe(true); | ||
* expect(element(by.exactRepeater('person in | ||
* people')).isPresent()).toBe(false); | ||
* expect(element(by.exactRepeater('car in cars')).isPresent()).toBe(true); | ||
* expect(await element(by.exactRepeater('person in peopleWithRedHair')).isPresent()).toBe(true); | ||
* expect(await element(by.exactRepeater('person in people')).isPresent()).toBe(false); | ||
* expect(await element(by.exactRepeater('car in cars')).isPresent()).toBe(true); | ||
* | ||
@@ -403,3 +401,3 @@ * @param {string} repeatDescriptor | ||
* @param {string} cssSelector css selector | ||
* @param {string|RegExp} searchString text search | ||
* @param {string|RegExp} searchText text search | ||
* @returns {ProtractorLocator} location strategy | ||
@@ -410,5 +408,5 @@ */ | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByCssContainingText, cssSelector, searchText, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByCssContainingText, cssSelector, searchText, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -419,3 +417,2 @@ return 'by.cssContainingText("' + cssSelector + '", "' + searchText + '")'; | ||
} | ||
; | ||
/** | ||
@@ -433,5 +430,5 @@ * Find an element by ng-options expression. | ||
* var allOptions = element.all(by.options('c for c in colors')); | ||
* expect(allOptions.count()).toEqual(2); | ||
* expect(await allOptions.count()).toEqual(2); | ||
* var firstOption = allOptions.first(); | ||
* expect(firstOption.getText()).toEqual('red'); | ||
* expect(await firstOption.getText()).toEqual('red'); | ||
* | ||
@@ -443,5 +440,5 @@ * @param {string} optionsDescriptor ng-options expression. | ||
return { | ||
findElementsOverride: (driver, using, rootSelector) => { | ||
return driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByOptions, optionsDescriptor, using, rootSelector)); | ||
}, | ||
findElementsOverride: (driver, using, rootSelector) => __awaiter(this, void 0, void 0, function* () { | ||
return yield driver.findElements(selenium_webdriver_1.By.js(clientSideScripts.findByOptions, optionsDescriptor, using, rootSelector)); | ||
}), | ||
toString: () => { | ||
@@ -452,3 +449,2 @@ return 'by.option("' + optionsDescriptor + '")'; | ||
} | ||
; | ||
/** | ||
@@ -470,3 +466,3 @@ * Find an element by css selector within the Shadow DOM. | ||
* var spans = element.all(by.deepCss('span')); | ||
* expect(spans.count()).toEqual(3); | ||
* expect(await spans.count()).toEqual(3); | ||
* | ||
@@ -481,5 +477,4 @@ * @param {string} selector a css selector within the Shadow DOM. | ||
} | ||
; | ||
} | ||
exports.ProtractorBy = ProtractorBy; | ||
//# sourceMappingURL=locators.js.map |
@@ -6,3 +6,3 @@ import { Config } from './config'; | ||
INFO = 2, | ||
DEBUG = 3, | ||
DEBUG = 3 | ||
} | ||
@@ -13,3 +13,3 @@ export declare enum WriteTo { | ||
BOTH = 2, | ||
NONE = 3, | ||
NONE = 3 | ||
} | ||
@@ -16,0 +16,0 @@ /** |
@@ -1,10 +0,4 @@ | ||
/// <reference types="q" /> | ||
import * as q from 'q'; | ||
import * as webdriver from 'selenium-webdriver'; | ||
import { ProtractorBrowser } from './browser'; | ||
import { Config } from './config'; | ||
export declare enum PromiseType { | ||
Q = 0, | ||
WEBDRIVER = 1, | ||
} | ||
export interface PluginConfig { | ||
@@ -113,4 +107,4 @@ path?: string; | ||
* This is called inside browser.get() directly after angular is done | ||
* bootstrapping/synchronizing. If `browser.ignoreSynchronization` is `true`, | ||
* this will not be called. | ||
* bootstrapping/synchronizing. If `await browser.waitForAngularEnabled()` | ||
* is `false`, this will not be called. | ||
* | ||
@@ -279,4 +273,4 @@ * @param {ProtractorBrowser} browser The browser instance which is loading a page. | ||
*/ | ||
private annotatePluginObj(obj, conf, i); | ||
private printPluginResults(specResults); | ||
private annotatePluginObj; | ||
private printPluginResults; | ||
/** | ||
@@ -303,11 +297,11 @@ * Gets the tests results generated by any plugins | ||
*/ | ||
setup: (...args: any[]) => q.Promise<any[]>; | ||
onPrepare: (...args: any[]) => q.Promise<any[]>; | ||
teardown: (...args: any[]) => q.Promise<any[]>; | ||
postResults: (...args: any[]) => q.Promise<any[]>; | ||
postTest: (...args: any[]) => q.Promise<any[]>; | ||
onPageLoad: (...args: any[]) => webdriver.promise.Promise<any[]>; | ||
onPageStable: (...args: any[]) => webdriver.promise.Promise<any[]>; | ||
waitForPromise: (...args: any[]) => webdriver.promise.Promise<any[]>; | ||
waitForCondition: (...args: any[]) => webdriver.promise.Promise<any[]>; | ||
setup: (...args: any[]) => Promise<any[]>; | ||
onPrepare: (...args: any[]) => Promise<any[]>; | ||
teardown: (...args: any[]) => Promise<any[]>; | ||
postResults: (...args: any[]) => Promise<any[]>; | ||
postTest: (...args: any[]) => Promise<any[]>; | ||
onPageLoad: (...args: any[]) => Promise<any[]>; | ||
onPageStable: (...args: any[]) => Promise<any[]>; | ||
waitForPromise: (...args: any[]) => Promise<any[]>; | ||
waitForCondition: (...args: any[]) => Promise<any[]>; | ||
/** | ||
@@ -322,11 +316,9 @@ * Calls a function from a plugin safely. If the plugin's function throws an | ||
* @param {*[]} args The arguments we want to invoke the function with | ||
* @param {PromiseType} promiseType The type of promise (WebDriver or Q) that | ||
* should be used | ||
* @param {boolean} resultsReported If the results have already been reported | ||
* @param {*} failReturnVal The value to return if the function fails | ||
* | ||
* @return {webdriver.promise.Promise|Q.Promise} A promise which resolves to the | ||
* @return {Promise} A promise which resolves to the | ||
* function's return value | ||
*/ | ||
private safeCallPluginFun(pluginObj, funName, args, promiseType, failReturnVal); | ||
private safeCallPluginFun; | ||
/** | ||
@@ -336,3 +328,2 @@ * Generates the handler for a plugin function (e.g. the setup() function) | ||
* @param {string} funName The name of the function to make a handler for | ||
* @param {PromiseType} promiseType The type of promise (WebDriver or Q) that should be used | ||
* @param {boolean=} failReturnVal The value that the function should return if the plugin crashes | ||
@@ -342,4 +333,3 @@ * | ||
*/ | ||
private pluginFunFactory(funName, promiseType, failReturnVal?); | ||
private pluginFunFactory(funName, promiseType, failReturnVal?); | ||
private pluginFunFactory; | ||
} | ||
@@ -346,0 +336,0 @@ export interface SpecResult { |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const q = require("q"); | ||
const webdriver = require("selenium-webdriver"); | ||
const configParser_1 = require("./configParser"); | ||
const logger_1 = require("./logger"); | ||
const ptor_1 = require("./ptor"); | ||
let logger = new logger_1.Logger('plugins'); | ||
var PromiseType; | ||
(function (PromiseType) { | ||
PromiseType[PromiseType["Q"] = 0] = "Q"; | ||
PromiseType[PromiseType["WEBDRIVER"] = 1] = "WEBDRIVER"; | ||
})(PromiseType = exports.PromiseType || (exports.PromiseType = {})); | ||
/** | ||
@@ -26,11 +26,11 @@ * The plugin API for Protractor. Note that this API is unstable. See | ||
*/ | ||
this.setup = this.pluginFunFactory('setup', PromiseType.Q); | ||
this.onPrepare = this.pluginFunFactory('onPrepare', PromiseType.Q); | ||
this.teardown = this.pluginFunFactory('teardown', PromiseType.Q); | ||
this.postResults = this.pluginFunFactory('postResults', PromiseType.Q); | ||
this.postTest = this.pluginFunFactory('postTest', PromiseType.Q); | ||
this.onPageLoad = this.pluginFunFactory('onPageLoad', PromiseType.WEBDRIVER); | ||
this.onPageStable = this.pluginFunFactory('onPageStable', PromiseType.WEBDRIVER); | ||
this.waitForPromise = this.pluginFunFactory('waitForPromise', PromiseType.WEBDRIVER); | ||
this.waitForCondition = this.pluginFunFactory('waitForCondition', PromiseType.WEBDRIVER, true); | ||
this.setup = this.pluginFunFactory('setup'); | ||
this.onPrepare = this.pluginFunFactory('onPrepare'); | ||
this.teardown = this.pluginFunFactory('teardown'); | ||
this.postResults = this.pluginFunFactory('postResults'); | ||
this.postTest = this.pluginFunFactory('postTest'); | ||
this.onPageLoad = this.pluginFunFactory('onPageLoad'); | ||
this.onPageStable = this.pluginFunFactory('onPageStable'); | ||
this.waitForPromise = this.pluginFunFactory('waitForPromise'); | ||
this.waitForCondition = this.pluginFunFactory('waitForCondition', true); | ||
this.pluginObjs = []; | ||
@@ -68,3 +68,2 @@ this.assertions = {}; | ||
} | ||
; | ||
/** | ||
@@ -149,3 +148,2 @@ * Adds properties to a plugin's object | ||
} | ||
; | ||
/** | ||
@@ -160,3 +158,2 @@ * Returns true if any loaded plugin has skipAngularStability enabled. | ||
} | ||
; | ||
/** | ||
@@ -171,12 +168,10 @@ * Calls a function from a plugin safely. If the plugin's function throws an | ||
* @param {*[]} args The arguments we want to invoke the function with | ||
* @param {PromiseType} promiseType The type of promise (WebDriver or Q) that | ||
* should be used | ||
* @param {boolean} resultsReported If the results have already been reported | ||
* @param {*} failReturnVal The value to return if the function fails | ||
* | ||
* @return {webdriver.promise.Promise|Q.Promise} A promise which resolves to the | ||
* @return {Promise} A promise which resolves to the | ||
* function's return value | ||
*/ | ||
safeCallPluginFun(pluginObj, funName, args, promiseType, failReturnVal) { | ||
const resolver = (done) => { | ||
safeCallPluginFun(pluginObj, funName, args, failReturnVal) { | ||
const resolver = (done) => __awaiter(this, void 0, void 0, function* () { | ||
const logError = (e) => { | ||
@@ -199,9 +194,4 @@ if (this.resultsReported) { | ||
try { | ||
const result = pluginObj[funName].apply(pluginObj, args); | ||
if (webdriver.promise.isPromise(result)) { | ||
result.then(done, logError); | ||
} | ||
else { | ||
done(result); | ||
} | ||
const result = yield pluginObj[funName].apply(pluginObj, args); | ||
done(result); | ||
} | ||
@@ -211,18 +201,10 @@ catch (e) { | ||
} | ||
}; | ||
if (promiseType == PromiseType.Q) { | ||
return q.Promise(resolver); | ||
} | ||
else if (ptor_1.protractor.browser.controlFlowIsEnabled()) { | ||
return new webdriver.promise.Promise(resolver); | ||
} | ||
else { | ||
return new Promise(resolver); | ||
} | ||
}); | ||
return new Promise(resolver); | ||
} | ||
pluginFunFactory(funName, promiseType, failReturnVal) { | ||
pluginFunFactory(funName, failReturnVal) { | ||
return (...args) => { | ||
const promises = this.pluginObjs.filter(pluginObj => typeof pluginObj[funName] === 'function') | ||
.map(pluginObj => this.safeCallPluginFun(pluginObj, funName, args, promiseType, failReturnVal)); | ||
return promiseType == PromiseType.Q ? q.all(promises) : webdriver.promise.all(promises); | ||
.map(pluginObj => this.safeCallPluginFun(pluginObj, funName, args, failReturnVal)); | ||
return Promise.all(promises); | ||
}; | ||
@@ -229,0 +211,0 @@ } |
/// <reference types="node" /> | ||
/// <reference types="q" /> | ||
import { EventEmitter } from 'events'; | ||
import * as q from 'q'; | ||
import { promise as wdpromise } from 'selenium-webdriver'; | ||
import { ProtractorBrowser } from './browser'; | ||
@@ -16,5 +13,5 @@ import { Config } from './config'; | ||
plugins_: Plugins; | ||
restartPromise: q.Promise<any>; | ||
restartPromise: Promise<any>; | ||
frameworkUsesAfterEach: boolean; | ||
ready_?: wdpromise.Promise<void>; | ||
ready_?: Promise<void>; | ||
constructor(config: Config); | ||
@@ -31,6 +28,6 @@ /** | ||
* @param {string[]=} An optional list of command line arguments the framework will accept. | ||
* @return {q.Promise} A promise that will resolve when the test preparers | ||
* @return {Promise} A promise that will resolve when the test preparers | ||
* are finished. | ||
*/ | ||
runTestPreparer(extraFlags?: string[]): q.Promise<any>; | ||
runTestPreparer(extraFlags?: string[]): Promise<any>; | ||
/** | ||
@@ -42,5 +39,5 @@ * Called after each test finishes. | ||
* @public | ||
* @return {q.Promise} A promise that will resolve when the work here is done | ||
* @return {Promise} A promise that will resolve when the work here is done | ||
*/ | ||
afterEach(): q.Promise<void>; | ||
afterEach(): Promise<void>; | ||
/** | ||
@@ -63,3 +60,3 @@ * Grab driver provider based on type | ||
*/ | ||
exit_: (exitCode: number) => any; | ||
exit_(exitCode: number): Promise<number>; | ||
/** | ||
@@ -72,7 +69,2 @@ * Getter for the Runner config object | ||
/** | ||
* Get the control flow used by this runner. | ||
* @return {Object} WebDriver control flow. | ||
*/ | ||
controlFlow(): any; | ||
/** | ||
* Sets up convenience globals for test specs | ||
@@ -94,17 +86,17 @@ * @private | ||
*/ | ||
createBrowser(plugins: any, parentBrowser?: ProtractorBrowser): any; | ||
createBrowser(plugins: any, parentBrowser?: ProtractorBrowser): Promise<any>; | ||
/** | ||
* Final cleanup on exiting the runner. | ||
* | ||
* @return {q.Promise} A promise which resolves on finish. | ||
* @return {Promise} A promise which resolves on finish. | ||
* @private | ||
*/ | ||
shutdown_(): q.Promise<void>; | ||
shutdown_(): Promise<void>; | ||
/** | ||
* The primary workhorse interface. Kicks off the test running process. | ||
* | ||
* @return {q.Promise} A promise which resolves to the exit code of the tests. | ||
* @return {Promise} A promise which resolves to the exit code of the tests. | ||
* @public | ||
*/ | ||
run(): q.Promise<any>; | ||
run(): Promise<number>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const events_1 = require("events"); | ||
const q = require("q"); | ||
// TODO(cnishina): remove when selenium webdriver is upgraded. | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
@@ -12,3 +20,3 @@ const util = require("util"); | ||
const ptor_1 = require("./ptor"); | ||
const helper = require("./util"); | ||
const util_1 = require("./util"); | ||
let logger = new logger_1.Logger('runner'); | ||
@@ -30,18 +38,2 @@ /* | ||
super(); | ||
/** | ||
* Responsible for cleaning up test run and exiting the process. | ||
* @private | ||
* @param {int} Standard unix exit code | ||
*/ | ||
this.exit_ = function (exitCode) { | ||
return helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]) | ||
.then((returned) => { | ||
if (typeof returned === 'number') { | ||
return returned; | ||
} | ||
else { | ||
return exitCode; | ||
} | ||
}); | ||
}; | ||
this.config_ = config; | ||
@@ -54,14 +46,9 @@ if (config.v8Debug) { | ||
process['_debugProcess'](process.pid); | ||
let flow = selenium_webdriver_1.promise.controlFlow(); | ||
this.ready_ = flow.execute(() => { | ||
let nodedebug = require('child_process').fork('debug', ['localhost:5858']); | ||
process.on('exit', function () { | ||
nodedebug.kill('SIGTERM'); | ||
}); | ||
nodedebug.on('exit', function () { | ||
process.exit(1); | ||
}); | ||
}, 'start the node debugger').then(() => { | ||
return flow.timeout(1000, 'waiting for debugger to attach'); | ||
const nodedebug = require('child_process').fork('debug', ['localhost:5858']); | ||
process.on('exit', () => { | ||
nodedebug.kill('SIGTERM'); | ||
}); | ||
nodedebug.on('exit', () => { | ||
process.exit(1); | ||
}); | ||
} | ||
@@ -86,3 +73,3 @@ if (config.capabilities && config.capabilities.seleniumAddress) { | ||
* @param {string[]=} An optional list of command line arguments the framework will accept. | ||
* @return {q.Promise} A promise that will resolve when the test preparers | ||
* @return {Promise} A promise that will resolve when the test preparers | ||
* are finished. | ||
@@ -102,3 +89,3 @@ */ | ||
return this.plugins_.onPrepare().then(() => { | ||
return helper.runFilenameOrFn_(this.config_.configDir, this.preparer_); | ||
return util_1.runFilenameOrFn_(this.config_.configDir, this.preparer_); | ||
}); | ||
@@ -112,3 +99,3 @@ } | ||
* @public | ||
* @return {q.Promise} A promise that will resolve when the work here is done | ||
* @return {Promise} A promise that will resolve when the work here is done | ||
*/ | ||
@@ -119,7 +106,7 @@ afterEach() { | ||
if (this.config_.restartBrowserBetweenTests) { | ||
this.restartPromise = this.restartPromise || q(ptor_1.protractor.browser.restart()); | ||
this.restartPromise = this.restartPromise || Promise.resolve(ptor_1.protractor.browser.restart()); | ||
ret = this.restartPromise; | ||
this.restartPromise = undefined; | ||
} | ||
return ret || q(); | ||
return ret || Promise.resolve(); | ||
} | ||
@@ -142,2 +129,18 @@ /** | ||
/** | ||
* Responsible for cleaning up test run and exiting the process. | ||
* @private | ||
* @param {int} Standard unix exit code | ||
*/ | ||
exit_(exitCode) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const returned = yield util_1.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]); | ||
if (typeof returned === 'number') { | ||
return returned; | ||
} | ||
else { | ||
return exitCode; | ||
} | ||
}); | ||
} | ||
/** | ||
* Getter for the Runner config object | ||
@@ -151,9 +154,2 @@ * @public | ||
/** | ||
* Get the control flow used by this runner. | ||
* @return {Object} WebDriver control flow. | ||
*/ | ||
controlFlow() { | ||
return selenium_webdriver_1.promise.controlFlow(); | ||
} | ||
/** | ||
* Sets up convenience globals for test specs | ||
@@ -203,62 +199,54 @@ * @private | ||
createBrowser(plugins, parentBrowser) { | ||
let config = this.config_; | ||
let driver = this.driverprovider_.getNewDriver(); | ||
let blockingProxyUrl; | ||
if (config.useBlockingProxy) { | ||
blockingProxyUrl = this.driverprovider_.getBPUrl(); | ||
} | ||
let initProperties = { | ||
baseUrl: config.baseUrl, | ||
rootElement: config.rootElement, | ||
untrackOutstandingTimeouts: config.untrackOutstandingTimeouts, | ||
params: config.params, | ||
getPageTimeout: config.getPageTimeout, | ||
allScriptsTimeout: config.allScriptsTimeout, | ||
debuggerServerPort: config.debuggerServerPort, | ||
ng12Hybrid: config.ng12Hybrid, | ||
waitForAngularEnabled: true | ||
}; | ||
if (parentBrowser) { | ||
initProperties.baseUrl = parentBrowser.baseUrl; | ||
initProperties.rootElement = parentBrowser.angularAppRoot(); | ||
initProperties.untrackOutstandingTimeouts = !parentBrowser.trackOutstandingTimeouts_; | ||
initProperties.params = parentBrowser.params; | ||
initProperties.getPageTimeout = parentBrowser.getPageTimeout; | ||
initProperties.allScriptsTimeout = parentBrowser.allScriptsTimeout; | ||
initProperties.debuggerServerPort = parentBrowser.debuggerServerPort; | ||
initProperties.ng12Hybrid = parentBrowser.ng12Hybrid; | ||
initProperties.waitForAngularEnabled = parentBrowser.waitForAngularEnabled(); | ||
} | ||
let browser_ = new browser_1.ProtractorBrowser(driver, initProperties.baseUrl, initProperties.rootElement, initProperties.untrackOutstandingTimeouts, blockingProxyUrl); | ||
browser_.params = initProperties.params; | ||
browser_.plugins_ = plugins || new plugins_1.Plugins({}); | ||
if (initProperties.getPageTimeout) { | ||
browser_.getPageTimeout = initProperties.getPageTimeout; | ||
} | ||
if (initProperties.allScriptsTimeout) { | ||
browser_.allScriptsTimeout = initProperties.allScriptsTimeout; | ||
} | ||
if (initProperties.debuggerServerPort) { | ||
browser_.debuggerServerPort = initProperties.debuggerServerPort; | ||
} | ||
if (initProperties.ng12Hybrid) { | ||
browser_.ng12Hybrid = initProperties.ng12Hybrid; | ||
} | ||
browser_.ready = | ||
browser_.ready | ||
.then(() => { | ||
return browser_.waitForAngularEnabled(initProperties.waitForAngularEnabled); | ||
}) | ||
.then(() => { | ||
return driver.manage().timeouts().setScriptTimeout(initProperties.allScriptsTimeout || 0); | ||
}) | ||
.then(() => { | ||
return browser_; | ||
}); | ||
browser_.getProcessedConfig = () => { | ||
return selenium_webdriver_1.promise.when(config); | ||
}; | ||
browser_.forkNewDriverInstance = | ||
(useSameUrl, copyMockModules, copyConfigUpdates = true) => { | ||
let newBrowser = this.createBrowser(plugins); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let config = this.config_; | ||
let driver = yield this.driverprovider_.getNewDriver(); | ||
let blockingProxyUrl; | ||
if (config.useBlockingProxy) { | ||
blockingProxyUrl = this.driverprovider_.getBPUrl(); | ||
} | ||
let initProperties = { | ||
baseUrl: config.baseUrl, | ||
rootElement: config.rootElement, | ||
untrackOutstandingTimeouts: config.untrackOutstandingTimeouts, | ||
params: config.params, | ||
getPageTimeout: config.getPageTimeout, | ||
allScriptsTimeout: config.allScriptsTimeout, | ||
debuggerServerPort: config.debuggerServerPort, | ||
ng12Hybrid: config.ng12Hybrid, | ||
waitForAngularEnabled: true | ||
}; | ||
if (parentBrowser) { | ||
initProperties.baseUrl = parentBrowser.baseUrl; | ||
initProperties.rootElement = parentBrowser.angularAppRoot(); | ||
initProperties.untrackOutstandingTimeouts = !parentBrowser.trackOutstandingTimeouts_; | ||
initProperties.params = parentBrowser.params; | ||
initProperties.getPageTimeout = parentBrowser.getPageTimeout; | ||
initProperties.allScriptsTimeout = parentBrowser.allScriptsTimeout; | ||
initProperties.debuggerServerPort = parentBrowser.debuggerServerPort; | ||
initProperties.ng12Hybrid = parentBrowser.ng12Hybrid; | ||
initProperties.waitForAngularEnabled = parentBrowser.waitForAngularEnabled(); | ||
} | ||
let browser_ = new browser_1.ProtractorBrowser(driver, initProperties.baseUrl, initProperties.rootElement, initProperties.untrackOutstandingTimeouts, blockingProxyUrl); | ||
browser_.params = initProperties.params; | ||
browser_.plugins_ = plugins || new plugins_1.Plugins({}); | ||
if (initProperties.getPageTimeout) { | ||
browser_.getPageTimeout = initProperties.getPageTimeout; | ||
} | ||
if (initProperties.allScriptsTimeout) { | ||
browser_.allScriptsTimeout = initProperties.allScriptsTimeout; | ||
} | ||
if (initProperties.debuggerServerPort) { | ||
browser_.debuggerServerPort = initProperties.debuggerServerPort; | ||
} | ||
if (initProperties.ng12Hybrid) { | ||
browser_.ng12Hybrid = initProperties.ng12Hybrid; | ||
} | ||
yield browser_.waitForAngularEnabled(initProperties.waitForAngularEnabled); | ||
// TODO(selenium4): Options does not have a setScriptTimeout method. | ||
yield driver.manage().setTimeouts({ script: initProperties.allScriptsTimeout || 0 }); | ||
browser_.getProcessedConfig = () => { | ||
return Promise.resolve(config); | ||
}; | ||
browser_.forkNewDriverInstance = (useSameUrl, copyMockModules, copyConfigUpdates = true) => __awaiter(this, void 0, void 0, function* () { | ||
let newBrowser = yield this.createBrowser(plugins); | ||
if (copyMockModules) { | ||
@@ -268,43 +256,23 @@ newBrowser.mockModules_ = browser_.mockModules_; | ||
if (useSameUrl) { | ||
newBrowser.ready = newBrowser.ready | ||
.then(() => { | ||
return browser_.driver.getCurrentUrl(); | ||
}) | ||
.then((url) => { | ||
return newBrowser.get(url); | ||
}) | ||
.then(() => { | ||
return newBrowser; | ||
}); | ||
const currentUrl = yield browser_.driver.getCurrentUrl(); | ||
yield newBrowser.get(currentUrl); | ||
} | ||
return newBrowser; | ||
}; | ||
let replaceBrowser = () => { | ||
let newBrowser = browser_.forkNewDriverInstance(false, true); | ||
if (browser_ === ptor_1.protractor.browser) { | ||
this.setupGlobals_(newBrowser); | ||
} | ||
return newBrowser; | ||
}; | ||
browser_.restart = () => { | ||
// Note: because tests are not paused at this point, any async | ||
// calls here are not guaranteed to complete before the tests resume. | ||
// Seperate solutions depending on if the control flow is enabled (see lib/browser.ts) | ||
if (browser_.controlFlowIsEnabled()) { | ||
return browser_.restartSync().ready; | ||
} | ||
else { | ||
return this.driverprovider_.quitDriver(browser_.driver) | ||
.then(replaceBrowser) | ||
.then(newBrowser => newBrowser.ready); | ||
} | ||
}; | ||
browser_.restartSync = () => { | ||
if (!browser_.controlFlowIsEnabled()) { | ||
throw TypeError('Unable to use `browser.restartSync()` when the control flow is disabled'); | ||
} | ||
this.driverprovider_.quitDriver(browser_.driver); | ||
return replaceBrowser(); | ||
}; | ||
return browser_; | ||
}); | ||
let replaceBrowser = () => __awaiter(this, void 0, void 0, function* () { | ||
let newBrowser = yield browser_.forkNewDriverInstance(false, true); | ||
if (browser_ === ptor_1.protractor.browser) { | ||
this.setupGlobals_(newBrowser); | ||
} | ||
return newBrowser; | ||
}); | ||
browser_.restart = () => __awaiter(this, void 0, void 0, function* () { | ||
// Note: because tests are not paused at this point, any async | ||
// calls here are not guaranteed to complete before the tests resume. | ||
const restartedBrowser = yield replaceBrowser(); | ||
yield this.driverprovider_.quitDriver(browser_.driver); | ||
return restartedBrowser; | ||
}); | ||
return browser_; | ||
}); | ||
} | ||
@@ -314,3 +282,3 @@ /** | ||
* | ||
* @return {q.Promise} A promise which resolves on finish. | ||
* @return {Promise} A promise which resolves on finish. | ||
* @private | ||
@@ -324,46 +292,40 @@ */ | ||
* | ||
* @return {q.Promise} A promise which resolves to the exit code of the tests. | ||
* @return {Promise} A promise which resolves to the exit code of the tests. | ||
* @public | ||
*/ | ||
run() { | ||
let testPassed; | ||
let plugins = this.plugins_ = new plugins_1.Plugins(this.config_); | ||
let pluginPostTestPromises; | ||
let browser_; | ||
let results; | ||
if (this.config_.framework !== 'explorer' && !this.config_.specs.length) { | ||
throw new Error('Spec patterns did not match any files.'); | ||
} | ||
if (this.config_.SELENIUM_PROMISE_MANAGER != null) { | ||
selenium_webdriver_1.promise.USE_PROMISE_MANAGER = this.config_.SELENIUM_PROMISE_MANAGER; | ||
} | ||
if (this.config_.webDriverLogDir || this.config_.highlightDelay) { | ||
this.config_.useBlockingProxy = true; | ||
} | ||
// 0) Wait for debugger | ||
return q(this.ready_) | ||
.then(() => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let testPassed; | ||
let plugins = this.plugins_ = new plugins_1.Plugins(this.config_); | ||
let pluginPostTestPromises; | ||
let browser_; | ||
let results; | ||
if (this.config_.framework !== 'explorer' && !this.config_.specs.length) { | ||
throw new Error('Spec patterns did not match any files.'); | ||
} | ||
// TODO(selenium4): Remove when selenium is upgraded. | ||
if (this.config_.SELENIUM_PROMISE_MANAGER != null) { | ||
selenium_webdriver_1.promise.USE_PROMISE_MANAGER = this.config_.SELENIUM_PROMISE_MANAGER; | ||
} | ||
if (this.config_.webDriverLogDir || this.config_.highlightDelay) { | ||
this.config_.useBlockingProxy = true; | ||
} | ||
// 1) Setup environment | ||
// noinspection JSValidateTypes | ||
return this.driverprovider_.setupEnv(); | ||
}) | ||
.then(() => { | ||
yield this.driverprovider_.setupEnv(); | ||
// 2) Create a browser and setup globals | ||
browser_ = this.createBrowser(plugins); | ||
browser_ = yield this.createBrowser(plugins); | ||
this.setupGlobals_(browser_); | ||
return browser_.ready.then(browser_.getSession) | ||
.then((session) => { | ||
try { | ||
const session = yield browser_.getSession(); | ||
logger.debug('WebDriver session successfully started with capabilities ' + | ||
util.inspect(session.getCapabilities())); | ||
}, (err) => { | ||
} | ||
catch (err) { | ||
logger.error('Unable to start a WebDriver session.'); | ||
throw err; | ||
}); | ||
} | ||
// 3) Setup plugins | ||
}) | ||
.then(() => { | ||
return plugins.setup(); | ||
yield plugins.setup(); | ||
// 4) Execute test cases | ||
}) | ||
.then(() => { | ||
// Do the framework setup here so that jasmine and mocha globals are | ||
@@ -398,7 +360,7 @@ // available to the onPrepare function. | ||
// TODO(sjelin): replace with warnings once `afterEach` support is required | ||
let restartDriver = () => { | ||
let restartDriver = () => __awaiter(this, void 0, void 0, function* () { | ||
if (!this.frameworkUsesAfterEach) { | ||
this.restartPromise = q(browser_.restart()); | ||
this.restartPromise = yield browser_.restart(); | ||
} | ||
}; | ||
}); | ||
this.on('testPass', restartDriver); | ||
@@ -419,38 +381,22 @@ this.on('testFail', restartDriver); | ||
logger.debug('Running with spec files ' + this.config_.specs); | ||
return require(frameworkPath).run(this, this.config_.specs); | ||
let testResults = yield require(frameworkPath).run(this, this.config_.specs); | ||
// 5) Wait for postTest plugins to finish | ||
}) | ||
.then((testResults) => { | ||
results = testResults; | ||
return q.all(pluginPostTestPromises); | ||
yield Promise.all(pluginPostTestPromises); | ||
// 6) Teardown plugins | ||
}) | ||
.then(() => { | ||
return plugins.teardown(); | ||
yield plugins.teardown(); | ||
// 7) Teardown | ||
}) | ||
.then(() => { | ||
results = helper.joinTestLogs(results, plugins.getResults()); | ||
results = util_1.joinTestLogs(results, plugins.getResults()); | ||
this.emit('testsDone', results); | ||
testPassed = results.failedCount === 0; | ||
if (this.driverprovider_.updateJob) { | ||
return this.driverprovider_.updateJob({ 'passed': testPassed }).then(() => { | ||
return this.driverprovider_.teardownEnv(); | ||
}); | ||
yield this.driverprovider_.updateJob({ 'passed': testPassed }); | ||
} | ||
else { | ||
return this.driverprovider_.teardownEnv(); | ||
} | ||
yield this.driverprovider_.teardownEnv(); | ||
// 8) Let plugins do final cleanup | ||
}) | ||
.then(() => { | ||
return plugins.postResults(); | ||
yield plugins.postResults(); | ||
// 9) Exit process | ||
}) | ||
.then(() => { | ||
let exitCode = testPassed ? 0 : 1; | ||
const exitCode = testPassed ? 0 : 1; | ||
yield this.shutdown_(); | ||
return this.exit_(exitCode); | ||
}) | ||
.fin(() => { | ||
return this.shutdown_(); | ||
}); | ||
@@ -457,0 +403,0 @@ } |
@@ -21,3 +21,3 @@ export declare class TaskLogger { | ||
*/ | ||
private logHeader_(); | ||
private logHeader_; | ||
/** | ||
@@ -24,0 +24,0 @@ * Prints the contents of the buffer without clearing it. |
/// <reference types="node" /> | ||
/// <reference types="q" /> | ||
import { EventEmitter } from 'events'; | ||
import * as q from 'q'; | ||
import { Config } from './config'; | ||
export interface RunResults { | ||
taskId: number; | ||
specs: Array<string>; | ||
capabilities: any; | ||
failedCount: number; | ||
exitCode: number; | ||
specResults: Array<any>; | ||
taskId?: number; | ||
specs?: Array<string>; | ||
capabilities?: any; | ||
failedCount?: number; | ||
exitCode?: number; | ||
specResults?: Array<any>; | ||
} | ||
@@ -34,3 +32,3 @@ /** | ||
* Sends the run command. | ||
* @return {q.Promise} A promise that will resolve when the task finishes | ||
* @return {Promise} A promise that will resolve when the task finishes | ||
* running. The promise contains the following parameters representing the | ||
@@ -40,3 +38,3 @@ * result of the run: | ||
*/ | ||
run(): q.Promise<any>; | ||
run(): Promise<any>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const child_process = require("child_process"); | ||
const events_1 = require("events"); | ||
const q = require("q"); | ||
const configParser_1 = require("./configParser"); | ||
@@ -31,3 +38,3 @@ const runner_1 = require("./runner"); | ||
* Sends the run command. | ||
* @return {q.Promise} A promise that will resolve when the task finishes | ||
* @return {Promise} A promise that will resolve when the task finishes | ||
* running. The promise contains the following parameters representing the | ||
@@ -38,80 +45,81 @@ * result of the run: | ||
run() { | ||
let runResults = { | ||
taskId: this.task.taskId, | ||
specs: this.task.specs, | ||
capabilities: this.task.capabilities, | ||
// The following are populated while running the test: | ||
failedCount: 0, | ||
exitCode: -1, | ||
specResults: [] | ||
}; | ||
let configParser = new configParser_1.ConfigParser(); | ||
if (this.configFile) { | ||
configParser.addFileConfig(this.configFile); | ||
} | ||
if (this.additionalConfig) { | ||
configParser.addConfig(this.additionalConfig); | ||
} | ||
let config = configParser.getConfig(); | ||
config.capabilities = this.task.capabilities; | ||
config.specs = this.task.specs; | ||
if (this.runInFork) { | ||
let deferred = q.defer(); | ||
let childProcess = child_process.fork(__dirname + '/runnerCli.js', process.argv.slice(2), { cwd: process.cwd(), silent: true }); | ||
let taskLogger = new taskLogger_1.TaskLogger(this.task, childProcess.pid); | ||
// stdout pipe | ||
childProcess.stdout.on('data', (data) => { | ||
taskLogger.log(data); | ||
}); | ||
// stderr pipe | ||
childProcess.stderr.on('data', (data) => { | ||
taskLogger.log(data); | ||
}); | ||
childProcess | ||
.on('message', (m) => { | ||
if (config.verboseMultiSessions) { | ||
taskLogger.peek(); | ||
} | ||
switch (m.event) { | ||
case 'testPass': | ||
process.stdout.write('.'); | ||
break; | ||
case 'testFail': | ||
process.stdout.write('F'); | ||
break; | ||
case 'testsDone': | ||
runResults.failedCount = m.results.failedCount; | ||
runResults.specResults = m.results.specResults; | ||
break; | ||
} | ||
}) | ||
.on('error', (err) => { | ||
taskLogger.flush(); | ||
deferred.reject(err); | ||
}) | ||
.on('exit', (code) => { | ||
taskLogger.flush(); | ||
runResults.exitCode = code; | ||
deferred.resolve(runResults); | ||
}); | ||
childProcess.send({ | ||
command: 'run', | ||
configFile: this.configFile, | ||
additionalConfig: this.additionalConfig, | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let runResults = { | ||
taskId: this.task.taskId, | ||
specs: this.task.specs, | ||
capabilities: this.task.capabilities, | ||
specs: this.task.specs | ||
}); | ||
return deferred.promise; | ||
} | ||
else { | ||
let runner = new runner_1.Runner(config); | ||
runner.on('testsDone', (results) => { | ||
runResults.failedCount = results.failedCount; | ||
runResults.specResults = results.specResults; | ||
}); | ||
return runner.run().then((exitCode) => { | ||
// The following are populated while running the test: | ||
failedCount: 0, | ||
exitCode: -1, | ||
specResults: [] | ||
}; | ||
let configParser = new configParser_1.ConfigParser(); | ||
if (this.configFile) { | ||
configParser.addFileConfig(this.configFile); | ||
} | ||
if (this.additionalConfig) { | ||
configParser.addConfig(this.additionalConfig); | ||
} | ||
let config = configParser.getConfig(); | ||
config.capabilities = this.task.capabilities; | ||
config.specs = this.task.specs; | ||
if (this.runInFork) { | ||
return new Promise((resolve, reject) => { | ||
let childProcess = child_process.fork(__dirname + '/runnerCli.js', process.argv.slice(2), { cwd: process.cwd(), silent: true }); | ||
let taskLogger = new taskLogger_1.TaskLogger(this.task, childProcess.pid); | ||
// stdout pipe | ||
childProcess.stdout.on('data', (data) => { | ||
taskLogger.log(data); | ||
}); | ||
// stderr pipe | ||
childProcess.stderr.on('data', (data) => { | ||
taskLogger.log(data); | ||
}); | ||
childProcess | ||
.on('message', (m) => { | ||
if (config.verboseMultiSessions) { | ||
taskLogger.peek(); | ||
} | ||
switch (m.event) { | ||
case 'testPass': | ||
process.stdout.write('.'); | ||
break; | ||
case 'testFail': | ||
process.stdout.write('F'); | ||
break; | ||
case 'testsDone': | ||
runResults.failedCount = m.results.failedCount; | ||
runResults.specResults = m.results.specResults; | ||
break; | ||
} | ||
}) | ||
.on('error', (err) => { | ||
taskLogger.flush(); | ||
reject(err); | ||
}) | ||
.on('exit', (code) => { | ||
taskLogger.flush(); | ||
runResults.exitCode = code; | ||
resolve(runResults); | ||
}); | ||
childProcess.send({ | ||
command: 'run', | ||
configFile: this.configFile, | ||
additionalConfig: this.additionalConfig, | ||
capabilities: this.task.capabilities, | ||
specs: this.task.specs | ||
}); | ||
}); | ||
} | ||
else { | ||
let runner = new runner_1.Runner(config); | ||
runner.on('testsDone', (results) => { | ||
runResults.failedCount = results.failedCount; | ||
runResults.specResults = results.specResults; | ||
}); | ||
const exitCode = yield runner.run(); | ||
runResults.exitCode = exitCode; | ||
return runResults; | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
@@ -118,0 +126,0 @@ } |
@@ -1,3 +0,1 @@ | ||
/// <reference types="q" /> | ||
import { Promise } from 'q'; | ||
/** | ||
@@ -14,3 +12,3 @@ * Utility function that filters a stack trace to be more readable. It removes | ||
* @param {Array.<object>}} args The args to pass into filenameOrFn. | ||
* @return {q.Promise} A promise that will resolve when filenameOrFn completes. | ||
* @return {Promise} A promise that will resolve when filenameOrFn completes. | ||
*/ | ||
@@ -17,0 +15,0 @@ export declare function runFilenameOrFn_(configDir: string, filenameOrFn: any, args?: any[]): Promise<any>; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const q_1 = require("q"); | ||
const path = require("path"); | ||
const selenium_webdriver_1 = require("selenium-webdriver"); | ||
let STACK_SUBSTRINGS_TO_FILTER = [ | ||
'node_modules/jasmine/', 'node_modules/selenium-webdriver', 'at Module.', 'at Object.Module.', | ||
'at Function.Module', '(timers.js:', 'jasminewd2/index.js', 'protractor/lib/' | ||
'at Function.Module', '(timers.js:', 'protractor/lib/' | ||
]; | ||
@@ -35,6 +42,6 @@ /** | ||
* @param {Array.<object>}} args The args to pass into filenameOrFn. | ||
* @return {q.Promise} A promise that will resolve when filenameOrFn completes. | ||
* @return {Promise} A promise that will resolve when filenameOrFn completes. | ||
*/ | ||
function runFilenameOrFn_(configDir, filenameOrFn, args) { | ||
return q_1.Promise((resolvePromise) => { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (filenameOrFn && !(typeof filenameOrFn === 'string' || typeof filenameOrFn === 'function')) { | ||
@@ -44,6 +51,10 @@ throw new Error('filenameOrFn must be a string or function'); | ||
if (typeof filenameOrFn === 'string') { | ||
filenameOrFn = require(path_1.resolve(configDir, filenameOrFn)); | ||
filenameOrFn = require(path.resolve(configDir, filenameOrFn)); | ||
} | ||
if (typeof filenameOrFn === 'function') { | ||
let results = q_1.when(filenameOrFn.apply(null, args), null, (err) => { | ||
let results; | ||
try { | ||
results = yield filenameOrFn.apply(null, args); | ||
} | ||
catch (err) { | ||
if (typeof err === 'string') { | ||
@@ -60,7 +71,7 @@ err = new Error(err); | ||
throw err; | ||
}); | ||
resolvePromise(results); | ||
} | ||
return results; | ||
} | ||
else { | ||
resolvePromise(undefined); | ||
return undefined; | ||
} | ||
@@ -67,0 +78,0 @@ }); |
104
gulpfile.js
'use strict'; | ||
var gulp = require('gulp'); | ||
var clangFormat = require('clang-format'); | ||
var gulpFormat = require('gulp-clang-format'); | ||
var runSequence = require('run-sequence'); | ||
var spawn = require('child_process').spawn; | ||
var spawnSync = require('child_process').spawnSync; | ||
var tslint = require('gulp-tslint'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var glob = require('glob'); | ||
var semver = require('semver'); | ||
const gulp = require('gulp'); | ||
const format = require('gulp-clang-format'); | ||
const clangFormat = require('clang-format'); | ||
const spawn = require('child_process').spawn; | ||
const tslint = require('gulp-tslint'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const semver = require('semver'); | ||
var runSpawn = function(done, task, opt_arg, opt_io) { | ||
const runSpawn = (done, task, opt_arg, opt_io) => { | ||
opt_arg = typeof opt_arg !== 'undefined' ? opt_arg : []; | ||
var stdio = 'inherit'; | ||
const stdio = 'inherit'; | ||
if (opt_io === 'ignore') { | ||
stdio = 'ignore'; | ||
} | ||
var child = spawn(task, opt_arg, {stdio: stdio}); | ||
var running = false; | ||
child.on('close', function() { | ||
const child = spawn(task, opt_arg, {stdio: stdio}); | ||
let running = false; | ||
child.on('close', () => { | ||
if (!running) { | ||
@@ -29,3 +26,3 @@ running = true; | ||
}); | ||
child.on('error', function() { | ||
child.on('error', () => { | ||
if (!running) { | ||
@@ -39,17 +36,21 @@ console.error('gulp encountered a child error'); | ||
gulp.task('tslint', function() { | ||
gulp.task('tslint', () => { | ||
return gulp.src(['lib/**/*.ts', 'spec/**/*.ts', '!spec/install/**/*.ts']) | ||
.pipe(tslint()).pipe(tslint.report()); | ||
.pipe(tslint()) | ||
.pipe(tslint.report()); | ||
}); | ||
gulp.task('lint', function(done) { | ||
runSequence('tslint', 'jshint', 'format:enforce', done); | ||
gulp.task('format:enforce', () => { | ||
return gulp.src(['lib/**/*.ts']) | ||
.pipe(format.checkFormat('file', clangFormat, {verbose: true, fail: true})); | ||
}); | ||
gulp.task('lint', gulp.series('tslint', 'format:enforce')); | ||
// prevent contributors from using the wrong version of node | ||
gulp.task('checkVersion', function(done) { | ||
gulp.task('checkVersion', (done) => { | ||
// read minimum node on package.json | ||
var packageJson = JSON.parse(fs.readFileSync(path.resolve('package.json'))); | ||
var protractorVersion = packageJson.version; | ||
var nodeVersion = packageJson.engines.node; | ||
const packageJson = JSON.parse(fs.readFileSync(path.resolve('package.json'))); | ||
const protractorVersion = packageJson.version; | ||
const nodeVersion = packageJson.engines.node; | ||
@@ -64,58 +65,33 @@ if (semver.satisfies(process.version, nodeVersion)) { | ||
gulp.task('built:copy', function(done) { | ||
gulp.task('built:copy', () => { | ||
return gulp.src(['lib/**/*.js']) | ||
.pipe(gulp.dest('built/')); | ||
done(); | ||
}); | ||
gulp.task('webdriver:update', function(done) { | ||
gulp.task('webdriver:update', (done) => { | ||
runSpawn(done, 'node', ['bin/webdriver-manager', 'update']); | ||
}); | ||
gulp.task('jshint', function(done) { | ||
runSpawn(done, 'node', ['node_modules/jshint/bin/jshint', '-c', | ||
'.jshintrc', 'lib', 'spec', 'scripts', | ||
'--exclude=lib/selenium-webdriver/**/*.js,lib/webdriver-js-extender/**/*.js,' + | ||
'spec/dependencyTest/*.js,spec/install/**/*.js']); | ||
gulp.task('format', () => { | ||
return gulp.src(['lib/**/*.ts'], { base: '.' }) | ||
.pipe(format.format('file', clangFormat)) | ||
.pipe(gulp.dest('.')); | ||
}); | ||
gulp.task('format:enforce', function() { | ||
var format = require('gulp-clang-format'); | ||
var clangFormat = require('clang-format'); | ||
return gulp.src(['lib/**/*.ts']).pipe( | ||
format.checkFormat('file', clangFormat, {verbose: true, fail: true})); | ||
}); | ||
gulp.task('format', function() { | ||
var format = require('gulp-clang-format'); | ||
var clangFormat = require('clang-format'); | ||
return gulp.src(['lib/**/*.ts'], { base: '.' }).pipe( | ||
format.format('file', clangFormat)).pipe(gulp.dest('.')); | ||
}); | ||
gulp.task('tsc', function(done) { | ||
gulp.task('tsc', (done) => { | ||
runSpawn(done, 'node', ['node_modules/typescript/bin/tsc']); | ||
}); | ||
gulp.task('tsc:spec', function(done) { | ||
gulp.task('tsc:spec', (done) => { | ||
runSpawn(done, 'node', ['node_modules/typescript/bin/tsc', '-p', 'ts_spec_config.json']); | ||
}); | ||
gulp.task('tsc:es5', function(done) { | ||
runSpawn(done, './scripts/compile_to_es5.sh'); | ||
}); | ||
gulp.task('prepublish', gulp.series('checkVersion', 'tsc', 'built:copy')); | ||
gulp.task('compile_to_es5', function(done) { | ||
runSequence('checkVersion', 'tsc:es5', 'built:copy', done); | ||
}); | ||
gulp.task('pretest', gulp.series( | ||
'checkVersion', | ||
gulp.parallel('webdriver:update', 'tslint', 'format'), | ||
'tsc', 'built:copy', 'tsc:spec')); | ||
gulp.task('prepublish', function(done) { | ||
runSequence('checkVersion', 'tsc', 'built:copy', done); | ||
}); | ||
gulp.task('default', gulp.series('prepublish')); | ||
gulp.task('pretest', function(done) { | ||
runSequence('checkVersion', | ||
['webdriver:update', 'tslint', 'format'], 'tsc', 'built:copy', 'tsc:spec', done); | ||
}); | ||
gulp.task('default',['prepublish']); |
@@ -15,4 +15,2 @@ { | ||
"dependencies": { | ||
"@types/q": "^0.0.32", | ||
"@types/selenium-webdriver": "^3.0.0", | ||
"blocking-proxy": "^1.0.0", | ||
@@ -22,11 +20,9 @@ "browserstack": "^1.5.1", | ||
"glob": "^7.0.3", | ||
"jasmine": "2.8.0", | ||
"jasminewd2": "^2.1.0", | ||
"jasmine": "^3.3.1", | ||
"optimist": "~0.6.0", | ||
"q": "1.4.1", | ||
"saucelabs": "^1.5.0", | ||
"selenium-webdriver": "3.6.0", | ||
"selenium-webdriver": "^4.0.0-alpha.1", | ||
"source-map-support": "~0.4.0", | ||
"webdriver-js-extender": "2.1.0", | ||
"webdriver-manager": "^12.0.6" | ||
"webdriver-manager": "13.0.0-beta" | ||
}, | ||
@@ -37,7 +33,8 @@ "devDependencies": { | ||
"@types/glob": "^5.0.29", | ||
"@types/jasmine": "^2.5.47", | ||
"@types/jasminewd2": "^2.0.0", | ||
"@types/jasmine": "^3.3.0", | ||
"@types/loglevel": "^1.5.3", | ||
"@types/minimatch": "^2.0.28", | ||
"@types/minimist": "^1.1.28", | ||
"@types/optimist": "^0.0.29", | ||
"@types/yargs": "^12.0.1", | ||
"body-parser": "~1.15.2", | ||
@@ -49,6 +46,5 @@ "chai": "~3.5.0", | ||
"express": "~4.14.0", | ||
"gulp": "^3.9.1", | ||
"gulp": "^4.0.0", | ||
"gulp-clang-format": "1.0.23", | ||
"gulp-tslint": "^7.0.1", | ||
"jshint": "^2.9.2", | ||
"gulp-tslint": "^8.1.3", | ||
"lodash": "^4.5.1", | ||
@@ -58,7 +54,6 @@ "marked": "^0.3.3", | ||
"rimraf": "~2.5.3", | ||
"run-sequence": "^1.1.5", | ||
"semver": "^5.3.0", | ||
"tslint": "^4.1.1", | ||
"tslint-eslint-rules": "^3.1.0", | ||
"typescript": "^2.1.5", | ||
"tslint": "^5.11.0", | ||
"tslint-eslint-rules": "^5.4.0", | ||
"typescript": "^3.2.2", | ||
"vrsource-tslint-rules": "^4.0.1" | ||
@@ -83,2 +78,3 @@ }, | ||
"test": "node scripts/test.js", | ||
"tsc": "tsc", | ||
"website": "cd website && npm start", | ||
@@ -89,5 +85,5 @@ "compile_to_es5": "gulp compile_to_es5" | ||
"engines": { | ||
"node": ">=6.9.x" | ||
"node": ">=8.8.x" | ||
}, | ||
"version": "5.4.2" | ||
"version": "6.0.0-beta" | ||
} |
@@ -19,4 +19,5 @@ { | ||
"exampleTypescript", | ||
"spec/**/*" | ||
"spec/**/*", | ||
"typings" | ||
] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
942334
11
27
122
18942
7
1
+ Addedadm-zip@0.4.16(transitive)
+ Addedansi-regex@3.0.1(transitive)
+ Addedcamelcase@5.3.1(transitive)
+ Addedchownr@1.1.4(transitive)
+ Addedcliui@4.1.0(transitive)
+ Addedcode-point-at@1.1.0(transitive)
+ Addedcross-spawn@6.0.5(transitive)
+ Addeddecamelize@1.2.0(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedexeca@1.0.0(transitive)
+ Addedfind-up@3.0.0(transitive)
+ Addedfs-minipass@1.2.7(transitive)
+ Addedget-caller-file@1.0.3(transitive)
+ Addedget-stream@4.1.0(transitive)
+ Addedinvert-kv@2.0.0(transitive)
+ Addedis-fullwidth-code-point@1.0.02.0.0(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjasmine@3.99.0(transitive)
+ Addedjasmine-core@3.99.1(transitive)
+ Addedlcid@2.0.0(transitive)
+ Addedlocate-path@3.0.0(transitive)
+ Addedloglevel@1.9.1(transitive)
+ Addedmap-age-cleaner@0.1.3(transitive)
+ Addedmem@4.3.0(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addedminipass@2.9.0(transitive)
+ Addedminizlib@1.3.3(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addednice-try@1.0.5(transitive)
+ Addednpm-run-path@2.0.2(transitive)
+ Addednumber-is-nan@1.0.1(transitive)
+ Addedos-locale@3.1.0(transitive)
+ Addedp-defer@1.0.0(transitive)
+ Addedp-finally@1.0.0(transitive)
+ Addedp-is-promise@2.1.0(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-locate@3.0.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpath-exists@3.0.0(transitive)
+ Addedpath-key@2.0.1(transitive)
+ Addedpump@3.0.0(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedrequire-main-filename@1.0.1(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedselenium-webdriver@4.22.0(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedshebang-command@1.2.0(transitive)
+ Addedshebang-regex@1.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstring-width@1.0.22.1.1(transitive)
+ Addedstrip-ansi@4.0.0(transitive)
+ Addedstrip-eof@1.0.0(transitive)
+ Addedtar@4.4.19(transitive)
+ Addedtmp@0.2.3(transitive)
+ Addedwebdriver-manager@13.0.0-beta(transitive)
+ Addedwhich@1.3.1(transitive)
+ Addedwhich-module@2.0.1(transitive)
+ Addedwrap-ansi@2.1.0(transitive)
+ Addedws@8.17.1(transitive)
+ Addedy18n@4.0.3(transitive)
+ Addedyallist@3.1.1(transitive)
+ Addedyargs@12.0.5(transitive)
+ Addedyargs-parser@11.1.1(transitive)
- Removed@types/q@^0.0.32
- Removed@types/selenium-webdriver@^3.0.0
- Removedjasminewd2@^2.1.0
- Removedq@1.4.1
- Removed@types/q@0.0.32(transitive)
- Removedadm-zip@0.5.14(transitive)
- Removedarray-union@1.0.2(transitive)
- Removedarray-uniq@1.0.3(transitive)
- Removedarrify@1.0.1(transitive)
- Removeddel@2.2.2(transitive)
- Removedexit@0.1.2(transitive)
- Removedglobby@5.0.0(transitive)
- Removedini@1.3.8(transitive)
- Removedis-path-cwd@1.0.0(transitive)
- Removedis-path-in-cwd@1.0.1(transitive)
- Removedis-path-inside@1.0.1(transitive)
- Removedjasmine@2.8.0(transitive)
- Removedjasmine-core@2.8.0(transitive)
- Removedjasminewd2@2.2.0(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedpath-is-inside@1.0.2(transitive)
- Removedpify@2.3.0(transitive)
- Removedpinkie@2.0.4(transitive)
- Removedpinkie-promise@2.0.1(transitive)
- Removedq@1.4.1(transitive)
- Removedwebdriver-manager@12.1.9(transitive)
Updatedjasmine@^3.3.1