From 37b564a86713216d458be72bbca0db0cf1228849 Mon Sep 17 00:00:00 2001 From: Craig Nishina Date: Tue, 13 Nov 2018 12:23:54 -0800 Subject: [PATCH 1/4] chore(test): move error tests off of the control flow. - Leave node scripts/errorTest.js commented out since it has something to do with the control flow where the exit code is not set. Also the breakpointhook.js file has issues we will need to address (Error: Cannot find module). - Add TODO block for slowHttpAndTimeout tests. - Update spec/errorTest to use const, let over var and async/await. - Add SELENIUM_PROMISE_MANAGER flag to plugins tests (currently missing) - Turn on the rest of test suite prior to updating to selenium 4 (basicConf using blocking proxy, unit tests, dependency tests, and typing tests) - Remove spec/errorTest/error_spec.js. Committed in https://github.com/angular/protractor/commit/a13a2d323e10c9ced340b30f43399f5b503574cd#diff-0b3f10a17756d2a4773c4d716805edf8 but not used. --- scripts/test.js | 137 +++++++++--------- .../afterLaunchChangesExitCodeConf.js | 1 + spec/errorTest/baseCase/error_spec.js | 6 - spec/errorTest/baseCase/mocha_failure_spec.js | 14 +- .../baseCase/single_failure_spec1.js | 10 +- .../baseCase/single_failure_spec2.js | 10 +- .../baseCase/slow_http_and_timeout_spec.js | 30 ++-- spec/errorTest/baseCase/success_spec.js | 10 +- spec/errorTest/baseCase/timeout_spec.js | 6 +- spec/errorTest/browserStackAuthentication.js | 1 + spec/errorTest/debugMultiCapabilities.js | 1 + spec/errorTest/getMultiCapabilitiesConf.js | 1 + spec/errorTest/mochaFailureConf.js | 1 + spec/errorTest/multiFailureConf.js | 1 + spec/errorTest/pluginsFailingConf.js | 2 +- spec/errorTest/sauceLabsAuthentication.js | 1 + spec/errorTest/shardedFailureConf.js | 2 +- spec/errorTest/singleFailureConf.js | 1 + spec/errorTest/slowHttpAndTimeoutConf.js | 2 +- spec/errorTest/timeoutConf.js | 1 + spec/plugins/smokeConf.js | 1 + spec/plugins/specs/smoke_spec.js | 4 +- 22 files changed, 125 insertions(+), 118 deletions(-) delete mode 100644 spec/errorTest/baseCase/error_spec.js diff --git a/scripts/test.js b/scripts/test.js index 8fa8c7c65..68c594c8c 100755 --- a/scripts/test.js +++ b/scripts/test.js @@ -5,7 +5,7 @@ var Executor = require('./test/test_util').Executor; var passingTests = [ 'node built/cli.js spec/basicConf.js', - // 'node built/cli.js spec/basicConf.js --useBlockingProxy', + 'node built/cli.js spec/basicConf.js --useBlockingProxy', 'node built/cli.js spec/multiConf.js', 'node built/cli.js spec/altRootConf.js', 'node built/cli.js spec/inferRootConf.js', @@ -21,7 +21,7 @@ var passingTests = [ 'node built/cli.js spec/suitesConf.js --suite okmany', 'node built/cli.js spec/suitesConf.js --suite okspec', 'node built/cli.js spec/suitesConf.js --suite okmany,okspec', - // 'node built/cli.js spec/plugins/smokeConf.js', + 'node built/cli.js spec/plugins/smokeConf.js', 'node built/cli.js spec/plugins/multiPluginConf.js', 'node built/cli.js spec/plugins/jasminePostTestConf.js', 'node built/cli.js spec/plugins/mochaPostTestConf.js', @@ -47,15 +47,15 @@ var passingTests = [ // // Interactive Element Explorer tasks // 'node scripts/interactive_tests/interactive_test.js', // 'node scripts/interactive_tests/with_base_url.js', - // // Unit tests - // 'node node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=scripts/unit_test.json', - // // Dependency tests - // 'node node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=scripts/dependency_test.json', - // // Typings tests - // 'node spec/install/test.js' + // Unit tests + 'node node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=scripts/unit_test.json', + // Dependency tests + 'node node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=scripts/dependency_test.json', + // Typings tests + 'node spec/install/test.js' ]; -var executor = new Executor(); +const executor = new Executor(); passingTests.forEach(function(passing_test) { executor.addCommandlineTest(passing_test) @@ -67,64 +67,65 @@ passingTests.forEach(function(passing_test) { *************************/ // assert stacktrace shows line of failure -// executor.addCommandlineTest('node built/cli.js spec/errorTest/singleFailureConf.js') -// .expectExitCode(1) -// .expectErrors({ -// stackTrace: 'single_failure_spec1.js:5:32' -// }); - -// // assert timeout works -// executor.addCommandlineTest('node built/cli.js spec/errorTest/timeoutConf.js') -// .expectExitCode(1) -// .expectErrors({ -// message: 'Timeout - Async callback was not invoked within timeout ' + -// 'specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.' -// }) -// .expectTestDuration(0, 1000); - -// executor.addCommandlineTest('node built/cli.js spec/errorTest/afterLaunchChangesExitCodeConf.js') -// .expectExitCode(11) -// .expectErrors({ -// message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.' -// }); - -// executor.addCommandlineTest('node built/cli.js spec/errorTest/multiFailureConf.js') -// .expectExitCode(1) -// .expectErrors([{ -// message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', -// stacktrace: 'single_failure_spec1.js:5:32' -// }, { -// message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', -// stacktrace: 'single_failure_spec2.js:5:32' -// }]); - -// executor.addCommandlineTest('node built/cli.js spec/errorTest/shardedFailureConf.js') -// .expectExitCode(1) -// .expectErrors([{ -// message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', -// stacktrace: 'single_failure_spec1.js:5:32' -// }, { -// message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', -// stacktrace: 'single_failure_spec2.js:5:32' -// }]); - -// executor.addCommandlineTest('node built/cli.js spec/errorTest/mochaFailureConf.js') -// .expectExitCode(1) -// .expectErrors([{ -// message: 'expected \'My AngularJS App\' to equal \'INTENTIONALLY INCORRECT\'', -// stacktrace: 'mocha_failure_spec.js:11:20' -// }]); - -// executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf.js') -// .expectExitCode(1) -// .expectErrors([ -// {message: 'Expected true to be false'}, -// {message: 'from setup'}, -// {message: 'from postTest passing'}, -// {message: 'from postTest failing'}, -// {message: 'from teardown'} -// ]); - +executor.addCommandlineTest('node built/cli.js spec/errorTest/singleFailureConf.js') + .expectExitCode(1) + .expectErrors({ + stackTrace: 'single_failure_spec1.js:5:38' + }); + +// assert timeout works +executor.addCommandlineTest('node built/cli.js spec/errorTest/timeoutConf.js') + .expectExitCode(1) + .expectErrors({ + message: 'Timeout - Async callback was not invoked within timeout ' + + 'specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.' + }) + .expectTestDuration(0, 1000); + +executor.addCommandlineTest('node built/cli.js spec/errorTest/afterLaunchChangesExitCodeConf.js') + .expectExitCode(11) + .expectErrors({ + message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.' + }); + +executor.addCommandlineTest('node built/cli.js spec/errorTest/multiFailureConf.js') + .expectExitCode(1) + .expectErrors([{ + message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', + stacktrace: 'single_failure_spec1.js:5:32' + }, { + message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', + stacktrace: 'single_failure_spec2.js:5:32' + }]); + +executor.addCommandlineTest('node built/cli.js spec/errorTest/shardedFailureConf.js') + .expectExitCode(1) + .expectErrors([{ + message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', + stacktrace: 'single_failure_spec1.js:5:32' + }, { + message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', + stacktrace: 'single_failure_spec2.js:5:32' + }]); + +executor.addCommandlineTest('node built/cli.js spec/errorTest/mochaFailureConf.js') + .expectExitCode(1) + .expectErrors([{ + message: 'expected \'My AngularJS App\' to equal \'INTENTIONALLY INCORRECT\'', + stacktrace: 'mocha_failure_spec.js:11:20' + }]); + +executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf.js') + .expectExitCode(1) + .expectErrors([ + {message: 'Expected true to be false'}, + {message: 'from setup'}, + {message: 'from postTest passing'}, + {message: 'from postTest failing'}, + {message: 'from teardown'} + ]); + +// TODO(selenium4): turn these on when we figure out the correct error message handling. // executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeoutConf.js') // .expectExitCode(1) // .expectErrors([ @@ -135,6 +136,7 @@ passingTests.forEach(function(passing_test) { // '*}'} // ]); +// TODO(selenium4): turn these on when we figure out the correct error message handling. // executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeoutConf.js ' + // '--untrackOutstandingTimeouts true') // .expectExitCode(1) @@ -144,6 +146,7 @@ passingTests.forEach(function(passing_test) { // 'Locator: by.binding\\(\\"slowAngularTimeoutStatus\\"\\)$'} // ]); +// TODO(selenium4): turn these on when we figure out the correct error message handling. // executor.addCommandlineTest('node built/cli.js spec/angular2TimeoutConf.js') // .expectExitCode(1) // .expectErrors([ diff --git a/spec/errorTest/afterLaunchChangesExitCodeConf.js b/spec/errorTest/afterLaunchChangesExitCodeConf.js index 049140fc7..1d8b41b8d 100644 --- a/spec/errorTest/afterLaunchChangesExitCodeConf.js +++ b/spec/errorTest/afterLaunchChangesExitCodeConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/baseCase/error_spec.js b/spec/errorTest/baseCase/error_spec.js deleted file mode 100644 index 2b39ccaab..000000000 --- a/spec/errorTest/baseCase/error_spec.js +++ /dev/null @@ -1,6 +0,0 @@ -describe('finding an element that does not exist', function() { - it('should throw an error', function() { - browser.get('index.html'); - element(by.binding('INVALID')); // greeting - }); -}); diff --git a/spec/errorTest/baseCase/mocha_failure_spec.js b/spec/errorTest/baseCase/mocha_failure_spec.js index 6dcfe5586..023968acb 100644 --- a/spec/errorTest/baseCase/mocha_failure_spec.js +++ b/spec/errorTest/baseCase/mocha_failure_spec.js @@ -1,13 +1,13 @@ // Use the external Chai As Promised to deal with resolving promises in // expectations. -var chai = require('chai'); -var chaiAsPromised = require('chai-as-promised'); +const chai = require('chai'); +const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); -var expect = chai.expect; +const expect = chai.expect; -describe('protractor library', function() { - it('should fail', function() { - browser.get('index.html'); - expect(browser.getTitle()).to.eventually.equal('INTENTIONALLY INCORRECT'); +describe('protractor library', () => { + it('should fail', async () => { + await browser.get('index.html'); + expect(await browser.getTitle()).to.equal('INTENTIONALLY INCORRECT'); }); }); diff --git a/spec/errorTest/baseCase/single_failure_spec1.js b/spec/errorTest/baseCase/single_failure_spec1.js index c94068415..f2fb4cd15 100644 --- a/spec/errorTest/baseCase/single_failure_spec1.js +++ b/spec/errorTest/baseCase/single_failure_spec1.js @@ -1,7 +1,7 @@ -describe('single failure spec1', function() { - it('should fail expectation', function() { - browser.get('index.html'); - var greeting = element(by.binding('greeting')); - expect(greeting.getText()).toEqual('INTENTIONALLY INCORRECT'); +describe('single failure spec1', () => { + it('should fail expectation', async () => { + await browser.get('index.html'); + const greeting = element(by.binding('greeting')); + expect(await greeting.getText()).toEqual('INTENTIONALLY INCORRECT'); }); }); diff --git a/spec/errorTest/baseCase/single_failure_spec2.js b/spec/errorTest/baseCase/single_failure_spec2.js index c39404110..d3110349e 100644 --- a/spec/errorTest/baseCase/single_failure_spec2.js +++ b/spec/errorTest/baseCase/single_failure_spec2.js @@ -1,7 +1,7 @@ -describe('single failure spec2', function() { - it('should fail expectation', function() { - browser.get('index.html'); - var greeting = element(by.binding('greeting')); - expect(greeting.getText()).toEqual('INTENTIONALLY INCORRECT'); +describe('single failure spec2', () => { + it('should fail expectation', async () => { + await browser.get('index.html'); + const greeting = element(by.binding('greeting')); + expect(await greeting.getText()).toEqual('INTENTIONALLY INCORRECT'); }); }); diff --git a/spec/errorTest/baseCase/slow_http_and_timeout_spec.js b/spec/errorTest/baseCase/slow_http_and_timeout_spec.js index 8efcb9bc4..07d93642d 100644 --- a/spec/errorTest/baseCase/slow_http_and_timeout_spec.js +++ b/spec/errorTest/baseCase/slow_http_and_timeout_spec.js @@ -1,27 +1,27 @@ -describe('slow asynchronous events', function() { - beforeEach(function() { - browser.get('index.html#/async'); +describe('slow asynchronous events', () => { + beforeEach(async () => { + await browser.get('index.html#/async'); }); - it('waits for http calls', function() { - var status = element(by.binding('slowHttpStatus')); - var button = element(by.css('[ng-click="slowHttp()"]')); + it('waits for http calls', async () => { + const status = element(by.binding('slowHttpStatus')); + const button = element(by.css('[ng-click="slowHttp()"]')); - expect(status.getText()).toEqual('not started'); + expect(await status.getText()).toEqual('not started'); - button.click(); + await button.click(); - expect(status.getText()).toEqual('done'); + expect(await status.getText()).toEqual('done'); }); - it('waits for $timeout', function() { - var status = element(by.binding('slowAngularTimeoutStatus')); - var button = element(by.css('[ng-click="slowAngularTimeout()"]')); + it('waits for $timeout', async () => { + const status = element(by.binding('slowAngularTimeoutStatus')); + const button = element(by.css('[ng-click="slowAngularTimeout()"]')); - expect(status.getText()).toEqual('not started'); + expect(await status.getText()).toEqual('not started'); - button.click(); + await button.click(); - expect(status.getText()).toEqual('done'); + expect(await status.getText()).toEqual('done'); }); }); diff --git a/spec/errorTest/baseCase/success_spec.js b/spec/errorTest/baseCase/success_spec.js index e39caa3d6..0a9609b2e 100644 --- a/spec/errorTest/baseCase/success_spec.js +++ b/spec/errorTest/baseCase/success_spec.js @@ -1,7 +1,7 @@ -describe('success spec', function() { - it('should pass', function() { - browser.get('index.html'); - var greeting = element(by.binding('greeting')); - expect(greeting.getText()).toEqual('Hiya'); +describe('success spec', () => { + it('should pass', async () => { + await browser.get('index.html'); + const greeting = element(by.binding('greeting')); + expect(await greeting.getText()).toEqual('Hiya'); }); }); diff --git a/spec/errorTest/baseCase/timeout_spec.js b/spec/errorTest/baseCase/timeout_spec.js index 5387a6a5c..a489b9675 100644 --- a/spec/errorTest/baseCase/timeout_spec.js +++ b/spec/errorTest/baseCase/timeout_spec.js @@ -1,5 +1,5 @@ -describe('timeout spec', function() { - it('should timeout due to jasmine spec limit', function() { - browser.get('index.html#/form'); +describe('timeout spec', () => { + it('should timeout due to jasmine spec limit', async () => { + await browser.get('index.html#/form'); }, 1); }); diff --git a/spec/errorTest/browserStackAuthentication.js b/spec/errorTest/browserStackAuthentication.js index 6e954ca56..98c1a9d1d 100644 --- a/spec/errorTest/browserStackAuthentication.js +++ b/spec/errorTest/browserStackAuthentication.js @@ -3,6 +3,7 @@ var env = require('../environment.js'); exports.config = { browserstackUser: 'foobar', browserstackKey: 'foobar', + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/debugMultiCapabilities.js b/spec/errorTest/debugMultiCapabilities.js index 188f1e39d..f5ddaf9c8 100644 --- a/spec/errorTest/debugMultiCapabilities.js +++ b/spec/errorTest/debugMultiCapabilities.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', debug: true, specs: [ diff --git a/spec/errorTest/getMultiCapabilitiesConf.js b/spec/errorTest/getMultiCapabilitiesConf.js index 587a0041b..8d69e644f 100644 --- a/spec/errorTest/getMultiCapabilitiesConf.js +++ b/spec/errorTest/getMultiCapabilitiesConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, // Spec patterns are relative to this directory. specs: [ diff --git a/spec/errorTest/mochaFailureConf.js b/spec/errorTest/mochaFailureConf.js index 5e726330f..af35e6f67 100644 --- a/spec/errorTest/mochaFailureConf.js +++ b/spec/errorTest/mochaFailureConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, specs: [ 'baseCase/mocha_failure_spec.js' diff --git a/spec/errorTest/multiFailureConf.js b/spec/errorTest/multiFailureConf.js index ba06b506b..589a7bb44 100644 --- a/spec/errorTest/multiFailureConf.js +++ b/spec/errorTest/multiFailureConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/pluginsFailingConf.js b/spec/errorTest/pluginsFailingConf.js index ecb6c88e6..9d95d507b 100644 --- a/spec/errorTest/pluginsFailingConf.js +++ b/spec/errorTest/pluginsFailingConf.js @@ -2,8 +2,8 @@ var env = require('../environment.js'); // A small suite to make sure the full functionality of plugins work exports.config = { - // seleniumAddress: env.seleniumAddress, mockSelenium: true, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/sauceLabsAuthentication.js b/spec/errorTest/sauceLabsAuthentication.js index 35f2180f8..b09fda6b6 100644 --- a/spec/errorTest/sauceLabsAuthentication.js +++ b/spec/errorTest/sauceLabsAuthentication.js @@ -3,6 +3,7 @@ var env = require('../environment.js'); exports.config = { sauceUser: 'foobar', sauceKey: 'foobar', + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/shardedFailureConf.js b/spec/errorTest/shardedFailureConf.js index a36d509dc..a13d53e87 100644 --- a/spec/errorTest/shardedFailureConf.js +++ b/spec/errorTest/shardedFailureConf.js @@ -2,7 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, - + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', specs: [ diff --git a/spec/errorTest/singleFailureConf.js b/spec/errorTest/singleFailureConf.js index 5c8a930ab..7c168c63c 100644 --- a/spec/errorTest/singleFailureConf.js +++ b/spec/errorTest/singleFailureConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/errorTest/slowHttpAndTimeoutConf.js b/spec/errorTest/slowHttpAndTimeoutConf.js index f81811758..84e0603a7 100644 --- a/spec/errorTest/slowHttpAndTimeoutConf.js +++ b/spec/errorTest/slowHttpAndTimeoutConf.js @@ -2,7 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, - + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', specs: [ diff --git a/spec/errorTest/timeoutConf.js b/spec/errorTest/timeoutConf.js index 213432cba..25a2a2bd4 100644 --- a/spec/errorTest/timeoutConf.js +++ b/spec/errorTest/timeoutConf.js @@ -2,6 +2,7 @@ var env = require('../environment.js'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/plugins/smokeConf.js b/spec/plugins/smokeConf.js index 44cbc5ef0..a1d2dd21d 100644 --- a/spec/plugins/smokeConf.js +++ b/spec/plugins/smokeConf.js @@ -4,6 +4,7 @@ var env = require('../environment.js'); // Tests the (potential) edge case of exactly one plugin being used exports.config = { mockSelenium: true, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/plugins/specs/smoke_spec.js b/spec/plugins/specs/smoke_spec.js index bc7f67f1b..2dafffaf0 100644 --- a/spec/plugins/specs/smoke_spec.js +++ b/spec/plugins/specs/smoke_spec.js @@ -1,5 +1,5 @@ -describe('check if plugin setup ran', function() { - it('should have set protractor.__BASIC_PLUGIN_RAN_*', function() { +describe('check if plugin setup ran', () => { + it('should have set protractor.__BASIC_PLUGIN_RAN_*', () => { expect(protractor.__BASIC_PLUGIN_RAN_SETUP).toBe(true); expect(protractor.__BASIC_PLUGIN_RAN_ON_PREPARE).toBe(true); }); From 6684f0f7a98199db96a8745b793897a9c8ed8a9c Mon Sep 17 00:00:00 2001 From: Craig Nishina Date: Mon, 19 Nov 2018 18:15:50 -0800 Subject: [PATCH 2/4] epic refactor! things are broken! such everywhere! much epic! - update browser.get method because of control flow.... and then it became whack-a-mole for q promises, wdpromises...fix one, two more type errors pop up. - remove q from protractor!!! huzzah. things are probably broken. (i'll have to do another review. i might not have done the debugger file) - will slowly add tests back into this test and pass the test suite. --- lib/browser.ts | 267 +++++++++----------- lib/debugger.ts | 2 - lib/index.ts | 2 +- lib/launcher.ts | 336 ++++++++++++------------- lib/plugins.ts | 68 ++--- lib/ptor.ts | 4 +- lib/runner.ts | 33 ++- lib/taskRunner.ts | 110 ++++---- lib/util.ts | 18 +- spec/basic/expected_conditions_spec.js | 2 +- spec/basic/handling_spec.js | 9 + spec/basicConf.js | 3 +- 12 files changed, 391 insertions(+), 463 deletions(-) diff --git a/lib/browser.ts b/lib/browser.ts index 1966487c9..5381061c8 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -196,7 +196,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @param {string|webdriver.promise.Promise} valuePromise The new selector. * @returns A promise that resolves with the value of the selector. */ - async angularAppRoot(valuePromise: string|wdpromise.Promise = null): Promise { + async angularAppRoot(valuePromise: string|Promise = null): Promise { if (valuePromise != null) { const value = await valuePromise; this.internalRootEl = value; @@ -255,7 +255,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * * @type {webdriver.promise.Promise.} */ - ready: wdpromise.Promise; + ready: Promise; /* * Set by the runner. @@ -318,9 +318,8 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { [key: string]: any; constructor( - webdriverInstance: WebDriver, opt_baseUrl?: string, - opt_rootElement?: string|wdpromise.Promise, opt_untrackOutstandingTimeouts?: boolean, - opt_blockingProxyUrl?: string) { + webdriverInstance: WebDriver, opt_baseUrl?: string, opt_rootElement?: string|Promise, + opt_untrackOutstandingTimeouts?: boolean, opt_blockingProxyUrl?: string) { super(); // These functions should delegate to the webdriver instance, but should // wait for Angular to sync up before performing the action. This does not @@ -411,8 +410,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * Call waitForAngularEnabled() without passing a value to read the current * state without changing it. */ - async waitForAngularEnabled(enabledPromise: boolean|wdpromise.Promise = null): - Promise { + async waitForAngularEnabled(enabledPromise: boolean|Promise = null): Promise { if (enabledPromise != null) { const enabled = await enabledPromise; if (this.bpClient) { @@ -431,10 +429,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * * Set by the runner. * - * @returns {webdriver.promise.Promise} A promise which resolves to the + * @returns {Promise} A promise which resolves to the * capabilities object. */ - getProcessedConfig(): wdpromise.Promise { + getProcessedConfig(): Promise { return null; } @@ -510,10 +508,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * }); * browser.restart(); * - * @returns {webdriver.promise.Promise} A promise resolving to the restarted + * @returns {Promise} A promise resolving to the restarted * browser */ - restart(): wdpromise.Promise { + restart(): Promise { return; } @@ -559,21 +557,22 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @param {!(string|Function)} script The script to execute. * @param {string} description A description of the command for debugging. * @param {...*} var_args The arguments to pass to the script. - * @returns {!webdriver.promise.Promise.} A promise that will resolve to + * @returns {!Promise} A promise that will resolve to * the scripts return value. * @template T */ public executeScriptWithDescription( - script: string|Function, description: string, ...scriptArgs: any[]): wdpromise.Promise { + script: string|Function, description: string, ...scriptArgs: any[]): Promise { if (typeof script === 'function') { script = 'return (' + script + ').apply(null, arguments);'; } + // TODO(selenium4): Update driver.execute for selenium4. return this.driver.schedule( - new Command(CommandName.EXECUTE_SCRIPT) - .setParameter('script', script) - .setParameter('args', scriptArgs), - description); + new Command(CommandName.EXECUTE_SCRIPT) + .setParameter('script', script) + .setParameter('args', scriptArgs), + description) as Promise; } /** @@ -584,7 +583,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @param {!(string|Function)} script The script to execute. * @param {string} description A description for debugging purposes. * @param {...*} var_args The arguments to pass to the script. - * @returns {!webdriver.promise.Promise.} A promise that will resolve to + * @returns {!Promise} A promise that will resolve to * the * scripts return value. * @template T @@ -619,13 +618,13 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { } let runWaitForAngularScript = async(): Promise => { - if (this.plugins_.skipAngularStability() || this.bpClient) { - return null; - } else { - let rootEl = await this.angularAppRoot(); - return this.executeAsyncScript_( - clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); - } + // if (this.plugins_.skipAngularStability() || this.bpClient) { + // return null; + // } else { + let rootEl = await this.angularAppRoot(); + return this.executeAsyncScript_( + clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); + // } }; try { @@ -714,7 +713,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @returns {!webdriver.promise.Promise} A promise that will be resolved to an * array of the located {@link webdriver.WebElement}s. */ - findElements(locator: Locator): wdpromise.Promise { + findElements(locator: Locator): Promise { return this.element.all(locator).getWebElements(); } @@ -724,7 +723,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @returns {!webdriver.promise.Promise} A promise that will resolve to whether * the element is present on the page. */ - isElementPresent(locatorOrElement: Locator|WebElement|ElementFinder): wdpromise.Promise { + isElementPresent(locatorOrElement: Locator|WebElement|ElementFinder): Promise { let element: ElementFinder; if (locatorOrElement instanceof ElementFinder) { element = locatorOrElement; @@ -831,125 +830,97 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { return 'Protractor.get(' + destination + ') - ' + str; }; - return this.driver.controlFlow() - .execute(() => { - return wdpromise.when(null); - }) - .then(() => { - if (this.bpClient) { - return this.driver.controlFlow().execute(() => { - return this.bpClient.setWaitEnabled(false); + if (this.bpClient) { + await this.bpClient.setWaitEnabled(false); + } + // Go to reset url + await this.driver.get(this.resetUrl); + + // Set defer label and navigate + await this.executeScriptWithDescription( + 'window.name = "' + DEFER_LABEL + '" + window.name;' + + 'window.location.replace("' + destination + '");', + msg('reset url')); + + // We need to make sure the new url has loaded before + // we try to execute any asynchronous scripts. + this.driver.wait(() => { + return this.executeScriptWithDescription('return window.location.href;', msg('get url')) + .then( + (url: any) => { + return url !== this.resetUrl; + }, + (err: IError) => { + if (err.code == 13 || err.name === 'JavascriptError') { + // Ignore the error, and continue trying. This is + // because IE driver sometimes (~1%) will throw an + // unknown error from this execution. See + // https://github.com/angular/protractor/issues/841 + // This shouldn't mask errors because it will fail + // with the timeout anyway. + return false; + } else { + throw err; + } + }); + }, timeout, 'waiting for page to load for ' + timeout + 'ms'); + + // Run Plugins + // await this.plugins_.onPageLoad(this); + + let angularVersion: number; + try { + // Make sure the page is an Angular page. + const angularTestResult: {ver: number, message: string} = await this.executeAsyncScript_( + clientSideScripts.testForAngular, msg('test for angular'), Math.floor(timeout / 1000), + this.ng12Hybrid); + angularVersion = angularTestResult.ver; + + if (!angularVersion) { + let message = angularTestResult.message; + logger.error(`Could not find Angular on page ${destination} : ${message}`); + throw new Error( + `Angular could not be found on the page ${destination}. ` + + `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`); + } + } catch (err) { + throw new Error('Error while running testForAngular: ' + err.message); + } + + // Load Angular Mocks + if (angularVersion === 1) { + // At this point, Angular will pause for us until angular.resumeBootstrap is called. + let moduleNames: string[] = []; + for (const {name, script, args} of this.mockModules_) { + moduleNames.push(name); + let executeScriptArgs = [script, msg('add mock module ' + name), ...args]; + await this.executeScriptWithDescription.apply(this, executeScriptArgs) + .then(null, (err: Error) => { + throw new Error('Error while running module script ' + name + ': ' + err.message); }); - } - }) - .then(() => { - // Go to reset url - return this.driver.get(this.resetUrl); - }) - .then(() => { - // Set defer label and navigate - return 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(() => { - return this.executeScriptWithDescription('return window.location.href;', msg('get url')) - .then( - (url: any) => { - return url !== this.resetUrl; - }, - (err: IError) => { - if (err.code == 13 || err.name === 'JavascriptError') { - // Ignore the error, and continue trying. This is - // because IE driver sometimes (~1%) will throw an - // unknown error from this execution. See - // https://github.com/angular/protractor/issues/841 - // This shouldn't mask errors because it will fail - // with the timeout anyway. - return false; - } else { - throw err; - } - }); - }, 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: {ver: number, message: string}) => { - let angularVersion = angularTestResult.ver; - if (!angularVersion) { - let message = angularTestResult.message; - logger.error(`Could not find Angular on page ${destination} : ${message}`); - throw new Error( - `Angular could not be found on the page ${destination}. ` + - `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`); - } - return angularVersion; - }, - (err: Error) => { - throw new Error('Error while running testForAngular: ' + err.message); - }); - }) - .then((angularVersion) => { - // Load Angular Mocks - if (angularVersion === 1) { - // At this point, Angular will pause for us until angular.resumeBootstrap is called. - let moduleNames: string[] = []; - let modulePromise: wdpromise.Promise = wdpromise.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) - .then(null, (err: Error) => { - 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)); - } else { - // TODO: support mock modules in Angular2. For now, error if someone - // has tried to use one. - if (this.mockModules_.length > 1) { - throw 'Trying to load mock modules on an Angular v2+ app is not yet supported.'; - } - } - }) - .then(() => { - // Reset bpClient sync - if (this.bpClient) { - return this.bpClient.setWaitEnabled(!this.internalIgnoreSynchronization); - } - }) - .then(() => { - // Run Plugins - if (!this.ignoreSynchronization) { - return this.plugins_.onPageStable(this); - } - }) - .then(() => null); + } + + await this.executeScriptWithDescription( + 'window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' + + 'angular.resumeBootstrap(arguments[0]);', + msg('resume bootstrap'), moduleNames); + } else { + // TODO: support mock modules in Angular2. For now, error if someone + // has tried to use one. + if (this.mockModules_.length > 1) { + throw 'Trying to load mock modules on an Angular v2+ app is not yet supported.'; + } + } + + // Reset bpClient sync + if (this.bpClient) { + await this.bpClient.setWaitEnabled(!this.internalIgnoreSynchronization); + } + + // Run Plugins + // await this.plugins_.onPageStable(this); } /** @@ -995,10 +966,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * .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 { + setLocation(url: string): Promise { return this.waitForAngular() .then(() => this.angularAppRoot()) .then( @@ -1028,7 +999,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @returns {webdriver.promise.Promise} The current absolute url from * AngularJS. */ - getLocationAbsUrl(): wdpromise.Promise { + getLocationAbsUrl(): Promise { logger.warn( '`browser.getLocationAbsUrl()` is deprecated, please use `browser.getCurrentUrl` instead.'); return this.waitForAngular() diff --git a/lib/debugger.ts b/lib/debugger.ts index b22cfa0dd..9a51758d3 100644 --- a/lib/debugger.ts +++ b/lib/debugger.ts @@ -6,13 +6,11 @@ import {ProtractorBrowser} from './browser'; import {Locator} from './locators'; import {Logger} from './logger'; import {Ptor} from './ptor'; -import * as helper from './util'; let breakpointHook = require('./breakpointhook.js'); declare var global: any; declare var process: any; -let logger = new Logger('protractor'); export class DebugHelper { /** diff --git a/lib/index.ts b/lib/index.ts index f1a0cae5f..311d714a2 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,7 @@ import {ElementHelper, ProtractorBrowser} from './browser'; import {ElementArrayFinder, ElementFinder} from './element'; import {ProtractorExpectedConditions} from './expectedConditions'; -import {Locator, ProtractorBy} from './locators'; +import {ProtractorBy} from './locators'; import {PluginConfig, ProtractorPlugin} from './plugins'; import {Ptor} from './ptor'; diff --git a/lib/launcher.ts b/lib/launcher.ts index 6a92e20ea..070745518 100644 --- a/lib/launcher.ts +++ b/lib/launcher.ts @@ -3,7 +3,6 @@ * input configuration and launching test runners. */ import * as fs from 'fs'; -import * as q from 'q'; import {Config} from './config'; import {ConfigParser} from './configParser'; @@ -93,7 +92,7 @@ let taskResults_ = new TaskResults(); * @param {string=} configFile * @param {Object=} additionalConfig */ -let initFn = function(configFile: string, additionalConfig: Config) { +let initFn = async function(configFile: string, additionalConfig: Config) { let configParser = new ConfigParser(); if (configFile) { configParser.addFileConfig(configFile); @@ -108,197 +107,174 @@ let initFn = function(configFile: string, additionalConfig: Config) { logger.debug('Your base url for tests is ' + config.baseUrl); // Run beforeLaunch - helper.runFilenameOrFn_(config.configDir, config.beforeLaunch) - .then(() => { + await helper.runFilenameOrFn_(config.configDir, config.beforeLaunch).then(async () => { + // 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. + const waitMultiConfig = await config.getMultiCapabilities(); + config.multiCapabilities = waitMultiConfig; + config.capabilities = null; + } - return q - .Promise((resolve: Function, reject: Function) => { - // 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); - }); - } else { - resolve(); - } - }) - .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'); + // 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'}]; + } + + // 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]; + } + config.framework = 'explorer'; + + let runner = new Runner(config); + return runner.run().then( + (exitCode: number) => { + process.exit(exitCode); + }, + (err: Error) => { + logger.error(err); + process.exit(1); + }); + } + + // 4) Run tests. + let scheduler = new TaskScheduler(config); + + process.on('uncaughtException', (exc: (Error|string)) => { + let e = (exc instanceof Error) ? exc : new Error(exc); + if (config.ignoreUncaughtExceptions) { + // This can be a sign of a bug in the test framework, that it may + // not be handling WebDriver errors properly. However, we don't + // want these errors to prevent running the tests. + logger.warn('Ignoring uncaught error ' + exc); + return; + } + + let errorCode = ErrorHandler.parseError(e); + if (errorCode) { + let protractorError = e as ProtractorError; + ProtractorError.log(logger, errorCode, protractorError.message, protractorError.stack); + process.exit(errorCode); + } else { + logger.error(e.message); + logger.error(e.stack); + process.exit(ProtractorError.CODE); + } + }); + + process.on('exit', (code: number) => { + if (code) { + logger.error('Process exited with error code ' + code); + } else if (scheduler.numTasksOutstanding() > 0) { + logger.error( + 'BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining'); + process.exit(RUNNERS_FAILED_EXIT_CODE); + } + }); + + // Run afterlaunch and exit + let cleanUpAndExit = (exitCode: number) => { + return helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]) + .then( + (returned) => { + if (typeof returned === 'number') { + process.exit(returned); } else { - // Use capabilities if multiCapabilities is empty. - config.multiCapabilities = [config.capabilities]; + process.exit(exitCode); } - } 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]; - } - config.framework = 'explorer'; - - let runner = new Runner(config); - return runner.run().then( - (exitCode: number) => { - process.exit(exitCode); }, (err: Error) => { - logger.error(err); + logger.error('Error:', err); process.exit(1); }); - } - }) - .then(() => { - // 4) Run tests. - let scheduler = new TaskScheduler(config); + }; - process.on('uncaughtException', (exc: (Error|string)) => { - let e = (exc instanceof Error) ? exc : new Error(exc); - if (config.ignoreUncaughtExceptions) { - // This can be a sign of a bug in the test framework, that it may - // not be handling WebDriver errors properly. However, we don't - // want these errors to prevent running the tests. - logger.warn('Ignoring uncaught error ' + exc); - return; - } - - let errorCode = ErrorHandler.parseError(e); - if (errorCode) { - let protractorError = e as ProtractorError; - ProtractorError.log(logger, errorCode, protractorError.message, protractorError.stack); - process.exit(errorCode); - } else { - logger.error(e.message); - logger.error(e.stack); - process.exit(ProtractorError.CODE); - } - }); - - process.on('exit', (code: number) => { - if (code) { - logger.error('Process exited with error code ' + code); - } else if (scheduler.numTasksOutstanding() > 0) { - logger.error( - 'BUG: launcher exited with ' + scheduler.numTasksOutstanding() + - ' tasks remaining'); - process.exit(RUNNERS_FAILED_EXIT_CODE); - } - }); - - // Run afterlaunch and exit - let cleanUpAndExit = (exitCode: number) => { - return helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]) - .then( - (returned) => { - if (typeof returned === 'number') { - process.exit(returned); - } else { - process.exit(exitCode); - } - }, - (err: Error) => { - logger.error('Error:', err); - process.exit(1); - }); - }; + let totalTasks = scheduler.numTasksOutstanding(); + let forkProcess = false; + if (totalTasks > 1) { // Start new processes only if there are >1 tasks. + forkProcess = true; + if (config.debug) { + throw new ConfigError( + logger, 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding'); + } + } - let totalTasks = scheduler.numTasksOutstanding(); - let forkProcess = false; - if (totalTasks > 1) { // Start new processes only if there are >1 tasks. - forkProcess = true; - if (config.debug) { - throw new ConfigError( - logger, 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding'); - } + const createNextTaskRunner = () => { + return new Promise(resolve => { + let task = scheduler.nextTask(); + if (task) { + let taskRunner = new 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); + } + taskResults_.add(result); + task.done(); + createNextTaskRunner(); + // If all tasks are finished + if (scheduler.numTasksOutstanding() === 0) { + resolve(); + } + logger.info( + scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); + }) + .catch((err: Error) => { + logger.error('Error:', (err as any).stack || err.message || err); + cleanUpAndExit(RUNNERS_FAILED_EXIT_CODE); + }); } + }); + }; - let deferred = q.defer(); // Resolved when all tasks are completed - let createNextTaskRunner = () => { - let task = scheduler.nextTask(); - if (task) { - let taskRunner = new 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); - } - taskResults_.add(result); - task.done(); - createNextTaskRunner(); - // If all tasks are finished - if (scheduler.numTasksOutstanding() === 0) { - deferred.resolve(); - } - logger.info( - scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); - }) - .catch((err: Error) => { - logger.error('Error:', (err as any).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(); - } - logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver'); + for (let i = 0; i < scheduler.maxConcurrentTasks(); ++i) { + await createNextTaskRunner(); + } + logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver'); + + // By now all runners have completed. + // Save results if desired + if (config.resultJsonOutputFile) { + taskResults_.saveResults(config.resultJsonOutputFile); + } - // 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; + } + await cleanUpAndExit(exitCode); + // 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. - 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(); + }); }; export let init = initFn; diff --git a/lib/plugins.ts b/lib/plugins.ts index 1eaf88b1d..062249e8a 100644 --- a/lib/plugins.ts +++ b/lib/plugins.ts @@ -1,19 +1,12 @@ -import * as q from 'q'; import * as webdriver from 'selenium-webdriver'; import {ProtractorBrowser} from './browser'; import {Config} from './config'; import {ConfigParser} from './configParser'; import {Logger} from './logger'; -import {protractor} from './ptor'; let logger = new Logger('plugins'); -export enum PromiseType { - Q, - WEBDRIVER -} - export interface PluginConfig { path?: string; package?: string; @@ -420,15 +413,15 @@ export class Plugins { /** * @see docs/plugins.md#writing-plugins for information on these functions */ - setup = this.pluginFunFactory('setup', PromiseType.Q); - onPrepare = this.pluginFunFactory('onPrepare', PromiseType.Q); - teardown = this.pluginFunFactory('teardown', PromiseType.Q); - postResults = this.pluginFunFactory('postResults', PromiseType.Q); - postTest = this.pluginFunFactory('postTest', PromiseType.Q); - onPageLoad = this.pluginFunFactory('onPageLoad', PromiseType.WEBDRIVER); - onPageStable = this.pluginFunFactory('onPageStable', PromiseType.WEBDRIVER); - waitForPromise = this.pluginFunFactory('waitForPromise', PromiseType.WEBDRIVER); - waitForCondition = this.pluginFunFactory('waitForCondition', PromiseType.WEBDRIVER, true); + setup = this.pluginFunFactory('setup'); + onPrepare = this.pluginFunFactory('onPrepare'); + teardown = this.pluginFunFactory('teardown'); + postResults = this.pluginFunFactory('postResults'); + postTest = this.pluginFunFactory('postTest'); + onPageLoad = this.pluginFunFactory('onPageLoad'); + onPageStable = this.pluginFunFactory('onPageStable'); + waitForPromise = this.pluginFunFactory('waitForPromise'); + waitForCondition = this.pluginFunFactory('waitForCondition', true); /** * Calls a function from a plugin safely. If the plugin's function throws an @@ -439,18 +432,15 @@ export class Plugins { * @param {Object} pluginObj The plugin object containing the function to be run * @param {string} funName The name of the function we want to run * @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: ProtractorPlugin, funName: string, args: any[], promiseType: PromiseType, - failReturnVal: any): q.Promise|Promise|webdriver.promise.Promise { - const resolver = (done: (result: any) => void) => { + pluginObj: ProtractorPlugin, funName: string, args: any[], failReturnVal: any): Promise { + const resolver = async (done: (result: any) => void) => { const logError = (e: any) => { if (this.resultsReported) { this.printPluginResults([{ @@ -468,47 +458,33 @@ export class Plugins { done(failReturnVal); }; try { - const result = (pluginObj as any)[funName].apply(pluginObj, args); - if (webdriver.promise.isPromise(result)) { - (result as PromiseLike).then(done, logError); - } else { - done(result); - } + const result = await(pluginObj as any)[funName].apply(pluginObj, args); + done(result); } catch (e) { logError(e); } }; - if (promiseType == PromiseType.Q) { - return q.Promise(resolver); - } else if (protractor.browser.controlFlowIsEnabled()) { - return new webdriver.promise.Promise(resolver); - } else { - return new Promise(resolver); - } + return new Promise(resolver); } /** * 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 * * @return The handler */ - private pluginFunFactory(funName: string, promiseType: PromiseType.Q, failReturnVal?: boolean): - (...args: any[]) => q.Promise; - private pluginFunFactory( - funName: string, promiseType: PromiseType.WEBDRIVER, - failReturnVal?: boolean): (...args: any[]) => webdriver.promise.Promise; - private pluginFunFactory(funName: string, promiseType: PromiseType, failReturnVal?: boolean) { + private pluginFunFactory(funName: string, failReturnVal?: boolean): + (...args: any[]) => Promise; + private pluginFunFactory(funName: string, failReturnVal?: boolean): + (...args: any[]) => webdriver.promise.Promise; + private pluginFunFactory(funName: string, failReturnVal?: boolean) { return (...args: any[]) => { const promises = this.pluginObjs.filter(pluginObj => typeof(pluginObj as any)[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); }; } } diff --git a/lib/ptor.ts b/lib/ptor.ts index f8c7af88b..801350c90 100644 --- a/lib/ptor.ts +++ b/lib/ptor.ts @@ -12,10 +12,10 @@ import {ProtractorBy} from './locators'; export class Ptor { // Variables tied to the global namespace. browser: ProtractorBrowser; - $ = function(search: string): ElementFinder { + $ = function(_: string): ElementFinder { return null; }; - $$ = function(search: string): ElementArrayFinder { + $$ = function(_: string): ElementArrayFinder { return null; }; element: ElementHelper; diff --git a/lib/runner.ts b/lib/runner.ts index e5a4144e8..7ad43304a 100644 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -1,5 +1,4 @@ import {EventEmitter} from 'events'; -import * as q from 'q'; import {promise as wdpromise, Session} from 'selenium-webdriver'; import * as util from 'util'; @@ -34,7 +33,7 @@ export class Runner extends EventEmitter { driverprovider_: DriverProvider; o: any; plugins_: Plugins; - restartPromise: q.Promise; + restartPromise: Promise; frameworkUsesAfterEach: boolean; ready_?: wdpromise.Promise; @@ -84,10 +83,10 @@ export class Runner extends EventEmitter { * Executor of testPreparer * @public * @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 { + runTestPreparer(extraFlags?: string[]): Promise { let unknownFlags = this.config_.unknownFlags_ || []; if (extraFlags) { unknownFlags = unknownFlags.filter((f) => extraFlags.indexOf(f) === -1); @@ -110,17 +109,17 @@ export class Runner extends EventEmitter { * Responsible for `restartBrowserBetweenTests` * * @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 { - let ret: q.Promise; + afterEach(): Promise { + let ret: Promise; this.frameworkUsesAfterEach = true; if (this.config_.restartBrowserBetweenTests) { - this.restartPromise = this.restartPromise || q(protractor.browser.restart()); + this.restartPromise = this.restartPromise || Promise.resolve(protractor.browser.restart()); ret = this.restartPromise; this.restartPromise = undefined; } - return ret || q(); + return ret || Promise.resolve(); } /** @@ -231,14 +230,14 @@ export class Runner extends EventEmitter { let initProperties = { baseUrl: config.baseUrl, - rootElement: config.rootElement as string | wdpromise.Promise, + rootElement: config.rootElement as string | Promise, untrackOutstandingTimeouts: config.untrackOutstandingTimeouts, params: config.params, getPageTimeout: config.getPageTimeout, allScriptsTimeout: config.allScriptsTimeout, debuggerServerPort: config.debuggerServerPort, ng12Hybrid: config.ng12Hybrid, - waitForAngularEnabled: true as boolean | wdpromise.Promise + waitForAngularEnabled: true as boolean | Promise }; if (parentBrowser) { @@ -286,7 +285,7 @@ export class Runner extends EventEmitter { }); browser_.getProcessedConfig = () => { - return wdpromise.when(config); + return Promise.resolve(config); }; browser_.forkNewDriverInstance = @@ -361,7 +360,7 @@ export class Runner extends EventEmitter { * @return {q.Promise} A promise which resolves to the exit code of the tests. * @public */ - run(): q.Promise { + run(): Promise { let testPassed: boolean; let plugins = this.plugins_ = new Plugins(this.config_); let pluginPostTestPromises: any; @@ -381,7 +380,7 @@ export class Runner extends EventEmitter { } // 0) Wait for debugger - return q(this.ready_) + return Promise.resolve(this.ready_) .then(() => { // 1) Setup environment // noinspection JSValidateTypes @@ -438,7 +437,7 @@ export class Runner extends EventEmitter { // TODO(sjelin): replace with warnings once `afterEach` support is required let restartDriver = () => { if (!this.frameworkUsesAfterEach) { - this.restartPromise = q(browser_.restart()); + this.restartPromise = Promise.resolve(browser_.restart()); } }; this.on('testPass', restartDriver); @@ -465,7 +464,7 @@ export class Runner extends EventEmitter { }) .then((testResults: any) => { results = testResults; - return q.all(pluginPostTestPromises); + return Promise.all(pluginPostTestPromises); // 6) Teardown plugins }) .then(() => { @@ -493,7 +492,7 @@ export class Runner extends EventEmitter { let exitCode = testPassed ? 0 : 1; return this.exit_(exitCode); }) - .fin(() => { + .then(() => { return this.shutdown_(); }); } diff --git a/lib/taskRunner.ts b/lib/taskRunner.ts index bdef6f953..c1402411c 100644 --- a/lib/taskRunner.ts +++ b/lib/taskRunner.ts @@ -1,6 +1,5 @@ import * as child_process from 'child_process'; import {EventEmitter} from 'events'; -import * as q from 'q'; import {Config} from './config'; import {ConfigParser} from './configParser'; @@ -37,12 +36,12 @@ export class TaskRunner extends EventEmitter { /** * 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 * result of the run: * taskId, specs, capabilities, failedCount, exitCode, specResults */ - public run(): q.Promise { + public async run(): Promise { let runResults: RunResults = { taskId: this.task.taskId, specs: this.task.specs, @@ -65,61 +64,59 @@ export class TaskRunner extends EventEmitter { config.specs = this.task.specs; if (this.runInFork) { - let deferred = q.defer(); + 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(this.task, childProcess.pid); - let childProcess = child_process.fork( - __dirname + '/runnerCli.js', process.argv.slice(2), {cwd: process.cwd(), silent: true}); - let taskLogger = new TaskLogger(this.task, childProcess.pid); + // stdout pipe + childProcess.stdout.on('data', (data: string) => { + taskLogger.log(data); + }); - // stdout pipe - childProcess.stdout.on('data', (data: string) => { - taskLogger.log(data); - }); - - // stderr pipe - childProcess.stderr.on('data', (data: string) => { - taskLogger.log(data); - }); + // stderr pipe + childProcess.stderr.on('data', (data: string) => { + taskLogger.log(data); + }); - childProcess - .on('message', - (m: any) => { - 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: any) => { - taskLogger.flush(); - deferred.reject(err); - }) - .on('exit', (code: number) => { - taskLogger.flush(); - runResults.exitCode = code; - deferred.resolve(runResults); - }); + childProcess + .on('message', + (m: any) => { + 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: any) => { + taskLogger.flush(); + reject(err); + }) + .on('exit', (code: number) => { + 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 + childProcess.send({ + command: 'run', + configFile: this.configFile, + additionalConfig: this.additionalConfig, + capabilities: this.task.capabilities, + specs: this.task.specs + }); }); - - return deferred.promise; } else { let runner = new Runner(config); @@ -128,10 +125,9 @@ export class TaskRunner extends EventEmitter { runResults.specResults = results.specResults; }); - return runner.run().then((exitCode: number) => { - runResults.exitCode = exitCode; - return runResults; - }); + const exitCode = await runner.run(); + runResults.exitCode = exitCode; + return runResults; } } } diff --git a/lib/util.ts b/lib/util.ts index 346051702..cb3b86546 100644 --- a/lib/util.ts +++ b/lib/util.ts @@ -1,5 +1,4 @@ -import {resolve} from 'path'; -import {Promise, when} from 'q'; +import * as path from 'path'; import {error as wderror} from 'selenium-webdriver'; let STACK_SUBSTRINGS_TO_FILTER = [ @@ -36,16 +35,19 @@ export function filterStackTrace(text: string): string { * @return {q.Promise} A promise that will resolve when filenameOrFn completes. */ export function runFilenameOrFn_(configDir: string, filenameOrFn: any, args?: any[]): Promise { - return Promise((resolvePromise) => { + return new Promise(async (resolve) => { if (filenameOrFn && !(typeof filenameOrFn === 'string' || typeof filenameOrFn === 'function')) { throw new Error('filenameOrFn must be a string or function'); } if (typeof filenameOrFn === 'string') { - filenameOrFn = require(resolve(configDir, filenameOrFn)); + filenameOrFn = require(path.resolve(configDir, filenameOrFn)); } + let results; if (typeof filenameOrFn === 'function') { - let results = when(filenameOrFn.apply(null, args), null, (err) => { + try { + results = await filenameOrFn.apply(null, args); + } catch (err) { if (typeof err === 'string') { err = new Error(err); } else { @@ -56,10 +58,10 @@ export function runFilenameOrFn_(configDir: string, filenameOrFn: any, args?: an } err.stack = exports.filterStackTrace(err.stack); throw err; - }); - resolvePromise(results); + } + resolve(results); } else { - resolvePromise(undefined); + resolve(0); } }); } diff --git a/spec/basic/expected_conditions_spec.js b/spec/basic/expected_conditions_spec.js index b537a7cb5..c28a8fbf2 100644 --- a/spec/basic/expected_conditions_spec.js +++ b/spec/basic/expected_conditions_spec.js @@ -177,7 +177,7 @@ describe('expected conditions', () => { describe('for forked browsers', () => { // ensure that we can run EC on forked browser instances it('should have alertIsPresent', async () => { - const browser2 = browser.forkNewDriverInstance(); + const browser2 = await browser.forkNewDriverInstance().ready; await browser2.get('index.html#/form'); const EC2 = browser2.ExpectedConditions; const alertIsPresent = EC2.alertIsPresent(); diff --git a/spec/basic/handling_spec.js b/spec/basic/handling_spec.js index d2d0e8340..fd6886436 100644 --- a/spec/basic/handling_spec.js +++ b/spec/basic/handling_spec.js @@ -1,4 +1,13 @@ describe('handling timeout errors', () => { + + // beforeEach(async () => { + // await browser.waitForAngularEnabled(false); + // }); + + // afterEach(async () => { + // await browser.waitForAngularEnabled(true); + // }); + it('should call error handler on a timeout', async () => { try { await browser.get('http://dummyUrl', 1); diff --git a/spec/basicConf.js b/spec/basicConf.js index 9b378fd52..2d9aeef90 100644 --- a/spec/basicConf.js +++ b/spec/basicConf.js @@ -9,7 +9,8 @@ exports.config = { // Spec patterns are relative to this directory. specs: [ - 'basic/*_spec.js' + // 'basic/*_spec.js' + 'basic/locators_spec.js' ], // Exclude patterns are relative to this directory. From ce4867eccd4e1b1ba0fdf89ebb20c443aba78cfc Mon Sep 17 00:00:00 2001 From: Craig Nishina Date: Tue, 20 Nov 2018 18:36:54 -0800 Subject: [PATCH 3/4] well there are things that need to be cleaned up but it kinda works? --- circle.yml | 2 +- lib/browser.ts | 125 +- lib/launcher.ts | 27 +- lib/runner.ts | 268 +- lib/util.ts | 3 +- spec/basic/elements_spec.js | 6 +- spec/basicConf.js | 3 +- spec/install/package-lock.json | 4005 +++++++++++++++++++++++ spec/unit/driverProviders/local_test.js | 22 +- tsconfig.json | 5 +- 10 files changed, 4197 insertions(+), 269 deletions(-) create mode 100644 spec/install/package-lock.json diff --git a/circle.yml b/circle.yml index 4ddd78bda..f32383b19 100644 --- a/circle.yml +++ b/circle.yml @@ -52,7 +52,7 @@ jobs: name: Selenium Start background: true command: | - ./node_modules/webdriver-manager/bin/webdriver-manager update + ./bin/webdriver-manager update ./node_modules/.bin/webdriver-manager-replacement update --gecko false ./node_modules/.bin/webdriver-manager-replacement start --gecko false diff --git a/lib/browser.ts b/lib/browser.ts index 5381061c8..5f7ff970b 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -1,5 +1,5 @@ import {BPClient} from 'blocking-proxy'; -import {ActionSequence, By, Capabilities, Command as WdCommand, FileDetector, ICommandName, Navigation, Options, promise as wdpromise, Session, TargetLocator, TouchSequence, until, WebDriver, WebElement, WebElementPromise} from 'selenium-webdriver'; +import {ActionSequence, By, Capabilities, Command as WdCommand, FileDetector, ICommandName, Navigation, Options, Session, TargetLocator, TouchSequence, until, WebDriver, WebElement, WebElementPromise} from 'selenium-webdriver'; import * as url from 'url'; import {extend as extendWD, ExtendedWebDriver} from 'webdriver-js-extender'; @@ -477,25 +477,12 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * 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'); * await browser.restart(); * await browser.get('page2'); // 'page2' gotten by restarted browser * - * // 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 + * // Running against forked browsers * var forked = await browser.forkNewDriverInstance().ready; * await fork.get('page1'); * fork = await fork.restart(); @@ -515,29 +502,6 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { return; } - /** - * 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 { - return; - } - /** * Instead of using a single root element, search through all angular apps * available on the page when finding elements or waiting for stability. @@ -584,14 +548,13 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @param {string} description A description for debugging purposes. * @param {...*} var_args The arguments to pass to the script. * @returns {!Promise} A promise that will resolve to - * the - * scripts return value. + * the scripts return value. * @template T */ private executeAsyncScript_(script: string|Function, description: string, ...scriptArgs: any[]): Promise { if (typeof script === 'function') { - script = 'return (' + script + ').apply(null, arguments);'; + script = `return (${script}).apply(null, arguments);`; } return this.driver.schedule( new Command(CommandName.EXECUTE_ASYNC_SCRIPT) @@ -618,13 +581,18 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { } let runWaitForAngularScript = async(): Promise => { - // if (this.plugins_.skipAngularStability() || this.bpClient) { - // return null; - // } else { - let rootEl = await this.angularAppRoot(); - return this.executeAsyncScript_( - clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); - // } + if (this.plugins_.skipAngularStability() || this.bpClient) { + return null; + } else { + try { + const rootEl = await this.angularAppRoot(); + return this.executeAsyncScript_( + clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); + } + catch (err) { + console.log('something wrong happened here'); + } + } }; try { @@ -637,7 +605,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { await this.plugins_.waitForPromise(this); await this.driver.wait(async () => { - let results = await this.plugins_.waitForCondition(this); + let results: boolean[] = await this.plugins_.waitForCondition(this); return results.reduce((x, y) => x && y, true); }, this.allScriptsTimeout, 'Plugins.waitForCondition()'); } catch (err) { @@ -660,13 +628,13 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { if (description.indexOf(' - Locator: ') == 0) { errMsg += '\nWhile waiting for element with locator' + description; } - let pendingTimeoutsPromise: wdpromise.Promise; + let pendingTimeoutsPromise: Promise; if (this.trackOutstandingTimeouts_) { pendingTimeoutsPromise = this.executeScriptWithDescription( 'return window.NG_PENDING_TIMEOUTS', 'Protractor.waitForAngular() - getting pending timeouts' + description); } else { - pendingTimeoutsPromise = wdpromise.when({}); + pendingTimeoutsPromise = Promise.resolve(); } let pendingHttpsPromise = this.executeScriptWithDescription( clientSideScripts.getPendingHttpRequests, @@ -740,8 +708,8 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * Modules will be registered after existing modules already on the page, * so any module registered here will override preexisting modules with the * same name. - * - * @example + *"both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. S + *"both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. S * browser.addMockModule('modName', function() { * angular.module('modName', []).value('foo', 'bar'); * }); @@ -801,6 +769,8 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { this.trackOutstandingTimeouts_); } + + navigating = false; /** * @see webdriver.WebDriver.get * @@ -844,7 +814,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { // We need to make sure the new url has loaded before // we try to execute any asynchronous scripts. - this.driver.wait(() => { + await this.driver.wait(() => { return this.executeScriptWithDescription('return window.location.href;', msg('get url')) .then( (url: any) => { @@ -866,7 +836,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { }, timeout, 'waiting for page to load for ' + timeout + 'ms'); // Run Plugins - // await this.plugins_.onPageLoad(this); + await this.plugins_.onPageLoad(this); let angularVersion: number; try { @@ -920,7 +890,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { } // Run Plugins - // await this.plugins_.onPageStable(this); + await this.plugins_.onPageStable(this); } /** @@ -933,17 +903,14 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * * @param {number=} opt_timeout Number of milliseconds to wait for Angular to start. */ - refresh(opt_timeout?: number) { - if (this.ignoreSynchronization) { - return this.driver.navigate().refresh(); + async refresh(opt_timeout?: number) { + if (!await this.waitForAngularEnabled()) { + return this.driver.navigate().refresh() as Promise; } - return this - .executeScriptWithDescription( - 'return window.location.href', 'Protractor.refresh() - getUrl') - .then((href: string) => { - return this.get(href, opt_timeout); - }); + const href = await this.executeScriptWithDescription( + 'return window.location.href', 'Protractor.refresh() - getUrl'); + return this.get(href, opt_timeout); } /** @@ -1029,12 +996,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * This will run the sendKeys command as the next task, then re-enter the * debugger. */ - debugger() { + async debugger() { // jshint debug: true - return this.driver.executeScript(clientSideScripts.installInBrowser) - .then(() => wdpromise.controlFlow().execute(() => { - debugger; - }, 'add breakpoint to control flow')); + await this.driver.executeScript(clientSideScripts.installInBrowser) + debugger; } /** @@ -1097,10 +1062,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * @param {number=} opt_debugPort Optional port to use for the debugging * process */ - pause(opt_debugPort?: number): wdpromise.Promise { + async pause(opt_debugPort?: number): Promise { if (this.debugHelper.isAttached()) { logger.info('Encountered browser.pause(), but debugger already attached.'); - return wdpromise.when(true); + return true; } let debuggerClientPath = __dirname + '/debugger/clients/wddebugger.js'; let onStartFn = (firstTime: boolean) => { @@ -1120,18 +1085,4 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { }; this.debugHelper.init(debuggerClientPath, onStartFn, opt_debugPort); } - - /** - * Determine if the control flow is enabled. - * - * @returns true if the control flow is enabled, false otherwise. - */ - controlFlowIsEnabled() { - if ((wdpromise as any).USE_PROMISE_MANAGER !== undefined) { - return (wdpromise as any).USE_PROMISE_MANAGER; - } else { - // True for old versions of `selenium-webdriver`, probably false in >=5.0.0 - return !!wdpromise.ControlFlow; - } - } } diff --git a/lib/launcher.ts b/lib/launcher.ts index 070745518..8d077d03b 100644 --- a/lib/launcher.ts +++ b/lib/launcher.ts @@ -149,14 +149,15 @@ let initFn = async function(configFile: string, additionalConfig: Config) { config.framework = 'explorer'; let runner = new Runner(config); - return runner.run().then( - (exitCode: number) => { - process.exit(exitCode); - }, - (err: Error) => { - logger.error(err); - process.exit(1); - }); + + try { + let exitCode = await runner.run(); + console.log('runner', exitCode); + process.exit(exitCode); + } catch (err) { + logger.error(err); + process.exit(1); + } } // 4) Run tests. @@ -171,7 +172,6 @@ let initFn = async function(configFile: string, additionalConfig: Config) { logger.warn('Ignoring uncaught error ' + exc); return; } - let errorCode = ErrorHandler.parseError(e); if (errorCode) { let protractorError = e as ProtractorError; @@ -185,9 +185,11 @@ let initFn = async function(configFile: string, additionalConfig: Config) { }); process.on('exit', (code: number) => { + console.log(code); if (code) { logger.error('Process exited with error code ' + code); } else if (scheduler.numTasksOutstanding() > 0) { + console.log('scheduler num task outstanding: ', scheduler.numTasksOutstanding()); logger.error( 'BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining'); process.exit(RUNNERS_FAILED_EXIT_CODE); @@ -196,12 +198,15 @@ let initFn = async function(configFile: string, additionalConfig: Config) { // Run afterlaunch and exit let cleanUpAndExit = (exitCode: number) => { + console.log('cleanUpAndExit'); return helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]) .then( (returned) => { if (typeof returned === 'number') { + console.log('returned:', returned); process.exit(returned); } else { + console.log('exitCode:', exitCode); process.exit(exitCode); } }, @@ -221,13 +226,13 @@ let initFn = async function(configFile: string, additionalConfig: Config) { } } - const createNextTaskRunner = () => { + const createNextTaskRunner = async () => { return new Promise(resolve => { let task = scheduler.nextTask(); if (task) { let taskRunner = new TaskRunner(configFile, additionalConfig, task, forkProcess); taskRunner.run() - .then((result) => { + .then(async (result) => { if (result.exitCode && !result.failedCount) { logger.error( 'Runner process exited unexpectedly with error code: ' + result.exitCode); diff --git a/lib/runner.ts b/lib/runner.ts index 7ad43304a..f46f66bd2 100644 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -143,16 +143,17 @@ export class Runner extends EventEmitter { * @private * @param {int} Standard unix exit code */ - exit_ = function(exitCode: number): any { - return helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]) - .then((returned): number | any => { - if (typeof returned === 'number') { - return returned; - } else { - return exitCode; - } - }); - }; + async exit_(exitCode: number): Promise { + console.log('exit_', exitCode); + let returned = await helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]); + console.log('exit_', returned); + if (typeof returned === 'number') { + return returned; + } else { + console.log('exit_ returns', exitCode); + return exitCode; + } + } /** * Getter for the Runner config object @@ -163,14 +164,6 @@ export class Runner extends EventEmitter { return this.config_; } - /** - * Get the control flow used by this runner. - * @return {Object} WebDriver control flow. - */ - controlFlow(): any { - return wdpromise.controlFlow(); - } - /** * Sets up convenience globals for test specs * @private @@ -320,24 +313,9 @@ export class Runner extends EventEmitter { 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 this.driverprovider_.quitDriver(browser_.driver) + .then(replaceBrowser) + .then(newBrowser => newBrowser.ready); }; return browser_; @@ -357,10 +335,10 @@ export class Runner extends EventEmitter { /** * 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(): Promise { + async run(): Promise { let testPassed: boolean; let plugins = this.plugins_ = new Plugins(this.config_); let pluginPostTestPromises: any; @@ -380,120 +358,108 @@ export class Runner extends EventEmitter { } // 0) Wait for debugger - return Promise.resolve(this.ready_) - .then(() => { - // 1) Setup environment - // noinspection JSValidateTypes - return this.driverprovider_.setupEnv(); - }) - .then(() => { - // 2) Create a browser and setup globals - browser_ = this.createBrowser(plugins); - this.setupGlobals_(browser_); - return browser_.ready.then(browser_.getSession) - .then( - (session: Session) => { - logger.debug( - 'WebDriver session successfully started with capabilities ' + - util.inspect(session.getCapabilities())); - }, - (err: Error) => { - logger.error('Unable to start a WebDriver session.'); - throw err; - }); - // 3) Setup plugins - }) - .then(() => { - return plugins.setup(); - // 4) Execute test cases - }) - .then(() => { - // Do the framework setup here so that jasmine and mocha globals are - // available to the onPrepare function. - let frameworkPath = ''; - if (this.config_.framework === 'jasmine' || this.config_.framework === 'jasmine2') { - frameworkPath = './frameworks/jasmine.js'; - } else if (this.config_.framework === 'mocha') { - frameworkPath = './frameworks/mocha.js'; - } else if (this.config_.framework === 'debugprint') { - // Private framework. Do not use. - frameworkPath = './frameworks/debugprint.js'; - } else if (this.config_.framework === 'explorer') { - // Private framework. Do not use. - frameworkPath = './frameworks/explorer.js'; - } else if (this.config_.framework === 'custom') { - if (!this.config_.frameworkPath) { - throw new Error( - 'When config.framework is custom, ' + - 'config.frameworkPath is required.'); - } - frameworkPath = this.config_.frameworkPath; - } else { - throw new Error( - 'config.framework (' + this.config_.framework + ') is not a valid framework.'); - } + await Promise.resolve(this.ready_); + + // 1) Setup environment + // noinspection JSValidateTypes + await this.driverprovider_.setupEnv(); + + // 2) Create a browser and setup globals + browser_ = this.createBrowser(plugins); + this.setupGlobals_(browser_); + try { + let session = await browser_.ready.then(browser_.getSession); + logger.debug( + 'WebDriver session successfully started with capabilities ' + + util.inspect(session.getCapabilities())); + } catch (err) { + logger.error('Unable to start a WebDriver session.'); + throw err; + } + + // 3) Setup plugins + await plugins.setup(); + + // 4) Execute test cases + // Do the framework setup here so that jasmine and mocha globals are + // available to the onPrepare function. + let frameworkPath = ''; + if (this.config_.framework === 'jasmine' || this.config_.framework === 'jasmine2') { + frameworkPath = './frameworks/jasmine.js'; + } else if (this.config_.framework === 'mocha') { + frameworkPath = './frameworks/mocha.js'; + } else if (this.config_.framework === 'debugprint') { + // Private framework. Do not use. + frameworkPath = './frameworks/debugprint.js'; + } else if (this.config_.framework === 'explorer') { + // Private framework. Do not use. + frameworkPath = './frameworks/explorer.js'; + } else if (this.config_.framework === 'custom') { + if (!this.config_.frameworkPath) { + throw new Error( + 'When config.framework is custom, ' + + 'config.frameworkPath is required.'); + } + frameworkPath = this.config_.frameworkPath; + } else { + throw new Error( + 'config.framework (' + this.config_.framework + ') is not a valid framework.'); + } - if (this.config_.restartBrowserBetweenTests) { - // TODO(sjelin): replace with warnings once `afterEach` support is required - let restartDriver = () => { - if (!this.frameworkUsesAfterEach) { - this.restartPromise = Promise.resolve(browser_.restart()); - } - }; - this.on('testPass', restartDriver); - this.on('testFail', restartDriver); - } + if (this.config_.restartBrowserBetweenTests) { + // TODO(sjelin): replace with warnings once `afterEach` support is required + let restartDriver = () => { + if (!this.frameworkUsesAfterEach) { + this.restartPromise = Promise.resolve(browser_.restart()); + } + }; + this.on('testPass', restartDriver); + this.on('testFail', restartDriver); + } - // We need to save these promises to make sure they're run, but we - // don't - // want to delay starting the next test (because we can't, it's just - // an event emitter). - pluginPostTestPromises = []; - - this.on('testPass', (testInfo: any) => { - pluginPostTestPromises.push(plugins.postTest(true, testInfo)); - }); - this.on('testFail', (testInfo: any) => { - pluginPostTestPromises.push(plugins.postTest(false, testInfo)); - }); - - logger.debug('Running with spec files ' + this.config_.specs); - - return require(frameworkPath).run(this, this.config_.specs); - // 5) Wait for postTest plugins to finish - }) - .then((testResults: any) => { - results = testResults; - return Promise.all(pluginPostTestPromises); - // 6) Teardown plugins - }) - .then(() => { - return plugins.teardown(); - // 7) Teardown - }) - .then(() => { - results = helper.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(); - }); - } else { - return this.driverprovider_.teardownEnv(); - } - // 8) Let plugins do final cleanup - }) - .then(() => { - return plugins.postResults(); - // 9) Exit process - }) - .then(() => { - let exitCode = testPassed ? 0 : 1; - return this.exit_(exitCode); - }) - .then(() => { - return this.shutdown_(); - }); + // We need to save these promises to make sure they're run, but we + // don't + // want to delay starting the next test (because we can't, it's just + // an event emitter). + pluginPostTestPromises = []; + + this.on('testPass', (testInfo: any) => { + pluginPostTestPromises.push(plugins.postTest(true, testInfo)); + }); + this.on('testFail', (testInfo: any) => { + pluginPostTestPromises.push(plugins.postTest(false, testInfo)); + }); + logger.debug('Running with spec files ' + this.config_.specs); + let testResults = await require(frameworkPath).run(this, this.config_.specs); + + // 5) Wait for postTest plugins to finish + results = testResults; + await Promise.all(pluginPostTestPromises); + + // 6) Teardown plugins + await plugins.teardown(); + + // 7) Teardown + results = helper.joinTestLogs(results, plugins.getResults()); + this.emit('testsDone', results); + testPassed = results.failedCount === 0; + if (this.driverprovider_.updateJob) { + await this.driverprovider_.updateJob({'passed': testPassed}); + await this.driverprovider_.teardownEnv(); + } else { + await this.driverprovider_.teardownEnv(); + } + + // 8) Let plugins do final cleanup + await plugins.postResults(); + + // 9) Exit process + console.log('testpassed', testPassed); + const exitCode = testPassed ? 0 : 1; + console.log('exitCode', exitCode); + + await this.shutdown_(); + + return this.exit_(exitCode); } } diff --git a/lib/util.ts b/lib/util.ts index cb3b86546..2dbc8a40b 100644 --- a/lib/util.ts +++ b/lib/util.ts @@ -61,7 +61,8 @@ export function runFilenameOrFn_(configDir: string, filenameOrFn: any, args?: an } resolve(results); } else { - resolve(0); + console.log('we are returning undefined from runFilenameOrFn_'); + resolve(undefined); } }); } diff --git a/spec/basic/elements_spec.js b/spec/basic/elements_spec.js index 098b77a89..a63a489fe 100644 --- a/spec/basic/elements_spec.js +++ b/spec/basic/elements_spec.js @@ -420,7 +420,7 @@ describe('ElementArrayFinder', () => { const colorList = element.all(by.model('color')); await browser.get('index.html#/form'); - colorList.each(async(colorElement) => { + await colorList.each(async(colorElement) => { expect(await colorElement.getText()).not.toEqual('purple'); }); }); @@ -429,12 +429,12 @@ describe('ElementArrayFinder', () => { await browser.get('index.html#/form'); const rows = element.all(by.css('.rowlike')); - rows.each(async(row) => { + await rows.each(async(row) => { const input = row.element(by.css('.input')); expect(await input.getAttribute('value')).toEqual('10'); }); - rows.each(async(row) => { + await rows.each(async(row) => { const input = row.element(by.css('input')); expect(await input.getAttribute('value')).toEqual('10'); }); diff --git a/spec/basicConf.js b/spec/basicConf.js index 2d9aeef90..10138c5cd 100644 --- a/spec/basicConf.js +++ b/spec/basicConf.js @@ -9,8 +9,7 @@ exports.config = { // Spec patterns are relative to this directory. specs: [ - // 'basic/*_spec.js' - 'basic/locators_spec.js' + 'basic/restart_spec.js' ], // Exclude patterns are relative to this directory. diff --git a/spec/install/package-lock.json b/spec/install/package-lock.json new file mode 100644 index 000000000..2be9a8b96 --- /dev/null +++ b/spec/install/package-lock.json @@ -0,0 +1,4005 @@ +{ + "name": "protractor-install", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/jasmine": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.12.tgz", + "integrity": "sha512-eE+xeiGBPgQsNcyg61JBqQS6NtxC+s2yfOikMCnc0Z4NqKujzmSahmtjLCKVQU/AyrTEQ76TOwQBnr8wGP2bmA==" + }, + "@types/jasminewd2": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz", + "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/q": { + "version": "0.0.32", + "resolved": "http://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "2.53.43", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz", + "integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-js": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jszip": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", + "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", + "requires": { + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" + } + }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "requires": { + "immediate": "~3.0.5" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "protractor": { + "version": "file:../..", + "requires": { + "@types/node": "^6.0.46", + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "optimist": "~0.6.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.0.6", + "webdriver-manager-replacement": "^1.1.0" + }, + "dependencies": { + "@types/chalk": { + "version": "0.4.31", + "bundled": true + }, + "@types/events": { + "version": "1.1.0", + "bundled": true + }, + "@types/glob": { + "version": "5.0.35", + "bundled": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "2.8.5", + "bundled": true + }, + "@types/jasminewd2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/minimatch": { + "version": "2.0.29", + "bundled": true + }, + "@types/minimist": { + "version": "1.2.0", + "bundled": true + }, + "@types/node": { + "version": "6.0.96", + "bundled": true + }, + "@types/optimist": { + "version": "0.0.29", + "bundled": true + }, + "@types/q": { + "version": "0.0.32", + "bundled": true + }, + "@types/selenium-webdriver": { + "version": "3.0.10", + "bundled": true + }, + "accepts": { + "version": "1.3.4", + "bundled": true, + "requires": { + "mime-types": "~2.1.16", + "negotiator": "0.6.1" + } + }, + "adm-zip": { + "version": "0.4.11", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "5.5.1", + "bundled": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "ansi-wrap": { + "version": "0.1.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true + }, + "array-differ": { + "version": "1.0.0", + "bundled": true + }, + "array-each": { + "version": "1.0.1", + "bundled": true + }, + "array-flatten": { + "version": "1.1.1", + "bundled": true + }, + "array-slice": { + "version": "1.1.0", + "bundled": true + }, + "array-union": { + "version": "1.0.2", + "bundled": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "bundled": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "assertion-error": { + "version": "1.0.2", + "bundled": true + }, + "async": { + "version": "1.5.2", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "beeper": { + "version": "1.1.1", + "bundled": true + }, + "blocking-proxy": { + "version": "1.0.1", + "bundled": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "body-parser": { + "version": "1.15.2", + "bundled": true, + "requires": { + "bytes": "2.4.0", + "content-type": "~1.0.2", + "debug": "~2.2.0", + "depd": "~1.1.0", + "http-errors": "~1.5.0", + "iconv-lite": "0.4.13", + "on-finished": "~2.3.0", + "qs": "6.2.0", + "raw-body": "~2.1.7", + "type-is": "~1.6.13" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true + }, + "qs": { + "version": "6.2.0", + "bundled": true + } + } + }, + "boom": { + "version": "4.3.1", + "bundled": true, + "requires": { + "hoek": "4.x.x" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "bundled": true, + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "bundled": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "browserstack": { + "version": "1.5.1", + "bundled": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "bytes": { + "version": "2.4.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chai": { + "version": "3.5.0", + "bundled": true, + "requires": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + } + }, + "chai-as-promised": { + "version": "5.3.0", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true + }, + "clang-format": { + "version": "1.0.49", + "bundled": true, + "requires": { + "async": "^1.5.2", + "glob": "^7.0.0", + "resolve": "^1.1.6" + } + }, + "cli": { + "version": "1.0.1", + "bundled": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-color": { + "version": "1.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.12", + "es6-iterator": "2", + "memoizee": "^0.4.3", + "timers-ext": "0.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.3", + "bundled": true + }, + "clone-stats": { + "version": "0.0.1", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.1.2", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.3.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "configstore": { + "version": "3.1.1", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "bundled": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "bundled": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "content-disposition": { + "version": "0.5.2", + "bundled": true + }, + "content-type": { + "version": "1.0.4", + "bundled": true + }, + "cookie": { + "version": "0.3.1", + "bundled": true + }, + "cookie-signature": { + "version": "1.0.6", + "bundled": true + }, + "core-js": { + "version": "2.3.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "cryptiles": { + "version": "3.1.2", + "bundled": true, + "requires": { + "boom": "5.x.x" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "bundled": true, + "requires": { + "hoek": "4.x.x" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "d": { + "version": "1.0.0", + "bundled": true, + "requires": { + "es5-ext": "^0.10.9" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "bundled": true + }, + "dateformat": { + "version": "2.2.0", + "bundled": true + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "2.0.0", + "bundled": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "deep-eql": { + "version": "0.1.3", + "bundled": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "bundled": true + } + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "^1.0.2" + } + }, + "del": { + "version": "2.2.2", + "bundled": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "depd": { + "version": "1.1.1", + "bundled": true + }, + "deprecated": { + "version": "0.0.1", + "bundled": true + }, + "destroy": { + "version": "1.0.4", + "bundled": true + }, + "detect-file": { + "version": "0.1.0", + "bundled": true, + "requires": { + "fs-exists-sync": "^0.1.0" + } + }, + "diff": { + "version": "2.2.3", + "bundled": true + }, + "doctrine": { + "version": "0.7.2", + "bundled": true, + "requires": { + "esutils": "^1.1.6", + "isarray": "0.0.1" + }, + "dependencies": { + "esutils": { + "version": "1.1.6", + "bundled": true + }, + "isarray": { + "version": "0.0.1", + "bundled": true + } + } + }, + "dom-serializer": { + "version": "0.1.0", + "bundled": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "bundled": true + }, + "entities": { + "version": "1.1.1", + "bundled": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "bundled": true + }, + "domhandler": { + "version": "2.3.0", + "bundled": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "bundled": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer": { + "version": "0.1.1", + "bundled": true + }, + "duplexer2": { + "version": "0.0.2", + "bundled": true, + "requires": { + "readable-stream": "~1.1.9" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "bundled": true + }, + "encodeurl": { + "version": "1.0.1", + "bundled": true + }, + "end-of-stream": { + "version": "0.1.5", + "bundled": true, + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "bundled": true, + "requires": { + "wrappy": "1" + } + } + } + }, + "entities": { + "version": "1.0.0", + "bundled": true + }, + "es5-ext": { + "version": "0.10.38", + "bundled": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "bundled": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "3.0.2", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "^4.0.3" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "bundled": true + } + } + }, + "es6-symbol": { + "version": "3.1.1", + "bundled": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "bundled": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "bundled": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "etag": { + "version": "1.7.0", + "bundled": true + }, + "event-emitter": { + "version": "0.3.5", + "bundled": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "event-stream": { + "version": "3.3.4", + "bundled": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "bundled": true + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "expand-tilde": { + "version": "1.2.2", + "bundled": true, + "requires": { + "os-homedir": "^1.0.1" + } + }, + "expect.js": { + "version": "0.3.1", + "bundled": true + }, + "express": { + "version": "4.14.1", + "bundled": true, + "requires": { + "accepts": "~1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "~1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "~2.2.0", + "depd": "~1.1.0", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "finalhandler": "0.5.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "~1.1.3", + "qs": "6.2.0", + "range-parser": "~1.2.0", + "send": "0.14.2", + "serve-static": "~1.11.2", + "type-is": "~1.6.14", + "utils-merge": "1.0.0", + "vary": "~1.1.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true + }, + "qs": { + "version": "6.2.0", + "bundled": true + } + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fancy-log": { + "version": "1.3.1", + "bundled": true, + "requires": { + "ansi-gray": "^0.1.1", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true + }, + "fill-range": { + "version": "2.2.3", + "bundled": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^1.1.3", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "finalhandler": { + "version": "0.5.1", + "bundled": true, + "requires": { + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true + }, + "statuses": { + "version": "1.3.1", + "bundled": true + } + } + }, + "find-index": { + "version": "0.1.1", + "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "0.4.3", + "bundled": true, + "requires": { + "detect-file": "^0.1.0", + "is-glob": "^2.0.1", + "micromatch": "^2.3.7", + "resolve-dir": "^0.1.0" + } + }, + "fined": { + "version": "1.1.0", + "bundled": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "bundled": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "bundled": true + }, + "flagged-respawn": { + "version": "0.3.2", + "bundled": true + }, + "for-in": { + "version": "1.0.2", + "bundled": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.1", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "bundled": true + }, + "fresh": { + "version": "0.3.0", + "bundled": true + }, + "from": { + "version": "0.1.7", + "bundled": true + }, + "fs-exists-sync": { + "version": "0.1.0", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gaze": { + "version": "0.5.2", + "bundled": true, + "requires": { + "globule": "~0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "bundled": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "bundled": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "minimatch": { + "version": "2.0.10", + "bundled": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "bundled": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "bundled": true, + "requires": { + "gaze": "^0.5.1" + } + }, + "glob2base": { + "version": "0.0.12", + "bundled": true, + "requires": { + "find-index": "^0.1.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "0.2.3", + "bundled": true, + "requires": { + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "bundled": true, + "requires": { + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" + } + }, + "globby": { + "version": "5.0.0", + "bundled": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globule": { + "version": "0.1.0", + "bundled": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "bundled": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "bundled": true + }, + "inherits": { + "version": "1.0.2", + "bundled": true + }, + "lodash": { + "version": "1.0.2", + "bundled": true + }, + "minimatch": { + "version": "0.2.14", + "bundled": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "bundled": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "bundled": true, + "requires": { + "natives": "^1.1.0" + } + }, + "growl": { + "version": "1.9.2", + "bundled": true + }, + "gulp": { + "version": "3.9.1", + "bundled": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "dependencies": { + "semver": { + "version": "4.3.6", + "bundled": true + } + } + }, + "gulp-clang-format": { + "version": "1.0.23", + "bundled": true, + "requires": { + "clang-format": "^1.0.32", + "gulp-diff": "^1.0.0", + "gulp-util": "^3.0.4", + "pkginfo": "^0.3.0", + "stream-combiner2": "^1.1.1", + "stream-equal": "0.1.6", + "through2": "^0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.0.34", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "bundled": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "gulp-diff": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cli-color": "^1.0.0", + "diff": "^2.0.2", + "event-stream": "^3.1.5", + "gulp-util": "^3.0.6", + "through2": "^2.0.0" + } + }, + "gulp-tslint": { + "version": "7.1.0", + "bundled": true, + "requires": { + "gulp-util": "~3.0.8", + "map-stream": "~0.1.0", + "through": "~2.3.8" + } + }, + "gulp-util": { + "version": "3.0.8", + "bundled": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "bundled": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "bundled": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.0.3", + "bundled": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "bundled": true + }, + "has-gulplog": { + "version": "0.1.0", + "bundled": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "bundled": true, + "requires": { + "boom": "4.x.x", + "cryptiles": "3.x.x", + "hoek": "4.x.x", + "sntp": "2.x.x" + } + }, + "hoek": { + "version": "4.2.0", + "bundled": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "bundled": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "htmlparser2": { + "version": "3.8.3", + "bundled": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "http-errors": { + "version": "1.5.1", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": ">= 1.3.1 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.13", + "bundled": true + }, + "immediate": { + "version": "3.0.6", + "bundled": true + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "interpret": { + "version": "1.1.0", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "ipaddr.js": { + "version": "1.4.0", + "bundled": true + }, + "is-absolute": { + "version": "0.2.6", + "bundled": true, + "requires": { + "is-relative": "^0.2.1", + "is-windows": "^0.2.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-cwd": { + "version": "1.0.0", + "bundled": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "bundled": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true + }, + "is-promise": { + "version": "2.1.0", + "bundled": true + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-relative": { + "version": "0.2.1", + "bundled": true, + "requires": { + "is-unc-path": "^0.1.1" + } + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "is-unc-path": { + "version": "0.1.2", + "bundled": true, + "requires": { + "unc-path-regex": "^0.1.0" + } + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true + }, + "is-windows": { + "version": "0.2.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jade": { + "version": "0.26.3", + "bundled": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "bundled": true + }, + "mkdirp": { + "version": "0.3.0", + "bundled": true + } + } + }, + "jasmine": { + "version": "2.8.0", + "bundled": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + } + }, + "jasmine-core": { + "version": "2.8.0", + "bundled": true + }, + "jasminewd2": { + "version": "2.2.0", + "bundled": true + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "jshint": { + "version": "2.9.5", + "bundled": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "3.7.x", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "lodash": { + "version": "3.7.0", + "bundled": true + } + } + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.1.5", + "bundled": true, + "requires": { + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" + } + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lie": { + "version": "3.1.1", + "bundled": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "liftoff": { + "version": "2.3.0", + "bundled": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^0.4.2", + "fined": "^1.0.1", + "flagged-respawn": "^0.3.2", + "lodash.isplainobject": "^4.0.4", + "lodash.isstring": "^4.0.1", + "lodash.mapvalues": "^4.4.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "bundled": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "bundled": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "bundled": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "bundled": true + }, + "lodash._reescape": { + "version": "3.0.0", + "bundled": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "bundled": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.escape": { + "version": "3.2.0", + "bundled": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "bundled": true + }, + "lodash.isarray": { + "version": "3.0.4", + "bundled": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "bundled": true + }, + "lodash.isstring": { + "version": "4.0.1", + "bundled": true + }, + "lodash.keys": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.template": { + "version": "3.6.2", + "bundled": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "bundled": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "loglevel": { + "version": "1.6.1", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.0", + "bundled": true + }, + "lru-cache": { + "version": "2.7.3", + "bundled": true + }, + "lru-queue": { + "version": "0.1.0", + "bundled": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "make-dir": { + "version": "1.1.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "bundled": true + } + } + }, + "map-age-cleaner": { + "version": "0.1.2", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "bundled": true + }, + "map-stream": { + "version": "0.1.0", + "bundled": true + }, + "marked": { + "version": "0.3.12", + "bundled": true + }, + "media-typer": { + "version": "0.3.0", + "bundled": true + }, + "mem": { + "version": "4.0.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "memoizee": { + "version": "0.4.11", + "bundled": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.30", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.2" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "bundled": true + }, + "methods": { + "version": "1.1.2", + "bundled": true + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "mime": { + "version": "1.3.4", + "bundled": true + }, + "mime-db": { + "version": "1.30.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.17", + "bundled": true, + "requires": { + "mime-db": "~1.30.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.1", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "mocha": { + "version": "2.5.3", + "bundled": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + } + }, + "diff": { + "version": "1.4.0", + "bundled": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "bundled": true + }, + "glob": { + "version": "3.2.11", + "bundled": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "minimatch": { + "version": "0.3.0", + "bundled": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true + }, + "supports-color": { + "version": "1.2.0", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "multipipe": { + "version": "0.1.2", + "bundled": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "natives": { + "version": "1.1.3", + "bundled": true + }, + "negotiator": { + "version": "0.6.1", + "bundled": true + }, + "next-tick": { + "version": "1.0.0", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "object.defaults": { + "version": "1.1.0", + "bundled": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "bundled": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "bundled": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true + } + } + }, + "on-finished": { + "version": "2.3.0", + "bundled": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "bundled": true + } + } + }, + "orchestrator": { + "version": "0.3.8", + "bundled": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.0.1", + "bundled": true, + "requires": { + "execa": "^0.10.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.10.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "1.1.0", + "bundled": true + }, + "p-limit": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pako": { + "version": "1.0.6", + "bundled": true + }, + "parse-filepath": { + "version": "1.0.1", + "bundled": true, + "requires": { + "is-absolute": "^0.2.3", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "bundled": true + }, + "parseurl": { + "version": "1.3.2", + "bundled": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true + }, + "path-root": { + "version": "0.1.1", + "bundled": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "bundled": true + }, + "path-to-regexp": { + "version": "0.1.7", + "bundled": true + }, + "pause-stream": { + "version": "0.0.11", + "bundled": true, + "requires": { + "through": "~2.3" + } + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkginfo": { + "version": "0.3.1", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "preserve": { + "version": "0.2.0", + "bundled": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "proxy-addr": { + "version": "1.1.5", + "bundled": true, + "requires": { + "forwarded": "~0.1.0", + "ipaddr.js": "1.4.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.29", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "q": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.5.1", + "bundled": true + }, + "randomatic": { + "version": "1.1.7", + "bundled": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "range-parser": { + "version": "1.2.0", + "bundled": true + }, + "raw-body": { + "version": "2.1.7", + "bundled": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.2", + "bundled": true, + "requires": { + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.0.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "bundled": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "registry-auth-token": { + "version": "3.3.1", + "bundled": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "^1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true + }, + "replace-ext": { + "version": "0.0.1", + "bundled": true + }, + "request": { + "version": "2.83.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "hawk": "~6.0.2", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "stringstream": "~0.0.5", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve": { + "version": "1.5.0", + "bundled": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "bundled": true, + "requires": { + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" + } + }, + "rimraf": { + "version": "2.5.4", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-sequence": { + "version": "1.2.2", + "bundled": true, + "requires": { + "chalk": "*", + "gulp-util": "*" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "saucelabs": { + "version": "1.5.0", + "bundled": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "selenium-webdriver": { + "version": "3.6.0", + "bundled": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + } + } + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "^5.0.3" + } + }, + "send": { + "version": "0.14.2", + "bundled": true, + "requires": { + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.5.1", + "mime": "1.3.4", + "ms": "0.7.2", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + }, + "dependencies": { + "ms": { + "version": "0.7.1", + "bundled": true + } + } + }, + "ms": { + "version": "0.7.2", + "bundled": true + }, + "statuses": { + "version": "1.3.1", + "bundled": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "bundled": true + }, + "serve-static": { + "version": "1.11.2", + "bundled": true, + "requires": { + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "parseurl": "~1.3.1", + "send": "0.14.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "setprototypeof": { + "version": "1.0.2", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "shelljs": { + "version": "0.3.0", + "bundled": true + }, + "sigmund": { + "version": "1.0.1", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "2.1.0", + "bundled": true, + "requires": { + "hoek": "4.x.x" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.4.18", + "bundled": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "sparkles": { + "version": "1.0.0", + "bundled": true + }, + "split": { + "version": "0.3.3", + "bundled": true, + "requires": { + "through": "2" + } + }, + "sshpk": { + "version": "1.13.1", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.4.0", + "bundled": true + }, + "stream-combiner": { + "version": "0.0.4", + "bundled": true, + "requires": { + "duplexer": "~0.1.1" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "bundled": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "bundled": true, + "requires": { + "readable-stream": "^2.0.2" + } + } + } + }, + "stream-consume": { + "version": "0.1.0", + "bundled": true + }, + "stream-equal": { + "version": "0.1.6", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "1.0.0", + "bundled": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "1.0.4", + "bundled": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + }, + "tar": { + "version": "4.4.7", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "^0.7.0" + } + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "bundled": true + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "timers-ext": { + "version": "0.1.2", + "bundled": true, + "requires": { + "es5-ext": "~0.10.14", + "next-tick": "1" + } + }, + "tmp": { + "version": "0.0.30", + "bundled": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "to-iso-string": { + "version": "0.0.2", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.3", + "bundled": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "tslint": { + "version": "4.5.1", + "bundled": true, + "requires": { + "babel-code-frame": "^6.20.0", + "colors": "^1.1.2", + "diff": "^3.0.1", + "findup-sync": "~0.3.0", + "glob": "^7.1.1", + "optimist": "~0.6.0", + "resolve": "^1.1.7", + "tsutils": "^1.1.0", + "update-notifier": "^2.0.0" + }, + "dependencies": { + "diff": { + "version": "3.4.0", + "bundled": true + }, + "findup-sync": { + "version": "0.3.0", + "bundled": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "bundled": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + } + } + }, + "tslint-eslint-rules": { + "version": "3.5.1", + "bundled": true, + "requires": { + "doctrine": "^0.7.2" + } + }, + "tsutils": { + "version": "1.9.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "type-detect": { + "version": "1.0.0", + "bundled": true + }, + "type-is": { + "version": "1.6.15", + "bundled": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.15" + } + }, + "typescript": { + "version": "2.6.2", + "bundled": true + }, + "unc-path-regex": { + "version": "0.1.2", + "bundled": true + }, + "unique-stream": { + "version": "1.0.0", + "bundled": true + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.3.0", + "bundled": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "bundled": true, + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "bundled": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "user-home": { + "version": "1.1.1", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "utils-merge": { + "version": "1.0.0", + "bundled": true + }, + "uuid": { + "version": "3.1.0", + "bundled": true + }, + "v8flags": { + "version": "2.1.1", + "bundled": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "vary": { + "version": "1.1.2", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "0.5.3", + "bundled": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "bundled": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "bundled": true + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.0.34", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "bundled": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "bundled": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "vrsource-tslint-rules": { + "version": "4.0.1", + "bundled": true, + "requires": { + "tslint": "^4.1.1" + } + }, + "webdriver-js-extender": { + "version": "2.1.0", + "bundled": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webdriver-manager": { + "version": "12.0.6", + "bundled": true, + "requires": { + "adm-zip": "^0.4.7", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.78.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "dependencies": { + "adm-zip": { + "version": "0.4.7", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + } + } + }, + "webdriver-manager-replacement": { + "version": "1.1.0", + "bundled": true, + "requires": { + "adm-zip": "^0.4.11", + "loglevel": "^1.6.1", + "request": "^2.87.0", + "semver": "^5.5.0", + "tar": "^4.4.4", + "xml2js": "^0.4.19", + "yargs": "^12.0.1" + }, + "dependencies": { + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.7", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "har-validator": { + "version": "5.1.0", + "bundled": true, + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.21", + "bundled": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "uuid": { + "version": "3.3.2", + "bundled": true + } + } + }, + "which": { + "version": "1.3.0", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "bundled": true + } + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xml2js": { + "version": "0.4.19", + "bundled": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.4", + "bundled": true + }, + "xregexp": { + "version": "4.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "12.0.2", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } +} diff --git a/spec/unit/driverProviders/local_test.js b/spec/unit/driverProviders/local_test.js index 052282551..2ad101674 100644 --- a/spec/unit/driverProviders/local_test.js +++ b/spec/unit/driverProviders/local_test.js @@ -8,19 +8,19 @@ var WriteTo = require('../../../built/logger').WriteTo; var Local = require('../../../built/driverProviders').Local; var webdriver, file; -describe('local connect', function() { - beforeEach(function() { +describe('local connect', () => { + beforeEach(() => { ProtractorError.SUPRESS_EXIT_CODE = true; Logger.setWrite(WriteTo.NONE); }); - afterEach(function() { + afterEach(() => { ProtractorError.SUPRESS_EXIT_CODE = false; Logger.setWrite(WriteTo.CONSOLE); }); - describe('without the selenium standalone jar', function() { - it('should throw an error jar file is not present', function() { + describe('without the selenium standalone jar', () => { + it('should throw an error jar file is not present', async () => { var config = { capabilities: { browserName: 'chrome' }, seleniumServerJar: '/foo/bar/selenium.jar' @@ -28,7 +28,7 @@ describe('local connect', function() { var errorFound = false; try { webdriver = new Local(config); - webdriver.setupEnv(); + await webdriver.setupEnv(); } catch(e) { errorFound = true; expect(e.code).toBe(BrowserError.CODE); @@ -37,8 +37,8 @@ describe('local connect', function() { }); }); - describe('with the selenium standalone jar', function() { - it('should throw an error if the jar file does not work', function() { + describe('with the selenium standalone jar', () => { + it('should throw an error if the jar file does not work', async () => { var jarFile = ''; beforeEach(function() { // add files to selenium folder @@ -54,7 +54,7 @@ describe('local connect', function() { } }); - it('should throw an error if the selenium sever jar cannot be used', function() { + it('should throw an error if the selenium sever jar cannot be used', () => { var config = { capabilities: { browserName: 'foobar explorer' }, seleniumServerJar: jarFile @@ -73,7 +73,7 @@ describe('local connect', function() { }); describe('binary does not exist', () => { - it('should throw an error if the update-config.json does not exist', () => { + it('should throw an error if the update-config.json does not exist', async () => { spyOn(fs, 'readFileSync').and.callFake(() => { return null; }); var config = { capabilities: { browserName: 'chrome' }, @@ -82,7 +82,7 @@ describe('local connect', function() { var errorFound = false; try { webdriver = new Local(config); - webdriver.setupDriverEnv(); + await webdriver.setupDriverEnv(); } catch(e) { errorFound = true; expect(e.code).toBe(BrowserError.CODE); diff --git a/tsconfig.json b/tsconfig.json index 0ac13f1d3..62d315af5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,14 @@ { "compilerOptions": { - "target": "es6", + "target": "es2017", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "declaration": true, "removeComments": false, "noImplicitAny": true, - "outDir": "built/" + "outDir": "built/", + "lib": ["es2017"] }, "exclude": [ "built", From 84fe80fd9691b10b78f77e06b6dedb6720c56acf Mon Sep 17 00:00:00 2001 From: Craig Nishina Date: Wed, 21 Nov 2018 16:04:03 -0800 Subject: [PATCH 4/4] cleaned up - Removed jshint to reduce noise. We will not need this when switching suite to TypeScript. - Changed Protractor configuration files to be ".conf.js" for uniformity (I was trying to exclude ".conf.js" from jshint. After removing jshint, this decision seems pointless but cleaner?) - Cleaned up logging. Ran all the tests and most seem to pass. There are some issues where catching and unhandled promises throwing errors report slightly differently. - Fixed the driverProviderAttachSession test. --- .jshintignore | 1 - .jshintrc | 28 -- gulpfile.js | 15 +- lib/browser.ts | 25 +- lib/driverProviders/attachSession.ts | 2 +- lib/driverProviders/driverProvider.ts | 2 +- lib/launcher.ts | 301 +++++++++--------- lib/runner.ts | 22 +- lib/util.ts | 1 - package-lock.json | 149 --------- package.json | 1 - scripts/driverProviderAttachSession.js | 207 ++++++------ scripts/errorTest.js | 25 +- scripts/test.js | 102 +++--- spec/{altRootConf.js => altRoot.conf.js} | 0 spec/{angular2Conf.js => angular2.conf.js} | 0 ...TimeoutConf.js => angular2Timeout.conf.js} | 1 + spec/{basicConf.js => basic.conf.js} | 2 +- spec/basic/handling_spec.js | 9 - spec/{ciBStackConf.js => ciBStack.conf.js} | 0 spec/{ciFullConf.js => ciFull.conf.js} | 0 spec/{ciNg2Conf.js => ciNg2.conf.js} | 0 spec/{ciSmokeConf.js => ciSmoke.conf.js} | 0 ...controlLockConf.js => controlLock.conf.js} | 0 ...omFramework.js => customFramework.conf.js} | 0 ...ctConnectConf.js => directConnect.conf.js} | 0 ...js => driverProviderAttachSession.conf.js} | 1 + ...calConf.js => driverProviderLocal.conf.js} | 0 .../attachSession/attachSession_spec.js | 8 +- ...der_test.js => driverproviderTest.conf.js} | 0 spec/environment.js | 4 +- ....js => afterLaunchChangesExitCode.conf.js} | 0 ....js => browserStackAuthentication.conf.js} | 0 ...ties.js => debugMultiCapabilities.conf.js} | 0 ...esConf.js => getMultiCapabilities.conf.js} | 0 ...chaFailureConf.js => mochaFailure.conf.js} | 0 ...ltiFailureConf.js => multiFailure.conf.js} | 0 ...sFailingConf.js => pluginsFailing.conf.js} | 0 ...ion.js => sauceLabsAuthentication.conf.js} | 0 ...dFailureConf.js => shardedFailure.conf.js} | 0 ...leFailureConf.js => singleFailure.conf.js} | 0 ...eoutConf.js => slowHttpAndTimeout.conf.js} | 0 .../{timeoutConf.js => timeout.conf.js} | 0 ...ilitiesConf.js => getCapabilities.conf.js} | 0 spec/{hybridConf.js => hybrid.conf.js} | 0 spec/{inferRootConf.js => inferRoot.conf.js} | 0 ...interactionConf.js => interaction.conf.js} | 0 spec/{mochaConf.js => mocha.conf.js} | 0 spec/{multiConf.js => multi.conf.js} | 0 spec/ng2/timeout_spec.js | 12 +- spec/{noGlobalsConf.js => noGlobals.conf.js} | 0 ...f.js => onCleanUpAsyncReturnValue.conf.js} | 0 ...Conf.js => onCleanUpNoReturnValue.conf.js} | 0 ...nf.js => onCleanUpSyncReturnValue.conf.js} | 0 spec/{onPrepareConf.js => onPrepare.conf.js} | 0 ...epareFileConf.js => onPrepareFile.conf.js} | 0 ...romiseConf.js => onPreparePromise.conf.js} | 0 ...leConf.js => onPreparePromiseFile.conf.js} | 0 ...SyncedConf.js => browserGetSynced.conf.js} | 0 ...ncedConf.js => browserGetUnsynced.conf.js} | 0 spec/plugins/jasminePostTest.conf.js | 1 + spec/plugins/jasminePostTestConf.js | 1 - spec/plugins/mochaPostTest.conf.js | 1 + spec/plugins/mochaPostTestConf.js | 1 - ...multiPluginConf.js => multiPlugin.conf.js} | 0 ...mplate.js => postTestConfTemplate.conf.js} | 0 ...StabilityConf.js => skipStability.conf.js} | 0 spec/plugins/{smokeConf.js => smoke.conf.js} | 0 ...rAngularConf.js => waitForAngular.conf.js} | 0 ....js => restartBrowserBetweenTests.conf.js} | 0 .../setCookies_spec.js | 4 +- spec/{shardingConf.js => sharding.conf.js} | 0 spec/{suitesConf.js => suites.conf.js} | 0 .../{noCFBasicConf.ts => noCFBasic.conf.ts} | 0 .../{noCFPluginConf.ts => noCFPlugin.conf.ts} | 0 spec/unit/runner_test.js | 59 ++-- spec/{withLoginConf.js => withLogin.conf.js} | 0 77 files changed, 398 insertions(+), 587 deletions(-) delete mode 100644 .jshintignore delete mode 100644 .jshintrc rename spec/{altRootConf.js => altRoot.conf.js} (100%) rename spec/{angular2Conf.js => angular2.conf.js} (100%) rename spec/{angular2TimeoutConf.js => angular2Timeout.conf.js} (95%) rename spec/{basicConf.js => basic.conf.js} (94%) rename spec/{ciBStackConf.js => ciBStack.conf.js} (100%) rename spec/{ciFullConf.js => ciFull.conf.js} (100%) rename spec/{ciNg2Conf.js => ciNg2.conf.js} (100%) rename spec/{ciSmokeConf.js => ciSmoke.conf.js} (100%) rename spec/{controlLockConf.js => controlLock.conf.js} (100%) rename spec/{customFramework.js => customFramework.conf.js} (100%) rename spec/{directConnectConf.js => directConnect.conf.js} (100%) rename spec/{driverProviderAttachSessionConf.js => driverProviderAttachSession.conf.js} (87%) rename spec/{driverProviderLocalConf.js => driverProviderLocal.conf.js} (100%) rename spec/{driverprovider_test.js => driverproviderTest.conf.js} (100%) rename spec/errorTest/{afterLaunchChangesExitCodeConf.js => afterLaunchChangesExitCode.conf.js} (100%) rename spec/errorTest/{browserStackAuthentication.js => browserStackAuthentication.conf.js} (100%) rename spec/errorTest/{debugMultiCapabilities.js => debugMultiCapabilities.conf.js} (100%) rename spec/errorTest/{getMultiCapabilitiesConf.js => getMultiCapabilities.conf.js} (100%) rename spec/errorTest/{mochaFailureConf.js => mochaFailure.conf.js} (100%) rename spec/errorTest/{multiFailureConf.js => multiFailure.conf.js} (100%) rename spec/errorTest/{pluginsFailingConf.js => pluginsFailing.conf.js} (100%) rename spec/errorTest/{sauceLabsAuthentication.js => sauceLabsAuthentication.conf.js} (100%) rename spec/errorTest/{shardedFailureConf.js => shardedFailure.conf.js} (100%) rename spec/errorTest/{singleFailureConf.js => singleFailure.conf.js} (100%) rename spec/errorTest/{slowHttpAndTimeoutConf.js => slowHttpAndTimeout.conf.js} (100%) rename spec/errorTest/{timeoutConf.js => timeout.conf.js} (100%) rename spec/{getCapabilitiesConf.js => getCapabilities.conf.js} (100%) rename spec/{hybridConf.js => hybrid.conf.js} (100%) rename spec/{inferRootConf.js => inferRoot.conf.js} (100%) rename spec/{interactionConf.js => interaction.conf.js} (100%) rename spec/{mochaConf.js => mocha.conf.js} (100%) rename spec/{multiConf.js => multi.conf.js} (100%) rename spec/{noGlobalsConf.js => noGlobals.conf.js} (100%) rename spec/{onCleanUpAsyncReturnValueConf.js => onCleanUpAsyncReturnValue.conf.js} (100%) rename spec/{onCleanUpNoReturnValueConf.js => onCleanUpNoReturnValue.conf.js} (100%) rename spec/{onCleanUpSyncReturnValueConf.js => onCleanUpSyncReturnValue.conf.js} (100%) rename spec/{onPrepareConf.js => onPrepare.conf.js} (100%) rename spec/{onPrepareFileConf.js => onPrepareFile.conf.js} (100%) rename spec/{onPreparePromiseConf.js => onPreparePromise.conf.js} (100%) rename spec/{onPreparePromiseFileConf.js => onPreparePromiseFile.conf.js} (100%) rename spec/plugins/{browserGetSyncedConf.js => browserGetSynced.conf.js} (100%) rename spec/plugins/{browserGetUnsyncedConf.js => browserGetUnsynced.conf.js} (100%) create mode 100644 spec/plugins/jasminePostTest.conf.js delete mode 100644 spec/plugins/jasminePostTestConf.js create mode 100644 spec/plugins/mochaPostTest.conf.js delete mode 100644 spec/plugins/mochaPostTestConf.js rename spec/plugins/{multiPluginConf.js => multiPlugin.conf.js} (100%) rename spec/plugins/{postTestConfTemplate.js => postTestConfTemplate.conf.js} (100%) rename spec/plugins/{skipStabilityConf.js => skipStability.conf.js} (100%) rename spec/plugins/{smokeConf.js => smoke.conf.js} (100%) rename spec/plugins/{waitForAngularConf.js => waitForAngular.conf.js} (100%) rename spec/{restartBrowserBetweenTestsConf.js => restartBrowserBetweenTests.conf.js} (100%) rename spec/{shardingConf.js => sharding.conf.js} (100%) rename spec/{suitesConf.js => suites.conf.js} (100%) rename spec/ts/{noCFBasicConf.ts => noCFBasic.conf.ts} (100%) rename spec/ts/{noCFPluginConf.ts => noCFPlugin.conf.ts} (100%) rename spec/{withLoginConf.js => withLogin.conf.js} (100%) diff --git a/.jshintignore b/.jshintignore deleted file mode 100644 index 2442be841..000000000 --- a/.jshintignore +++ /dev/null @@ -1 +0,0 @@ -./spec/built/* diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index a48f2aa66..000000000 --- a/.jshintrc +++ /dev/null @@ -1,28 +0,0 @@ -{ - "unused": true, - "node": true, - "bitwise": true, - "immed": true, - "newcap": true, - "noarg": true, - "noempty": true, - "nonew": true, - "trailing": true, - "maxlen": 100, - "boss": true, - "eqnull": true, - "expr": true, - "laxbreak": true, - "loopfunc": true, - "sub": true, - "undef": true, - "quotmark": "single", - "evil": true, - "curly": true, - "esversion": 6, - "predef": ["$", "$$", "angular", "after", "afterAll", "afterEach", - "beforeAll", "beforeEach", "browser", "by", "By", "DartObject", - "describe", "document", "element", "expect", "ExpectedConditions", - "fdescribe", "fit", "it", "jasmine", "protractor", "spyOn", - "xdescribe", "xit"] -} diff --git a/gulpfile.js b/gulpfile.js index 8bf144e16..454711504 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -41,7 +41,7 @@ gulp.task('tslint', function() { }); gulp.task('lint', function(done) { - runSequence('tslint', 'jshint', 'format:enforce', done); + runSequence('tslint', 'format:enforce', done); }); // prevent contributors from using the wrong version of node @@ -59,22 +59,15 @@ gulp.task('checkVersion', function(done) { } }); -gulp.task('built:copy', function(done) { +gulp.task('built:copy', function() { return gulp.src(['lib/**/*.js']) .pipe(gulp.dest('built/')); - done(); }); gulp.task('webdriver:update', function(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:enforce', function() { var format = require('gulp-clang-format'); @@ -107,12 +100,12 @@ gulp.task('compile_to_es5', function(done) { }); gulp.task('prepublish', function(done) { - runSequence('checkVersion', 'jshint', 'tsc', 'built:copy', done); + runSequence('checkVersion', 'tsc', 'built:copy', done); }); gulp.task('pretest', function(done) { runSequence('checkVersion', - ['webdriver:update', 'jshint', 'tslint', 'format'], 'tsc', 'built:copy', 'tsc:spec', done); + ['webdriver:update', 'tslint', 'format'], 'tsc', 'built:copy', 'tsc:spec', done); }); gulp.task('default',['prepublish']); diff --git a/lib/browser.ts b/lib/browser.ts index 5f7ff970b..8e7a0156d 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -585,13 +585,13 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { return null; } else { try { - const rootEl = await this.angularAppRoot(); - return this.executeAsyncScript_( - clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, rootEl); - } - catch (err) { - console.log('something wrong happened here'); - } + const rootEl = await this.angularAppRoot(); + return this.executeAsyncScript_( + clientSideScripts.waitForAngular, `Protractor.waitForAngular() ${description}`, + rootEl); + } catch (err) { + console.log('something wrong happened here'); + } } }; @@ -708,11 +708,6 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { * Modules will be registered after existing modules already on the page, * so any module registered here will override preexisting modules with the * same name. - *"both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. S - *"both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. S - * browser.addMockModule('modName', function() { - * angular.module('modName', []).value('foo', 'bar'); - * }); * * @param {!string} name The name of the module to load or override. * @param {!string|Function} script The JavaScript to load the module. @@ -769,8 +764,6 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { this.trackOutstandingTimeouts_); } - - navigating = false; /** * @see webdriver.WebDriver.get * @@ -909,7 +902,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { } const href = await this.executeScriptWithDescription( - 'return window.location.href', 'Protractor.refresh() - getUrl'); + 'return window.location.href', 'Protractor.refresh() - getUrl'); return this.get(href, opt_timeout); } @@ -998,7 +991,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver { */ async debugger() { // jshint debug: true - await this.driver.executeScript(clientSideScripts.installInBrowser) + await this.driver.executeScript(clientSideScripts.installInBrowser); debugger; } diff --git a/lib/driverProviders/attachSession.ts b/lib/driverProviders/attachSession.ts index 37f6fe0a2..226ee63d2 100644 --- a/lib/driverProviders/attachSession.ts +++ b/lib/driverProviders/attachSession.ts @@ -38,7 +38,7 @@ export class AttachSession extends DriverProvider { getNewDriver(): WebDriver { const httpClient = new http.HttpClient(this.config_.seleniumAddress); const executor = new http.Executor(httpClient); - const newDriver = WebDriver.attachToSession(executor, this.config_.seleniumSessionId); + const newDriver = WebDriver.attachToSession(executor, this.config_.seleniumSessionId, null); this.drivers_.push(newDriver); return newDriver; } diff --git a/lib/driverProviders/driverProvider.ts b/lib/driverProviders/driverProvider.ts index c95000628..6e3a03762 100644 --- a/lib/driverProviders/driverProvider.ts +++ b/lib/driverProviders/driverProvider.ts @@ -3,7 +3,7 @@ * It is responsible for setting up the account object, tearing * it down, and setting up the driver correctly. */ -import {Builder, Session, WebDriver} from 'selenium-webdriver'; +import {Builder, WebDriver} from 'selenium-webdriver'; import {BlockingProxyRunner} from '../bpRunner'; import {Config} from '../config'; diff --git a/lib/launcher.ts b/lib/launcher.ts index 8d077d03b..a9cb9131a 100644 --- a/lib/launcher.ts +++ b/lib/launcher.ts @@ -107,179 +107,170 @@ let initFn = async function(configFile: string, additionalConfig: Config) { logger.debug('Your base url for tests is ' + config.baseUrl); // Run beforeLaunch - await helper.runFilenameOrFn_(config.configDir, config.beforeLaunch).then(async () => { - // 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. - const waitMultiConfig = await config.getMultiCapabilities(); - config.multiCapabilities = waitMultiConfig; - config.capabilities = null; + await helper.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'); } + // If getMultiCapabilities is defined and a function, use this. + const waitMultiConfig = await 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'); - } 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'}]; + // 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'}]; + } - // 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]; - } - config.framework = 'explorer'; - + // 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]; + } + config.framework = 'explorer'; + try { let runner = new Runner(config); - - try { - let exitCode = await runner.run(); - console.log('runner', exitCode); - process.exit(exitCode); - } catch (err) { - logger.error(err); - process.exit(1); - } + let exitCode = await runner.run(); + process.exit(exitCode); + } catch (err) { + logger.error(err); + process.exit(1); } + } - // 4) Run tests. - let scheduler = new TaskScheduler(config); + // 4) Run tests. + let scheduler = new TaskScheduler(config); - process.on('uncaughtException', (exc: (Error|string)) => { - let e = (exc instanceof Error) ? exc : new Error(exc); - if (config.ignoreUncaughtExceptions) { - // This can be a sign of a bug in the test framework, that it may - // not be handling WebDriver errors properly. However, we don't - // want these errors to prevent running the tests. - logger.warn('Ignoring uncaught error ' + exc); - return; - } - let errorCode = ErrorHandler.parseError(e); - if (errorCode) { - let protractorError = e as ProtractorError; - ProtractorError.log(logger, errorCode, protractorError.message, protractorError.stack); - process.exit(errorCode); - } else { - logger.error(e.message); - logger.error(e.stack); - process.exit(ProtractorError.CODE); - } - }); + // process.on('uncaughtException', (exc: (Error|string)) => { + // let e = (exc instanceof Error) ? exc : new Error(exc); + // if (config.ignoreUncaughtExceptions) { + // // This can be a sign of a bug in the test framework, that it may + // // not be handling WebDriver errors properly. However, we don't + // // want these errors to prevent running the tests. + // logger.warn('Ignoring uncaught error ' + exc); + // return; + // } - process.on('exit', (code: number) => { - console.log(code); - if (code) { - logger.error('Process exited with error code ' + code); - } else if (scheduler.numTasksOutstanding() > 0) { - console.log('scheduler num task outstanding: ', scheduler.numTasksOutstanding()); - logger.error( - 'BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining'); - process.exit(RUNNERS_FAILED_EXIT_CODE); - } - }); + // let errorCode = ErrorHandler.parseError(e); + // if (errorCode) { + // let protractorError = e as ProtractorError; + // ProtractorError.log(logger, errorCode, protractorError.message, protractorError.stack); + // process.exit(errorCode); + // } else { + // logger.error(e.message); + // logger.error(e.stack); + // process.exit(ProtractorError.CODE); + // } + // }); - // Run afterlaunch and exit - let cleanUpAndExit = (exitCode: number) => { - console.log('cleanUpAndExit'); - return helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]) - .then( - (returned) => { - if (typeof returned === 'number') { - console.log('returned:', returned); - process.exit(returned); - } else { - console.log('exitCode:', exitCode); - process.exit(exitCode); - } - }, - (err: Error) => { - logger.error('Error:', err); - process.exit(1); - }); - }; + process.on('exit', (code: number) => { + if (code) { + logger.error('Process exited with error code ' + code); + } else if (scheduler.numTasksOutstanding() > 0) { + logger.error( + 'BUG: launcher exited with ' + scheduler.numTasksOutstanding() + ' tasks remaining'); + process.exit(RUNNERS_FAILED_EXIT_CODE); + } + }); - let totalTasks = scheduler.numTasksOutstanding(); - let forkProcess = false; - if (totalTasks > 1) { // Start new processes only if there are >1 tasks. - forkProcess = true; - if (config.debug) { - throw new ConfigError( - logger, 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding'); + // Run afterlaunch and exit + const cleanUpAndExit = async (exitCode: number) => { + try { + let returned = + await helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]); + if (typeof returned === 'number') { + process.exit(returned); + } else { + process.exit(exitCode); } + } catch (err) { + logger.error('Error:', err); + process.exit(1); } + }; - const createNextTaskRunner = async () => { - return new Promise(resolve => { - let task = scheduler.nextTask(); - if (task) { - let taskRunner = new TaskRunner(configFile, additionalConfig, task, forkProcess); - taskRunner.run() - .then(async (result) => { - if (result.exitCode && !result.failedCount) { - logger.error( - 'Runner process exited unexpectedly with error code: ' + result.exitCode); - } - taskResults_.add(result); - task.done(); - createNextTaskRunner(); - // If all tasks are finished - if (scheduler.numTasksOutstanding() === 0) { - resolve(); - } - logger.info( - scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); - }) - .catch((err: Error) => { - logger.error('Error:', (err as any).stack || err.message || err); - cleanUpAndExit(RUNNERS_FAILED_EXIT_CODE); - }); - } - }); - }; - - for (let i = 0; i < scheduler.maxConcurrentTasks(); ++i) { - await createNextTaskRunner(); + let totalTasks = scheduler.numTasksOutstanding(); + let forkProcess = false; + if (totalTasks > 1) { // Start new processes only if there are >1 tasks. + forkProcess = true; + if (config.debug) { + throw new ConfigError( + logger, 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding'); } - logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver'); + } - // By now all runners have completed. - // Save results if desired - if (config.resultJsonOutputFile) { - taskResults_.saveResults(config.resultJsonOutputFile); - } + const createNextTaskRunner = async () => { + return new Promise(resolve => { + let task = scheduler.nextTask(); + if (task) { + let taskRunner = new TaskRunner(configFile, additionalConfig, task, forkProcess); + taskRunner.run() + .then(async (result) => { + if (result.exitCode && !result.failedCount) { + logger.error( + 'Runner process exited unexpectedly with error code: ' + result.exitCode); + } + taskResults_.add(result); + task.done(); + createNextTaskRunner(); + // If all tasks are finished + if (scheduler.numTasksOutstanding() === 0) { + resolve(); + } + logger.info(scheduler.countActiveTasks() + ' instance(s) of WebDriver still running'); + }) + .catch(async (err: Error) => { + const errorCode = ErrorHandler.parseError(err); + logger.error('Error:', (err as any).stack || err.message || err); + await cleanUpAndExit(errorCode ? errorCode : RUNNERS_FAILED_EXIT_CODE); + }); + } + }); + }; - taskResults_.reportSummary(); - let exitCode = 0; - if (taskResults_.totalProcessFailures() > 0) { - exitCode = RUNNERS_FAILED_EXIT_CODE; - } else if (taskResults_.totalSpecFailures() > 0) { - exitCode = 1; - } - await cleanUpAndExit(exitCode); - // 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) { + await createNextTaskRunner(); + } + logger.info('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver'); + + // By now all runners have completed. + // 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; + } + await cleanUpAndExit(exitCode); + // 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. - }); }; export let init = initFn; diff --git a/lib/runner.ts b/lib/runner.ts index f46f66bd2..110bcb7e6 100644 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -144,13 +144,11 @@ export class Runner extends EventEmitter { * @param {int} Standard unix exit code */ async exit_(exitCode: number): Promise { - console.log('exit_', exitCode); - let returned = await helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]); - console.log('exit_', returned); + let returned = + await helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]); if (typeof returned === 'number') { return returned; } else { - console.log('exit_ returns', exitCode); return exitCode; } } @@ -359,7 +357,7 @@ export class Runner extends EventEmitter { // 0) Wait for debugger await Promise.resolve(this.ready_); - + // 1) Setup environment // noinspection JSValidateTypes await this.driverprovider_.setupEnv(); @@ -370,13 +368,13 @@ export class Runner extends EventEmitter { try { let session = await browser_.ready.then(browser_.getSession); logger.debug( - 'WebDriver session successfully started with capabilities ' + - util.inspect(session.getCapabilities())); + 'WebDriver session successfully started with capabilities ' + + util.inspect(session.getCapabilities())); } catch (err) { logger.error('Unable to start a WebDriver session.'); throw err; } - + // 3) Setup plugins await plugins.setup(); @@ -431,7 +429,7 @@ export class Runner extends EventEmitter { }); logger.debug('Running with spec files ' + this.config_.specs); let testResults = await require(frameworkPath).run(this, this.config_.specs); - + // 5) Wait for postTest plugins to finish results = testResults; await Promise.all(pluginPostTestPromises); @@ -452,14 +450,12 @@ export class Runner extends EventEmitter { // 8) Let plugins do final cleanup await plugins.postResults(); - + // 9) Exit process - console.log('testpassed', testPassed); const exitCode = testPassed ? 0 : 1; - console.log('exitCode', exitCode); await this.shutdown_(); - + return this.exit_(exitCode); } } diff --git a/lib/util.ts b/lib/util.ts index 2dbc8a40b..f6e2000f8 100644 --- a/lib/util.ts +++ b/lib/util.ts @@ -61,7 +61,6 @@ export function runFilenameOrFn_(configDir: string, filenameOrFn: any, args?: an } resolve(results); } else { - console.log('we are returning undefined from runFilenameOrFn_'); resolve(undefined); } }); diff --git a/package-lock.json b/package-lock.json index 40781e592..bfdc52fdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -478,16 +478,6 @@ "resolve": "^1.1.6" } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, "cli-boxes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", @@ -617,15 +607,6 @@ } } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -733,12 +714,6 @@ "assert-plus": "^1.0.0" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, "dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", @@ -879,55 +854,6 @@ } } }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", @@ -1019,12 +945,6 @@ } } }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, "es5-ext": { "version": "0.10.38", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", @@ -1953,39 +1873,6 @@ "parse-passwd": "^1.0.0" } }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - } - } - }, "http-errors": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", @@ -2351,30 +2238,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, - "jshint": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", - "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", - "dev": true, - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "3.7.x", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "lodash": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", - "dev": true - } - } - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -3736,12 +3599,6 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -3909,12 +3766,6 @@ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", diff --git a/package.json b/package.json index 1bcea3357..f96845366 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "gulp": "^3.9.1", "gulp-clang-format": "1.0.23", "gulp-tslint": "^7.0.1", - "jshint": "^2.9.2", "lodash": "^4.5.1", "marked": "^0.3.3", "mocha": "2.5.3", diff --git a/scripts/driverProviderAttachSession.js b/scripts/driverProviderAttachSession.js index 8612f9a44..9f77fe5d4 100644 --- a/scripts/driverProviderAttachSession.js +++ b/scripts/driverProviderAttachSession.js @@ -2,105 +2,130 @@ 'use strict'; -var http = require('http'), - spawn = require('child_process').spawnSync; +const http = require('http'); +const child_process = require('child_process'); -var sessionId = ''; - -// 1. Create a new selenium session. -var postData = JSON.stringify( - {'desiredCapabilities': {'browserName': 'firefox'}}); -var createOptions = { - hostname: 'localhost', - port: 4444, - path: '/wd/hub/session', - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': Buffer.byteLength(postData) - } -}; -var req = http.request(createOptions, function(res) { - res.on('data', setBody); - res.on('end', checkSession); -}); -req.write(postData); -req.end(); - -// 2. After making the request to create a selenium session, read the selenium -// session id. -var setBody = function(chunk) { - var body = chunk.toString(); - sessionId = JSON.parse(body).sessionId; +// Delete session method to be used at the end of the test as well as +// when the tests fail. +const deleteSession = async (sessionId, err) => { + await new Promise(resolve => { + const deleteOptions = { + hostname: 'localhost', + port: 4444, + path: '/wd/hub/session/' + sessionId, + method: 'DELETE' + }; + var req = http.request(deleteOptions, res => { + res.on('end', () => { + if (err) { + throw err; + } + resolve(); + }); + }); + req.end(); + }); }; -// 3. After getting the session id, verify that the selenium session exists. -// If the session exists, run the protractor test. -var checkSession = function() { - var checkOptions = { - hostname: 'localhost', - port: 4444, - path: '/wd/hub/session/' + sessionId, - method: 'GET' - }; - var state = ''; - var req = http.request(checkOptions, function(res) { - res.on('data', function(chunk) { - state = JSON.parse(chunk.toString()).state; - }); - res.on('end', function() { - if (state === 'success') { - var runProtractor = spawn('node', - ['bin/protractor', 'spec/driverProviderAttachSessionConf.js', - '--seleniumSessionId=' + sessionId]); - console.log(runProtractor.stdout.toString()); - if (runProtractor.status !== 0) { - throw new Error('Protractor did not run properly.'); - } +const run = async () => { + // 1. Create a new selenium session. + const sessionId = await new Promise(resolve => { + const postData = JSON.stringify( + {'desiredCapabilities': {'browserName': 'chrome'}}); + const createOptions = { + hostname: '127.0.0.1', + port: 4444, + path: '/wd/hub/session', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(postData) } - else { - throw new Error('The selenium session was not created.'); - } - checkStoppedSession(); + }; + let body = ''; + const req = http.request(createOptions, (res) => { + res.on('data', (data) => { + body = JSON.parse(data.toString()); + }); + res.on('end', () => { + resolve(body.sessionId); + }); }); + req.write(postData); + req.end(); }); - req.end(); -}; -// 4. After the protractor test completes, check to see that the session still -// exists. If we can find the session, delete it. -var checkStoppedSession = function() { - var checkOptions = { - hostname: 'localhost', - port: 4444, - path: '/wd/hub/session/' + sessionId, - method: 'GET' - }; - var state = ''; - var req = http.request(checkOptions, function(res) { - res.on('data', function(chunk) { - state = JSON.parse(chunk.toString()).state; + await new Promise(resolve => { + // 2. After getting the session id, verify that the selenium session exists. + // If the session exists, run the protractor test. + const checkOptions = { + hostname: '127.0.0.1', + port: 4444, + path: '/wd/hub/sessions', + method: 'GET' + }; + + let values = []; + const req = http.request(checkOptions, (res) => { + res.on('data', (chunk) => { + values = JSON.parse(chunk.toString())['value']; + }); + res.on('end', () => { + let found = false; + for (let value of values) { + if (value['id'] === sessionId) { + found = true; + } + } + if (found) { + resolve(); + } else { + throw new Error('The selenium session was not created.'); + } + }); }); - res.on('end', function() { - if (state === 'success') { - deleteSession(); - } - else { - throw new Error('The selenium session should still exist.'); - } + req.end(); + }); + + // 3. Run Protractor and attach to the session. + const runProtractor = child_process.spawnSync('node', + ['bin/protractor', 'spec/driverProviderAttachSession.conf.js', + '--seleniumSessionId=' + sessionId]); + console.log(runProtractor.stdout.toString()); + if (runProtractor.status !== 0) { + const e = new Error('Protractor did not run properly.'); + deleteSession(sessionId, e); + } + + // 4. After the protractor test completes, check to see that the session still + // exists. If we can find the session, delete it. + await new Promise(resolve => { + const checkOptions = { + hostname: '127.0.0.1', + port: 4444, + path: '/wd/hub/session/' + sessionId, + method: 'GET' + }; + const req = http.request(checkOptions, (res) => { + let state = ''; + res.on('data', (chunk) => { + state = JSON.parse(chunk.toString()).state; + }); + res.on('end', function() { + if (state === 'success') { + resolve(); + } + else { + const e = new Error('The selenium session should still exist.'); + deleteSession(sessionId, e); + } + }); }); + req.end(); }); - req.end(); -}; -// 5. Delete the selenium session. -var deleteSession = function() { - var deleteOptions = { - hostname: 'localhost', - port: 4444, - path: '/wd/hub/session/' + sessionId, - method: 'DELETE' - }; - var req = http.request(deleteOptions); - req.end(); -}; + // 5. Delete the selenium session. + await deleteSession(sessionId); +} + +run().then(); \ No newline at end of file diff --git a/scripts/errorTest.js b/scripts/errorTest.js index 67b72a498..709a3c7cb 100644 --- a/scripts/errorTest.js +++ b/scripts/errorTest.js @@ -2,15 +2,14 @@ 'use strict'; -var spawn = require('child_process').spawnSync; -var exitCodes = require('../built/exitCodes'); +const spawn = require('child_process').spawnSync; +const exitCodes = require('../built/exitCodes'); -var runProtractor, output, messages; -var checkLogs = function(output, messages) { - for (var pos in messages) { - var message = messages[pos]; +let runProtractor, output, messages; +const checkLogs = (output, messages) => { + for (let message of messages) { if (output.indexOf(message) === -1) { - throw new Error('\'' + message + '\'' + ' does not exist in logs: ' + output); + throw new Error(`'${message}' does not exist in logs: ${output}`); } } }; @@ -21,24 +20,24 @@ var checkLogs = function(output, messages) { // assert authentication error for sauce labs runProtractor = spawn('node', - ['bin/protractor', 'spec/errorTest/sauceLabsAuthentication.js']); + ['bin/protractor', 'spec/errorTest/sauceLabsAuthentication.conf.js']); output = runProtractor.stdout.toString(); -messages = ['Sauce Labs Authentication Error.', +messages = [ + 'WebDriverError: Misconfigured -- Sauce Labs Authentication Error.', 'Process exited with error code ' + exitCodes.BrowserError.CODE]; checkLogs(output, messages); // assert authentication error for browser stack runProtractor = spawn('node', - ['bin/protractor', 'spec/errorTest/browserStackAuthentication.js']); + ['bin/protractor', 'spec/errorTest/browserStackAuthentication.conf.js']); output = runProtractor.stdout.toString(); messages = ['WebDriverError: Invalid username or password', 'Process exited with error code ' + exitCodes.BrowserError.CODE]; checkLogs(output, messages); - // assert there is no capabilities in the config runProtractor = spawn('node', - ['bin/protractor', 'spec/errorTest/debugMultiCapabilities.js']); + ['bin/protractor', 'spec/errorTest/debugMultiCapabilities.conf.js']); output = runProtractor.stdout.toString(); messages = [ 'Cannot run in debug mode with multiCapabilities, count > 1, or sharding', @@ -46,7 +45,7 @@ messages = [ checkLogs(output, messages); runProtractor = spawn('node', - ['bin/protractor', 'spec/errorTest/getMultiCapabilitiesConf.js']); + ['bin/protractor', 'spec/errorTest/getMultiCapabilities.conf.js']); output = runProtractor.stderr.toString(); messages = [ 'Error: get multi capabilities failed']; diff --git a/scripts/test.js b/scripts/test.js index 68c594c8c..9b947bcdb 100755 --- a/scripts/test.js +++ b/scripts/test.js @@ -4,47 +4,47 @@ var path = require('path'); var Executor = require('./test/test_util').Executor; var passingTests = [ - 'node built/cli.js spec/basicConf.js', - 'node built/cli.js spec/basicConf.js --useBlockingProxy', - 'node built/cli.js spec/multiConf.js', - 'node built/cli.js spec/altRootConf.js', - 'node built/cli.js spec/inferRootConf.js', - 'node built/cli.js spec/onCleanUpAsyncReturnValueConf.js', - 'node built/cli.js spec/onCleanUpNoReturnValueConf.js', - 'node built/cli.js spec/onCleanUpSyncReturnValueConf.js', - 'node built/cli.js spec/onPrepareConf.js', - 'node built/cli.js spec/onPrepareFileConf.js', - 'node built/cli.js spec/onPreparePromiseConf.js', - 'node built/cli.js spec/onPreparePromiseFileConf.js', - 'node built/cli.js spec/mochaConf.js', - 'node built/cli.js spec/withLoginConf.js', - 'node built/cli.js spec/suitesConf.js --suite okmany', - 'node built/cli.js spec/suitesConf.js --suite okspec', - 'node built/cli.js spec/suitesConf.js --suite okmany,okspec', - 'node built/cli.js spec/plugins/smokeConf.js', - 'node built/cli.js spec/plugins/multiPluginConf.js', - 'node built/cli.js spec/plugins/jasminePostTestConf.js', - 'node built/cli.js spec/plugins/mochaPostTestConf.js', - 'node built/cli.js spec/plugins/browserGetSyncedConf.js', - 'node built/cli.js spec/plugins/browserGetUnsyncedConf.js', - 'node built/cli.js spec/plugins/waitForAngularConf.js', - 'node built/cli.js spec/interactionConf.js', - 'node built/cli.js spec/directConnectConf.js', - 'node built/cli.js spec/restartBrowserBetweenTestsConf.js', - 'node built/cli.js spec/driverProviderLocalConf.js', - 'node built/cli.js spec/driverProviderLocalConf.js --useBlockingProxy', - 'node built/cli.js spec/getCapabilitiesConf.js', - 'node built/cli.js spec/controlLockConf.js', - 'node built/cli.js spec/customFramework.js', - 'node built/cli.js spec/noGlobalsConf.js', - // 'node built/cli.js spec/angular2Conf.js', - 'node built/cli.js spec/hybridConf.js', - 'node built/cli.js spec/built/noCFBasicConf.js', - 'node built/cli.js spec/built/noCFBasicConf.js --useBlockingProxy', - 'node built/cli.js spec/built/noCFPluginConf.js', - // //'node scripts/driverProviderAttachSession.js', - // 'node scripts/errorTest.js', - // // Interactive Element Explorer tasks + 'node built/cli.js spec/basic.conf.js', + 'node built/cli.js spec/basic.conf.js --useBlockingProxy', + 'node built/cli.js spec/multi.conf.js', + 'node built/cli.js spec/altRoot.conf.js', + 'node built/cli.js spec/inferRoot.conf.js', + 'node built/cli.js spec/onCleanUpAsyncReturnValue.conf.js', + 'node built/cli.js spec/onCleanUpNoReturnValue.conf.js', + 'node built/cli.js spec/onCleanUpSyncReturnValue.conf.js', + 'node built/cli.js spec/onPrepare.conf.js', + 'node built/cli.js spec/onPrepareFile.conf.js', + 'node built/cli.js spec/onPreparePromise.conf.js', + 'node built/cli.js spec/onPreparePromiseFile.conf.js', + 'node built/cli.js spec/mocha.conf.js', + 'node built/cli.js spec/withLogin.conf.js', + 'node built/cli.js spec/suites.conf.js --suite okmany', + 'node built/cli.js spec/suites.conf.js --suite okspec', + 'node built/cli.js spec/suites.conf.js --suite okmany,okspec', + 'node built/cli.js spec/plugins/smoke.conf.js', + 'node built/cli.js spec/plugins/multiPlugin.conf.js', + 'node built/cli.js spec/plugins/jasminePostTest.conf.js', + 'node built/cli.js spec/plugins/mochaPostTest.conf.js', + 'node built/cli.js spec/plugins/browserGetSynced.conf.js', + 'node built/cli.js spec/plugins/browserGetUnsynced.conf.js', + 'node built/cli.js spec/plugins/waitForAngular.conf.js', + 'node built/cli.js spec/interaction.conf.js', + 'node built/cli.js spec/directConnect.conf.js', + 'node built/cli.js spec/restartBrowserBetweenTests.conf.js', + 'node built/cli.js spec/driverProviderLocal.conf.js', + 'node built/cli.js spec/driverProviderLocal.conf.js --useBlockingProxy', + 'node built/cli.js spec/getCapabilities.conf.js', + 'node built/cli.js spec/controlLock.conf.js', + 'node built/cli.js spec/customFramework.conf.js', + 'node built/cli.js spec/noGlobals.conf.js', + 'node built/cli.js spec/angular2.conf.js', + 'node built/cli.js spec/hybrid.conf.js', + 'node built/cli.js spec/built/noCFBasic.conf.js', + 'node built/cli.js spec/built/noCFBasic.conf.js --useBlockingProxy', + 'node built/cli.js spec/built/noCFPlugin.conf.js', + 'node scripts/driverProviderAttachSession.js', + 'node scripts/errorTest.js', + // Interactive Element Explorer tasks // 'node scripts/interactive_tests/interactive_test.js', // 'node scripts/interactive_tests/with_base_url.js', // Unit tests @@ -67,14 +67,14 @@ passingTests.forEach(function(passing_test) { *************************/ // assert stacktrace shows line of failure -executor.addCommandlineTest('node built/cli.js spec/errorTest/singleFailureConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/singleFailure.conf.js') .expectExitCode(1) .expectErrors({ stackTrace: 'single_failure_spec1.js:5:38' }); // assert timeout works -executor.addCommandlineTest('node built/cli.js spec/errorTest/timeoutConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/timeout.conf.js') .expectExitCode(1) .expectErrors({ message: 'Timeout - Async callback was not invoked within timeout ' + @@ -82,13 +82,13 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/timeoutConf.js') }) .expectTestDuration(0, 1000); -executor.addCommandlineTest('node built/cli.js spec/errorTest/afterLaunchChangesExitCodeConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/afterLaunchChangesExitCode.conf.js') .expectExitCode(11) .expectErrors({ message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.' }); -executor.addCommandlineTest('node built/cli.js spec/errorTest/multiFailureConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/multiFailure.conf.js') .expectExitCode(1) .expectErrors([{ message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', @@ -98,7 +98,7 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/multiFailureConf.j stacktrace: 'single_failure_spec2.js:5:32' }]); -executor.addCommandlineTest('node built/cli.js spec/errorTest/shardedFailureConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/shardedFailure.conf.js') .expectExitCode(1) .expectErrors([{ message: 'Expected \'Hiya\' to equal \'INTENTIONALLY INCORRECT\'.', @@ -108,14 +108,14 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/shardedFailureConf stacktrace: 'single_failure_spec2.js:5:32' }]); -executor.addCommandlineTest('node built/cli.js spec/errorTest/mochaFailureConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/mochaFailure.conf.js') .expectExitCode(1) .expectErrors([{ message: 'expected \'My AngularJS App\' to equal \'INTENTIONALLY INCORRECT\'', stacktrace: 'mocha_failure_spec.js:11:20' }]); -executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf.js') +executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailing.conf.js') .expectExitCode(1) .expectErrors([ {message: 'Expected true to be false'}, @@ -126,7 +126,7 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf ]); // TODO(selenium4): turn these on when we figure out the correct error message handling. -// executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeoutConf.js') +// executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeout.conf.js') // .expectExitCode(1) // .expectErrors([ // {message: 'The following tasks were pending[\\s\\S]*\\$http: slowcall'}, @@ -137,7 +137,7 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf // ]); // TODO(selenium4): turn these on when we figure out the correct error message handling. -// executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeoutConf.js ' + +// executor.addCommandlineTest('node built/cli.js spec/errorTest/slowHttpAndTimeout.conf.js ' + // '--untrackOutstandingTimeouts true') // .expectExitCode(1) // .expectErrors([ @@ -147,7 +147,7 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/pluginsFailingConf // ]); // TODO(selenium4): turn these on when we figure out the correct error message handling. -// executor.addCommandlineTest('node built/cli.js spec/angular2TimeoutConf.js') +// executor.addCommandlineTest('node built/cli.js spec/angular2Timeout.conf.js') // .expectExitCode(1) // .expectErrors([ // {message: 'Timed out waiting for asynchronous Angular tasks to finish'}, diff --git a/spec/altRootConf.js b/spec/altRoot.conf.js similarity index 100% rename from spec/altRootConf.js rename to spec/altRoot.conf.js diff --git a/spec/angular2Conf.js b/spec/angular2.conf.js similarity index 100% rename from spec/angular2Conf.js rename to spec/angular2.conf.js diff --git a/spec/angular2TimeoutConf.js b/spec/angular2Timeout.conf.js similarity index 95% rename from spec/angular2TimeoutConf.js rename to spec/angular2Timeout.conf.js index 6f5bf3130..8ce099b55 100644 --- a/spec/angular2TimeoutConf.js +++ b/spec/angular2Timeout.conf.js @@ -12,6 +12,7 @@ var env = require('./environment'); // exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/basicConf.js b/spec/basic.conf.js similarity index 94% rename from spec/basicConf.js rename to spec/basic.conf.js index 10138c5cd..9b378fd52 100644 --- a/spec/basicConf.js +++ b/spec/basic.conf.js @@ -9,7 +9,7 @@ exports.config = { // Spec patterns are relative to this directory. specs: [ - 'basic/restart_spec.js' + 'basic/*_spec.js' ], // Exclude patterns are relative to this directory. diff --git a/spec/basic/handling_spec.js b/spec/basic/handling_spec.js index fd6886436..d2d0e8340 100644 --- a/spec/basic/handling_spec.js +++ b/spec/basic/handling_spec.js @@ -1,13 +1,4 @@ describe('handling timeout errors', () => { - - // beforeEach(async () => { - // await browser.waitForAngularEnabled(false); - // }); - - // afterEach(async () => { - // await browser.waitForAngularEnabled(true); - // }); - it('should call error handler on a timeout', async () => { try { await browser.get('http://dummyUrl', 1); diff --git a/spec/ciBStackConf.js b/spec/ciBStack.conf.js similarity index 100% rename from spec/ciBStackConf.js rename to spec/ciBStack.conf.js diff --git a/spec/ciFullConf.js b/spec/ciFull.conf.js similarity index 100% rename from spec/ciFullConf.js rename to spec/ciFull.conf.js diff --git a/spec/ciNg2Conf.js b/spec/ciNg2.conf.js similarity index 100% rename from spec/ciNg2Conf.js rename to spec/ciNg2.conf.js diff --git a/spec/ciSmokeConf.js b/spec/ciSmoke.conf.js similarity index 100% rename from spec/ciSmokeConf.js rename to spec/ciSmoke.conf.js diff --git a/spec/controlLockConf.js b/spec/controlLock.conf.js similarity index 100% rename from spec/controlLockConf.js rename to spec/controlLock.conf.js diff --git a/spec/customFramework.js b/spec/customFramework.conf.js similarity index 100% rename from spec/customFramework.js rename to spec/customFramework.conf.js diff --git a/spec/directConnectConf.js b/spec/directConnect.conf.js similarity index 100% rename from spec/directConnectConf.js rename to spec/directConnect.conf.js diff --git a/spec/driverProviderAttachSessionConf.js b/spec/driverProviderAttachSession.conf.js similarity index 87% rename from spec/driverProviderAttachSessionConf.js rename to spec/driverProviderAttachSession.conf.js index e75bcb6c4..3cdef4c46 100644 --- a/spec/driverProviderAttachSessionConf.js +++ b/spec/driverProviderAttachSession.conf.js @@ -2,6 +2,7 @@ var env = require('./environment'); exports.config = { seleniumAddress: env.seleniumAddress, + SELENIUM_PROMISE_MANAGER: false, framework: 'jasmine', diff --git a/spec/driverProviderLocalConf.js b/spec/driverProviderLocal.conf.js similarity index 100% rename from spec/driverProviderLocalConf.js rename to spec/driverProviderLocal.conf.js diff --git a/spec/driverProviders/attachSession/attachSession_spec.js b/spec/driverProviders/attachSession/attachSession_spec.js index e69bc614c..3639a6ba3 100644 --- a/spec/driverProviders/attachSession/attachSession_spec.js +++ b/spec/driverProviders/attachSession/attachSession_spec.js @@ -1,10 +1,10 @@ -describe('selenium session id', function() { +describe('selenium session id', () => { var URL = '/ng2/#/async'; - beforeEach(function() { - browser.get(URL); + beforeEach(async () => { + await browser.get(URL); }); - it('should be able to use an existing session', function() { + it('should be able to use an existing session', () => { var increment = $('#increment'); expect(increment).toBeDefined(); }); diff --git a/spec/driverprovider_test.js b/spec/driverproviderTest.conf.js similarity index 100% rename from spec/driverprovider_test.js rename to spec/driverproviderTest.conf.js diff --git a/spec/environment.js b/spec/environment.js index aa1c99eac..6a2240ef2 100644 --- a/spec/environment.js +++ b/spec/environment.js @@ -4,7 +4,7 @@ var webServerDefaultPort = 8081; module.exports = { // The address of a running selenium server. seleniumAddress: - (process.env.SELENIUM_URL || 'http://localhost:4444/wd/hub'), + (process.env.SELENIUM_URL || 'http://127.0.0.1:4444/wd/hub'), // Capabilities to be passed to the webdriver instance. capabilities: { @@ -22,7 +22,7 @@ module.exports = { // A base URL for your application under test. baseUrl: - 'http://' + (process.env.HTTP_HOST || 'localhost') + + 'http://' + (process.env.HTTP_HOST || '127.0.0.1') + ':' + (process.env.HTTP_PORT || webServerDefaultPort) }; \ No newline at end of file diff --git a/spec/errorTest/afterLaunchChangesExitCodeConf.js b/spec/errorTest/afterLaunchChangesExitCode.conf.js similarity index 100% rename from spec/errorTest/afterLaunchChangesExitCodeConf.js rename to spec/errorTest/afterLaunchChangesExitCode.conf.js diff --git a/spec/errorTest/browserStackAuthentication.js b/spec/errorTest/browserStackAuthentication.conf.js similarity index 100% rename from spec/errorTest/browserStackAuthentication.js rename to spec/errorTest/browserStackAuthentication.conf.js diff --git a/spec/errorTest/debugMultiCapabilities.js b/spec/errorTest/debugMultiCapabilities.conf.js similarity index 100% rename from spec/errorTest/debugMultiCapabilities.js rename to spec/errorTest/debugMultiCapabilities.conf.js diff --git a/spec/errorTest/getMultiCapabilitiesConf.js b/spec/errorTest/getMultiCapabilities.conf.js similarity index 100% rename from spec/errorTest/getMultiCapabilitiesConf.js rename to spec/errorTest/getMultiCapabilities.conf.js diff --git a/spec/errorTest/mochaFailureConf.js b/spec/errorTest/mochaFailure.conf.js similarity index 100% rename from spec/errorTest/mochaFailureConf.js rename to spec/errorTest/mochaFailure.conf.js diff --git a/spec/errorTest/multiFailureConf.js b/spec/errorTest/multiFailure.conf.js similarity index 100% rename from spec/errorTest/multiFailureConf.js rename to spec/errorTest/multiFailure.conf.js diff --git a/spec/errorTest/pluginsFailingConf.js b/spec/errorTest/pluginsFailing.conf.js similarity index 100% rename from spec/errorTest/pluginsFailingConf.js rename to spec/errorTest/pluginsFailing.conf.js diff --git a/spec/errorTest/sauceLabsAuthentication.js b/spec/errorTest/sauceLabsAuthentication.conf.js similarity index 100% rename from spec/errorTest/sauceLabsAuthentication.js rename to spec/errorTest/sauceLabsAuthentication.conf.js diff --git a/spec/errorTest/shardedFailureConf.js b/spec/errorTest/shardedFailure.conf.js similarity index 100% rename from spec/errorTest/shardedFailureConf.js rename to spec/errorTest/shardedFailure.conf.js diff --git a/spec/errorTest/singleFailureConf.js b/spec/errorTest/singleFailure.conf.js similarity index 100% rename from spec/errorTest/singleFailureConf.js rename to spec/errorTest/singleFailure.conf.js diff --git a/spec/errorTest/slowHttpAndTimeoutConf.js b/spec/errorTest/slowHttpAndTimeout.conf.js similarity index 100% rename from spec/errorTest/slowHttpAndTimeoutConf.js rename to spec/errorTest/slowHttpAndTimeout.conf.js diff --git a/spec/errorTest/timeoutConf.js b/spec/errorTest/timeout.conf.js similarity index 100% rename from spec/errorTest/timeoutConf.js rename to spec/errorTest/timeout.conf.js diff --git a/spec/getCapabilitiesConf.js b/spec/getCapabilities.conf.js similarity index 100% rename from spec/getCapabilitiesConf.js rename to spec/getCapabilities.conf.js diff --git a/spec/hybridConf.js b/spec/hybrid.conf.js similarity index 100% rename from spec/hybridConf.js rename to spec/hybrid.conf.js diff --git a/spec/inferRootConf.js b/spec/inferRoot.conf.js similarity index 100% rename from spec/inferRootConf.js rename to spec/inferRoot.conf.js diff --git a/spec/interactionConf.js b/spec/interaction.conf.js similarity index 100% rename from spec/interactionConf.js rename to spec/interaction.conf.js diff --git a/spec/mochaConf.js b/spec/mocha.conf.js similarity index 100% rename from spec/mochaConf.js rename to spec/mocha.conf.js diff --git a/spec/multiConf.js b/spec/multi.conf.js similarity index 100% rename from spec/multiConf.js rename to spec/multi.conf.js diff --git a/spec/ng2/timeout_spec.js b/spec/ng2/timeout_spec.js index a023b67b2..a90311e61 100644 --- a/spec/ng2/timeout_spec.js +++ b/spec/ng2/timeout_spec.js @@ -1,10 +1,10 @@ -describe('async angular2 application timeout', function() { +describe('async angular2 application timeout', () => { var URL = '/ng2/#/async'; - it('should timeout if intervals are used in the NgZone', function() { - browser.get(URL); - var timeout = $('#periodicIncrement'); - timeout.$('.action').click(); - timeout.$('.cancel').click(); + it('should timeout if intervals are used in the NgZone', async () => { + await browser.get(URL); + const timeout = $('#periodicIncrement'); + await timeout.$('.action').click(); + await timeout.$('.cancel').click(); }); }); diff --git a/spec/noGlobalsConf.js b/spec/noGlobals.conf.js similarity index 100% rename from spec/noGlobalsConf.js rename to spec/noGlobals.conf.js diff --git a/spec/onCleanUpAsyncReturnValueConf.js b/spec/onCleanUpAsyncReturnValue.conf.js similarity index 100% rename from spec/onCleanUpAsyncReturnValueConf.js rename to spec/onCleanUpAsyncReturnValue.conf.js diff --git a/spec/onCleanUpNoReturnValueConf.js b/spec/onCleanUpNoReturnValue.conf.js similarity index 100% rename from spec/onCleanUpNoReturnValueConf.js rename to spec/onCleanUpNoReturnValue.conf.js diff --git a/spec/onCleanUpSyncReturnValueConf.js b/spec/onCleanUpSyncReturnValue.conf.js similarity index 100% rename from spec/onCleanUpSyncReturnValueConf.js rename to spec/onCleanUpSyncReturnValue.conf.js diff --git a/spec/onPrepareConf.js b/spec/onPrepare.conf.js similarity index 100% rename from spec/onPrepareConf.js rename to spec/onPrepare.conf.js diff --git a/spec/onPrepareFileConf.js b/spec/onPrepareFile.conf.js similarity index 100% rename from spec/onPrepareFileConf.js rename to spec/onPrepareFile.conf.js diff --git a/spec/onPreparePromiseConf.js b/spec/onPreparePromise.conf.js similarity index 100% rename from spec/onPreparePromiseConf.js rename to spec/onPreparePromise.conf.js diff --git a/spec/onPreparePromiseFileConf.js b/spec/onPreparePromiseFile.conf.js similarity index 100% rename from spec/onPreparePromiseFileConf.js rename to spec/onPreparePromiseFile.conf.js diff --git a/spec/plugins/browserGetSyncedConf.js b/spec/plugins/browserGetSynced.conf.js similarity index 100% rename from spec/plugins/browserGetSyncedConf.js rename to spec/plugins/browserGetSynced.conf.js diff --git a/spec/plugins/browserGetUnsyncedConf.js b/spec/plugins/browserGetUnsynced.conf.js similarity index 100% rename from spec/plugins/browserGetUnsyncedConf.js rename to spec/plugins/browserGetUnsynced.conf.js diff --git a/spec/plugins/jasminePostTest.conf.js b/spec/plugins/jasminePostTest.conf.js new file mode 100644 index 000000000..173acb86e --- /dev/null +++ b/spec/plugins/jasminePostTest.conf.js @@ -0,0 +1 @@ +exports.config = require('./postTestConfTemplate.conf')('jasmine'); diff --git a/spec/plugins/jasminePostTestConf.js b/spec/plugins/jasminePostTestConf.js deleted file mode 100644 index 566ef575e..000000000 --- a/spec/plugins/jasminePostTestConf.js +++ /dev/null @@ -1 +0,0 @@ -exports.config = require('./postTestConfTemplate')('jasmine'); diff --git a/spec/plugins/mochaPostTest.conf.js b/spec/plugins/mochaPostTest.conf.js new file mode 100644 index 000000000..f3ba17fc2 --- /dev/null +++ b/spec/plugins/mochaPostTest.conf.js @@ -0,0 +1 @@ +exports.config = require('./postTestConfTemplate.conf')('mocha'); diff --git a/spec/plugins/mochaPostTestConf.js b/spec/plugins/mochaPostTestConf.js deleted file mode 100644 index bb6d56485..000000000 --- a/spec/plugins/mochaPostTestConf.js +++ /dev/null @@ -1 +0,0 @@ -exports.config = require('./postTestConfTemplate')('mocha'); diff --git a/spec/plugins/multiPluginConf.js b/spec/plugins/multiPlugin.conf.js similarity index 100% rename from spec/plugins/multiPluginConf.js rename to spec/plugins/multiPlugin.conf.js diff --git a/spec/plugins/postTestConfTemplate.js b/spec/plugins/postTestConfTemplate.conf.js similarity index 100% rename from spec/plugins/postTestConfTemplate.js rename to spec/plugins/postTestConfTemplate.conf.js diff --git a/spec/plugins/skipStabilityConf.js b/spec/plugins/skipStability.conf.js similarity index 100% rename from spec/plugins/skipStabilityConf.js rename to spec/plugins/skipStability.conf.js diff --git a/spec/plugins/smokeConf.js b/spec/plugins/smoke.conf.js similarity index 100% rename from spec/plugins/smokeConf.js rename to spec/plugins/smoke.conf.js diff --git a/spec/plugins/waitForAngularConf.js b/spec/plugins/waitForAngular.conf.js similarity index 100% rename from spec/plugins/waitForAngularConf.js rename to spec/plugins/waitForAngular.conf.js diff --git a/spec/restartBrowserBetweenTestsConf.js b/spec/restartBrowserBetweenTests.conf.js similarity index 100% rename from spec/restartBrowserBetweenTestsConf.js rename to spec/restartBrowserBetweenTests.conf.js diff --git a/spec/restartBrowserBetweenTests/setCookies_spec.js b/spec/restartBrowserBetweenTests/setCookies_spec.js index 6d21c5fa4..05356e3ea 100644 --- a/spec/restartBrowserBetweenTests/setCookies_spec.js +++ b/spec/restartBrowserBetweenTests/setCookies_spec.js @@ -1,7 +1,7 @@ const env = require('../environment.js'); describe('pages with login', () => { - it('should set a cookie', async() => { + it('should set a cookie', async () => { await browser.get(env.baseUrl + '/ng1/index.html'); await browser.manage().addCookie({name:'testcookie', value: 'Jane-1234'}); @@ -11,7 +11,7 @@ describe('pages with login', () => { expect(cookie.value).toEqual('Jane-1234'); }); - it('should check the cookie is gone', async() => { + it('should check the cookie is gone', async () => { await browser.get(env.baseUrl + '/ng1/index.html'); // Make sure the cookie is gone. diff --git a/spec/shardingConf.js b/spec/sharding.conf.js similarity index 100% rename from spec/shardingConf.js rename to spec/sharding.conf.js diff --git a/spec/suitesConf.js b/spec/suites.conf.js similarity index 100% rename from spec/suitesConf.js rename to spec/suites.conf.js diff --git a/spec/ts/noCFBasicConf.ts b/spec/ts/noCFBasic.conf.ts similarity index 100% rename from spec/ts/noCFBasicConf.ts rename to spec/ts/noCFBasic.conf.ts diff --git a/spec/ts/noCFPluginConf.ts b/spec/ts/noCFPlugin.conf.ts similarity index 100% rename from spec/ts/noCFPluginConf.ts rename to spec/ts/noCFPlugin.conf.ts diff --git a/spec/unit/runner_test.js b/spec/unit/runner_test.js index 411c0aeb1..5c98ca8ae 100644 --- a/spec/unit/runner_test.js +++ b/spec/unit/runner_test.js @@ -2,69 +2,70 @@ var Runner = require('../../built/runner').Runner; var Logger = require('../../built/logger').Logger, WriteTo = require('../../built/logger').WriteTo; -describe('the Protractor runner', function() { - beforeAll(function() { +describe('the Protractor runner', () => { + beforeAll(() => { Logger.writeTo = WriteTo.NONE; }); - afterAll(function() { + afterAll(() => { Logger.writeTo = WriteTo.CONSOLE; }); - it('should export its config', function() { - var config = { + it('should export its config', () => { + const config = { foo: 'bar' }; - var runner = new Runner(config); + const runner = new Runner(config); expect(runner.getConfig()).toEqual(config); }); - it('should run', function(done) { - var config = { + it('should run', async () => { + const config = { mockSelenium: true, specs: ['*.js'], framework: 'debugprint' }; - var exitCode; - var runner = new Runner(config); + let exitCode; + const runner = new Runner(config); runner.exit_ = function(exit) { exitCode = exit; }; - runner.run().then(function() { - expect(exitCode).toEqual(0); - done(); - }); + await runner.run() + expect(exitCode).toEqual(0); }); - it('should fail with no specs', function() { - var config = { + it('should fail with no specs', async (done) => { + const config = { mockSelenium: true, specs: [], framework: 'debugprint' }; - var exitCode; - Runner.prototype.exit_ = function(exit) { - exitCode = exit; - }; - var runner = new Runner(config); - expect(function() { - runner.run(); - }).toThrow(); + const runner = new Runner(config); + + try { + await runner.run(); + done.fail('expected error when no specs are defined'); + } catch (err) { + done(); + } }); - it('should fail when no custom framework is defined', function(done) { - var config = { + it('should fail when no custom framework is defined', async (done) => { + const config = { mockSelenium: true, specs: ['*.js'], framework: 'custom' }; - var runner = new Runner(config); - runner.run().then(function() { + const runner = new Runner(config); + try { + await runner.run(); done.fail('expected error when no custom framework is defined'); - }, done); + } catch (err) { + done(); + } }); }); diff --git a/spec/withLoginConf.js b/spec/withLogin.conf.js similarity index 100% rename from spec/withLoginConf.js rename to spec/withLogin.conf.js