diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-05-27 17:36:13 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-05-27 17:36:13 +0200 |
commit | 5f466137ad6ac596600e3ff53c9b786815398445 (patch) | |
tree | f914c221874f0b16bf3def7ac01d59d1a99a3b0b /node_modules/selenium-webdriver/test/lib | |
parent | c9f5ac8e763eda19aa0564179300cfff76785435 (diff) |
node_modules, clean up package.json
Diffstat (limited to 'node_modules/selenium-webdriver/test/lib')
14 files changed, 0 insertions, 9248 deletions
diff --git a/node_modules/selenium-webdriver/test/lib/by_test.js b/node_modules/selenium-webdriver/test/lib/by_test.js deleted file mode 100644 index 34314fbf8..000000000 --- a/node_modules/selenium-webdriver/test/lib/by_test.js +++ /dev/null @@ -1,160 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -var assert = require('assert'); -var by = require('../../lib/by'); - -describe('by', function() { - describe('By', function() { - describe('className', function() { - it('delegates to By.css', function() { - let locator = by.By.className('foo'); - assert.equal('css selector', locator.using); - assert.equal('.foo', locator.value); - }); - - it('escapes class name', function() { - let locator = by.By.className('foo#bar'); - assert.equal('css selector', locator.using); - assert.equal('.foo\\#bar', locator.value); - }); - - it('translates compound class names', function() { - let locator = by.By.className('a b'); - assert.equal('css selector', locator.using); - assert.equal('.a.b', locator.value); - - locator = by.By.className(' x y z-1 "g" '); - assert.equal('css selector', locator.using); - assert.equal('.x.y.z-1.\\"g\\"', locator.value); - }); - }); - - describe('id', function() { - it('delegates to By.css', function() { - let locator = by.By.id('foo'); - assert.equal('css selector', locator.using); - assert.equal('*[id="foo"]', locator.value); - }); - - it('escapes the ID', function() { - let locator = by.By.id('foo#bar'); - assert.equal('css selector', locator.using); - assert.equal('*[id="foo\\#bar"]', locator.value); - }); - }); - - describe('name', function() { - it('delegates to By.css', function() { - let locator = by.By.name('foo') - assert.equal('css selector', locator.using); - assert.equal('*[name="foo"]', locator.value); - }); - - it('escapes the name', function() { - let locator = by.By.name('foo"bar"') - assert.equal('css selector', locator.using); - assert.equal('*[name="foo\\"bar\\""]', locator.value); - }); - - it('escapes the name when it starts with a number', function() { - let locator = by.By.name('123foo"bar"') - assert.equal('css selector', locator.using); - assert.equal('*[name="\\31 23foo\\"bar\\""]', locator.value); - }); - - it('escapes the name when it starts with a negative number', function() { - let locator = by.By.name('-123foo"bar"') - assert.equal('css selector', locator.using); - assert.equal('*[name="-\\31 23foo\\"bar\\""]', locator.value); - }); - }); - }); - - describe('checkedLocator', function() { - it('accepts a By instance', function() { - let original = by.By.name('foo'); - let locator = by.checkedLocator(original); - assert.strictEqual(locator, original); - }); - - it('accepts custom locator functions', function() { - let original = function() {}; - let locator = by.checkedLocator(original); - assert.strictEqual(locator, original); - }); - - // See https://github.com/SeleniumHQ/selenium/issues/3056 - it('accepts By-like objects', function() { - let fakeBy = {using: 'id', value: 'foo'}; - let locator = by.checkedLocator(fakeBy); - assert.strictEqual(locator.constructor, by.By); - assert.equal(locator.using, 'id'); - assert.equal(locator.value, 'foo'); - }); - - it('accepts class name', function() { - let locator = by.checkedLocator({className: 'foo'}); - assert.equal('css selector', locator.using); - assert.equal('.foo', locator.value); - }); - - it('accepts css', function() { - let locator = by.checkedLocator({css: 'a > b'}); - assert.equal('css selector', locator.using); - assert.equal('a > b', locator.value); - }); - - it('accepts id', function() { - let locator = by.checkedLocator({id: 'foobar'}); - assert.equal('css selector', locator.using); - assert.equal('*[id="foobar"]', locator.value); - }); - - it('accepts linkText', function() { - let locator = by.checkedLocator({linkText: 'hello'}); - assert.equal('link text', locator.using); - assert.equal('hello', locator.value); - }); - - it('accepts name', function() { - let locator = by.checkedLocator({name: 'foobar'}); - assert.equal('css selector', locator.using); - assert.equal('*[name="foobar"]', locator.value); - }); - - it('accepts partialLinkText', function() { - let locator = by.checkedLocator({partialLinkText: 'hello'}); - assert.equal('partial link text', locator.using); - assert.equal('hello', locator.value); - }); - - it('accepts tagName', function() { - let locator = by.checkedLocator({tagName: 'div'}); - assert.equal('css selector', locator.using); - assert.equal('div', locator.value); - }); - - it('accepts xpath', function() { - let locator = by.checkedLocator({xpath: '//div[1]'}); - assert.equal('xpath', locator.using); - assert.equal('//div[1]', locator.value); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/capabilities_test.js b/node_modules/selenium-webdriver/test/lib/capabilities_test.js deleted file mode 100644 index 0d0c67c9a..000000000 --- a/node_modules/selenium-webdriver/test/lib/capabilities_test.js +++ /dev/null @@ -1,111 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const Capabilities = require('../../lib/capabilities').Capabilities; -const Symbols = require('../../lib/symbols'); - -const assert = require('assert'); - -describe('Capabilities', function() { - it('can set and unset a capability', function() { - let caps = new Capabilities(); - assert.equal(undefined, caps.get('foo')); - assert.ok(!caps.has('foo')); - - caps.set('foo', 'bar'); - assert.equal('bar', caps.get('foo')); - assert.ok(caps.has('foo')); - - caps.set('foo', null); - assert.equal(null, caps.get('foo')); - assert.ok(caps.has('foo')); - }); - - it('requires string capability keys', function() { - let caps = new Capabilities(); - assert.throws(() => caps.set({}, 'hi')); - }); - - it('can merge capabilities', function() { - let caps1 = new Capabilities() - .set('foo', 'bar') - .set('color', 'red'); - - let caps2 = new Capabilities() - .set('color', 'green'); - - assert.equal('bar', caps1.get('foo')); - assert.equal('red', caps1.get('color')); - assert.equal('green', caps2.get('color')); - assert.equal(undefined, caps2.get('foo')); - - caps2.merge(caps1); - assert.equal('bar', caps1.get('foo')); - assert.equal('red', caps1.get('color')); - assert.equal('red', caps2.get('color')); - assert.equal('bar', caps2.get('foo')); - }); - - it('can be initialized from a hash object', function() { - let caps = new Capabilities({'one': 123, 'abc': 'def'}); - assert.equal(123, caps.get('one')); - assert.equal('def', caps.get('abc')); - }); - - it('can be initialized from a map', function() { - let m = new Map([['one', 123], ['abc', 'def']]); - - let caps = new Capabilities(m); - assert.equal(123, caps.get('one')); - assert.equal('def', caps.get('abc')); - }); - - describe('serialize', function() { - it('works for simple capabilities', function() { - let m = new Map([['one', 123], ['abc', 'def']]); - let caps = new Capabilities(m); - assert.deepEqual({one: 123, abc: 'def'}, caps[Symbols.serialize]()); - }); - - it('does not omit capabilities set to a false-like value', function() { - let caps = new Capabilities; - caps.set('bool', false); - caps.set('number', 0); - caps.set('string', ''); - - assert.deepEqual( - {bool: false, number: 0, string: ''}, - caps[Symbols.serialize]()); - }); - - it('omits capabilities with a null value', function() { - let caps = new Capabilities; - caps.set('foo', null); - caps.set('bar', 123); - assert.deepEqual({bar: 123}, caps[Symbols.serialize]()); - }); - - it('omits capabilities with an undefined value', function() { - let caps = new Capabilities; - caps.set('foo', undefined); - caps.set('bar', 123); - assert.deepEqual({bar: 123}, caps[Symbols.serialize]()); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/error_test.js b/node_modules/selenium-webdriver/test/lib/error_test.js deleted file mode 100644 index a9fc87193..000000000 --- a/node_modules/selenium-webdriver/test/lib/error_test.js +++ /dev/null @@ -1,286 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -describe('error', function() { - let assert = require('assert'); - let error = require('../../lib/error'); - - describe('checkResponse', function() { - it('defaults to WebDriverError if type is unrecognized', function() { - assert.throws( - () => error.checkResponse({error: 'foo', message: 'hi there'}), - (e) => { - assert.equal(e.constructor, error.WebDriverError); - return true; - }); - }); - - it('does not throw if error property is not a string', function() { - let resp = {error: 123, message: 'abc123'}; - let out = error.checkResponse(resp); - assert.strictEqual(out, resp); - }); - - test('unknown error', error.WebDriverError); - test('element not selectable', error.ElementNotSelectableError); - test('element not visible', error.ElementNotVisibleError); - test('invalid argument', error.InvalidArgumentError); - test('invalid cookie domain', error.InvalidCookieDomainError); - test('invalid element coordinates', error.InvalidElementCoordinatesError); - test('invalid element state', error.InvalidElementStateError); - test('invalid selector', error.InvalidSelectorError); - test('invalid session id', error.NoSuchSessionError); - test('javascript error', error.JavascriptError); - test('move target out of bounds', error.MoveTargetOutOfBoundsError); - test('no such alert', error.NoSuchAlertError); - test('no such element', error.NoSuchElementError); - test('no such frame', error.NoSuchFrameError); - test('no such window', error.NoSuchWindowError); - test('script timeout', error.ScriptTimeoutError); - test('session not created', error.SessionNotCreatedError); - test('stale element reference', error.StaleElementReferenceError); - test('timeout', error.TimeoutError); - test('unable to set cookie', error.UnableToSetCookieError); - test('unable to capture screen', error.UnableToCaptureScreenError); - test('unexpected alert open', error.UnexpectedAlertOpenError); - test('unknown command', error.UnknownCommandError); - test('unknown method', error.UnknownMethodError); - test('unsupported operation', error.UnsupportedOperationError); - - function test(status, expectedType) { - it(`"${status}" => ${expectedType.name}`, function() { - assert.throws( - () => error.checkResponse({error: status, message: 'oops'}), - (e) => { - assert.equal(expectedType, e.constructor); - assert.equal(e.message, 'oops'); - return true; - }); - }); - } - }); - - describe('encodeError', function() { - describe('defaults to an unknown error', function() { - it('for a generic error value', function() { - runTest('hi', 'unknown error', 'hi'); - runTest(1, 'unknown error', '1'); - runTest({}, 'unknown error', '[object Object]'); - }); - - it('for a generic Error object', function() { - runTest(Error('oops'), 'unknown error', 'oops'); - runTest(TypeError('bad value'), 'unknown error', 'bad value'); - }); - }); - - test(error.WebDriverError, 'unknown error'); - test(error.ElementNotSelectableError, 'element not selectable'); - test(error.ElementNotVisibleError, 'element not visible'); - test(error.InvalidArgumentError, 'invalid argument'); - test(error.InvalidCookieDomainError, 'invalid cookie domain'); - test(error.InvalidElementStateError, 'invalid element state'); - test(error.InvalidSelectorError, 'invalid selector'); - test(error.NoSuchSessionError, 'invalid session id'); - test(error.JavascriptError, 'javascript error'); - test(error.MoveTargetOutOfBoundsError, 'move target out of bounds'); - test(error.NoSuchAlertError, 'no such alert'); - test(error.NoSuchElementError, 'no such element'); - test(error.NoSuchFrameError, 'no such frame'); - test(error.NoSuchWindowError, 'no such window'); - test(error.ScriptTimeoutError, 'script timeout'); - test(error.SessionNotCreatedError, 'session not created'); - test(error.StaleElementReferenceError, 'stale element reference'); - test(error.TimeoutError, 'timeout'); - test(error.UnableToSetCookieError, 'unable to set cookie'); - test(error.UnableToCaptureScreenError, 'unable to capture screen'); - test(error.UnexpectedAlertOpenError, 'unexpected alert open'); - test(error.UnknownCommandError, 'unknown command'); - test(error.UnknownMethodError, 'unknown method'); - test(error.UnsupportedOperationError, 'unsupported operation'); - - function test(ctor, code) { - it(`${ctor.name} => "${code}"`, () => { - runTest(new ctor('oops'), code, 'oops'); - }); - } - - function runTest(err, code, message) { - let obj = error.encodeError(err); - assert.strictEqual(obj['error'], code); - assert.strictEqual(obj['message'], message); - } - }); - - describe('throwDecodedError', function() { - it('defaults to WebDriverError if type is unrecognized', function() { - assert.throws( - () => error.throwDecodedError({error: 'foo', message: 'hi there'}), - (e) => { - assert.equal(e.constructor, error.WebDriverError); - return true; - }); - }); - - it('throws generic error if encoded data is not valid', function() { - assert.throws( - () => error.throwDecodedError({error: 123, message: 'abc123'}), - (e) => { - assert.strictEqual(e.constructor, error.WebDriverError); - return true; - }); - - assert.throws( - () => error.throwDecodedError('null'), - (e) => { - assert.strictEqual(e.constructor, error.WebDriverError); - return true; - }); - - assert.throws( - () => error.throwDecodedError(''), - (e) => { - assert.strictEqual(e.constructor, error.WebDriverError); - return true; - }); - }); - - test('unknown error', error.WebDriverError); - test('element not selectable', error.ElementNotSelectableError); - test('element not visible', error.ElementNotVisibleError); - test('invalid argument', error.InvalidArgumentError); - test('invalid cookie domain', error.InvalidCookieDomainError); - test('invalid element coordinates', error.InvalidElementCoordinatesError); - test('invalid element state', error.InvalidElementStateError); - test('invalid selector', error.InvalidSelectorError); - test('invalid session id', error.NoSuchSessionError); - test('javascript error', error.JavascriptError); - test('move target out of bounds', error.MoveTargetOutOfBoundsError); - test('no such alert', error.NoSuchAlertError); - test('no such element', error.NoSuchElementError); - test('no such frame', error.NoSuchFrameError); - test('no such window', error.NoSuchWindowError); - test('script timeout', error.ScriptTimeoutError); - test('session not created', error.SessionNotCreatedError); - test('stale element reference', error.StaleElementReferenceError); - test('timeout', error.TimeoutError); - test('unable to set cookie', error.UnableToSetCookieError); - test('unable to capture screen', error.UnableToCaptureScreenError); - test('unexpected alert open', error.UnexpectedAlertOpenError); - test('unknown command', error.UnknownCommandError); - test('unknown method', error.UnknownMethodError); - test('unsupported operation', error.UnsupportedOperationError); - - function test(status, expectedType) { - it(`"${status}" => ${expectedType.name}`, function() { - assert.throws( - () => error.throwDecodedError({error: status, message: 'oops'}), - (e) => { - assert.strictEqual(e.constructor, expectedType); - assert.strictEqual(e.message, 'oops'); - return true; - }); - }); - } - }); - - describe('checkLegacyResponse', function() { - it('does not throw for success', function() { - let resp = {status: error.ErrorCode.SUCCESS}; - assert.strictEqual(resp, error.checkLegacyResponse(resp)); - }); - - test('NO_SUCH_ELEMENT', error.NoSuchElementError); - test('NO_SUCH_FRAME', error.NoSuchFrameError); - test('UNKNOWN_COMMAND', error.UnsupportedOperationError); - test('UNSUPPORTED_OPERATION', error.UnsupportedOperationError); - test('STALE_ELEMENT_REFERENCE', error.StaleElementReferenceError); - test('ELEMENT_NOT_VISIBLE', error.ElementNotVisibleError); - test('INVALID_ELEMENT_STATE', error.InvalidElementStateError); - test('UNKNOWN_ERROR', error.WebDriverError); - test('ELEMENT_NOT_SELECTABLE', error.ElementNotSelectableError); - test('JAVASCRIPT_ERROR', error.JavascriptError); - test('XPATH_LOOKUP_ERROR', error.InvalidSelectorError); - test('TIMEOUT', error.TimeoutError); - test('NO_SUCH_WINDOW', error.NoSuchWindowError); - test('INVALID_COOKIE_DOMAIN', error.InvalidCookieDomainError); - test('UNABLE_TO_SET_COOKIE', error.UnableToSetCookieError); - test('UNEXPECTED_ALERT_OPEN', error.UnexpectedAlertOpenError); - test('NO_SUCH_ALERT', error.NoSuchAlertError); - test('SCRIPT_TIMEOUT', error.ScriptTimeoutError); - test('INVALID_ELEMENT_COORDINATES', error.InvalidElementCoordinatesError); - test('INVALID_SELECTOR_ERROR', error.InvalidSelectorError); - test('SESSION_NOT_CREATED', error.SessionNotCreatedError); - test('MOVE_TARGET_OUT_OF_BOUNDS', error.MoveTargetOutOfBoundsError); - test('INVALID_XPATH_SELECTOR', error.InvalidSelectorError); - test('INVALID_XPATH_SELECTOR_RETURN_TYPE', error.InvalidSelectorError); - test('METHOD_NOT_ALLOWED', error.UnsupportedOperationError); - - describe('UnexpectedAlertOpenError', function() { - it('includes alert text from the response object', function() { - let response = { - status: error.ErrorCode.UNEXPECTED_ALERT_OPEN, - value: { - message: 'hi', - alert: {text: 'alert text here'} - } - }; - assert.throws( - () => error.checkLegacyResponse(response), - (e) => { - assert.equal(error.UnexpectedAlertOpenError, e.constructor); - assert.equal(e.message, 'hi'); - assert.equal(e.getAlertText(), 'alert text here'); - return true; - }); - }); - - it('uses an empty string if alert text omitted', function() { - let response = { - status: error.ErrorCode.UNEXPECTED_ALERT_OPEN, - value: { - message: 'hi' - } - }; - assert.throws( - () => error.checkLegacyResponse(response), - (e) => { - assert.equal(error.UnexpectedAlertOpenError, e.constructor); - assert.equal(e.message, 'hi'); - assert.equal(e.getAlertText(), ''); - return true; - }); - }); - }); - - function test(codeKey, expectedType) { - it(`${codeKey} => ${expectedType.name}`, function() { - let code = error.ErrorCode[codeKey]; - let resp = {status: code, value: {message: 'hi'}}; - assert.throws( - () => error.checkLegacyResponse(resp), - (e) => { - assert.equal(expectedType, e.constructor); - assert.equal(e.message, 'hi'); - return true; - }); - }); - } - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/events_test.js b/node_modules/selenium-webdriver/test/lib/events_test.js deleted file mode 100644 index a02da9747..000000000 --- a/node_modules/selenium-webdriver/test/lib/events_test.js +++ /dev/null @@ -1,177 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const EventEmitter = require('../../lib/events').EventEmitter; - -const assert = require('assert'); -const sinon = require('sinon'); - -describe('EventEmitter', function() { - describe('#emit()', function() { - it('can emit events when nothing is registered', function() { - let emitter = new EventEmitter; - emitter.emit('foo'); - // Ok if no errors are thrown. - }); - - it('can pass args to listeners on emit', function() { - let emitter = new EventEmitter; - let now = Date.now(); - - let messages = []; - emitter.on('foo', (arg) => messages.push(arg)); - - emitter.emit('foo', now); - assert.deepEqual([now], messages); - - emitter.emit('foo', now + 15); - assert.deepEqual([now, now + 15], messages); - }); - }); - - describe('#addListener()', function() { - it('can add multiple listeners for one event', function() { - let emitter = new EventEmitter; - let count = 0; - emitter.addListener('foo', () => count++); - emitter.addListener('foo', () => count++); - emitter.addListener('foo', () => count++); - emitter.emit('foo'); - assert.equal(3, count); - }); - - it('only registers each listener function once', function() { - let emitter = new EventEmitter; - let count = 0; - let onFoo = () => count++; - emitter.addListener('foo', onFoo); - emitter.addListener('foo', onFoo); - emitter.addListener('foo', onFoo); - - emitter.emit('foo'); - assert.equal(1, count); - - emitter.emit('foo'); - assert.equal(2, count); - }); - - it('allows users to specify a custom scope', function() { - let obj = { - count: 0, - inc: function() { - this.count++; - } - }; - let emitter = new EventEmitter; - emitter.addListener('foo', obj.inc, obj); - - emitter.emit('foo'); - assert.equal(1, obj.count); - - emitter.emit('foo'); - assert.equal(2, obj.count); - }); - }); - - describe('#once()', function() { - it('only calls registered callback once', function() { - let emitter = new EventEmitter; - let count = 0; - emitter.once('foo', () => count++); - emitter.once('foo', () => count++); - emitter.once('foo', () => count++); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.emit('foo'); - assert.equal(3, count); - }); - }); - - describe('#removeListeners()', function() { - it('only removes the given listener function', function() { - let emitter = new EventEmitter; - let count = 0; - emitter.addListener('foo', () => count++); - emitter.addListener('foo', () => count++); - - let toRemove = () => count++; - emitter.addListener('foo', toRemove); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.removeListener('foo', toRemove); - emitter.emit('foo'); - assert.equal(5, count); - }); - }); - - describe('#removeAllListeners()', function() { - it('only removes listeners for type if specified', function() { - let emitter = new EventEmitter; - let count = 0; - emitter.addListener('foo', () => count++); - emitter.addListener('foo', () => count++); - emitter.addListener('foo', () => count++); - emitter.addListener('bar', () => count++); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.removeAllListeners('foo'); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.emit('bar'); - assert.equal(4, count); - }); - - it('removes absolutely all listeners if no type specified', function() { - let emitter = new EventEmitter; - let count = 0; - emitter.addListener('foo', () => count++); - emitter.addListener('bar', () => count++); - emitter.addListener('baz', () => count++); - emitter.addListener('baz', () => count++); - - emitter.emit('foo'); - assert.equal(1, count); - - emitter.emit('baz'); - assert.equal(3, count); - - emitter.removeAllListeners(); - - emitter.emit('foo'); - assert.equal(3, count); - - emitter.emit('bar'); - assert.equal(3, count); - - emitter.emit('baz'); - assert.equal(3, count); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/http_test.js b/node_modules/selenium-webdriver/test/lib/http_test.js deleted file mode 100644 index 7cb0050f7..000000000 --- a/node_modules/selenium-webdriver/test/lib/http_test.js +++ /dev/null @@ -1,696 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -var assert = require('assert'), - sinon = require('sinon'); - -var Capabilities = require('../../lib/capabilities').Capabilities, - Command = require('../../lib/command').Command, - CommandName = require('../../lib/command').Name, - error = require('../../lib/error'), - http = require('../../lib/http'), - Session = require('../../lib/session').Session, - promise = require('../../lib/promise'), - WebElement = require('../../lib/webdriver').WebElement; - -describe('http', function() { - describe('buildPath', function() { - it('properly replaces path segments with command parameters', function() { - var parameters = {'sessionId':'foo', 'url':'http://www.google.com'}; - var finalPath = http.buildPath('/session/:sessionId/url', parameters); - assert.equal(finalPath, '/session/foo/url'); - assert.deepEqual(parameters, {'url':'http://www.google.com'}); - }); - - it('handles web element references', function() { - var parameters = {'sessionId':'foo', 'id': WebElement.buildId('bar')}; - - var finalPath = http.buildPath( - '/session/:sessionId/element/:id/click', parameters); - assert.equal(finalPath, '/session/foo/element/bar/click'); - assert.deepEqual(parameters, {}); - }); - - it('throws if missing a parameter', function() { - assert.throws( - () => http.buildPath('/session/:sessionId', {}), - function(err) { - return err instanceof error.InvalidArgumentError - && 'Missing required parameter: sessionId' === err.message; - }); - - assert.throws( - () => http.buildPath( - '/session/:sessionId/element/:id', {'sessionId': 'foo'}), - function(err) { - return err instanceof error.InvalidArgumentError - && 'Missing required parameter: id' === err.message; - }); - }); - - it('does not match on segments that do not start with a colon', function() { - assert.equal( - http.buildPath('/session/foo:bar/baz', {}), - '/session/foo:bar/baz'); - }); - }); - - describe('Executor', function() { - let executor; - let client; - let send; - - beforeEach(function setUp() { - client = new http.Client; - send = sinon.stub(client, 'send'); - executor = new http.Executor(client); - }); - - describe('command routing', function() { - it('rejects unrecognized commands', function() { - return executor.execute(new Command('fake-name')) - .then(assert.fail, err => { - if (err instanceof error.UnknownCommandError - && 'Unrecognized command: fake-name' === err.message) { - return; - } - throw err; - }) - }); - - it('rejects promise if client fails to send request', function() { - let error = new Error('boom'); - send.returns(Promise.reject(error)); - return assertFailsToSend(new Command(CommandName.NEW_SESSION)) - .then(function(e) { - assert.strictEqual(error, e); - assertSent( - 'POST', '/session', {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - it('can execute commands with no URL parameters', function() { - var resp = JSON.stringify({sessionId: 'abc123'}); - send.returns(Promise.resolve(new http.Response(200, {}, resp))); - - let command = new Command(CommandName.NEW_SESSION); - return assertSendsSuccessfully(command).then(function(response) { - assertSent( - 'POST', '/session', {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - it('rejects commands missing URL parameters', function() { - let command = - new Command(CommandName.FIND_CHILD_ELEMENT). - setParameter('sessionId', 's123'). - // Let this be missing: setParameter('id', {'ELEMENT': 'e456'}). - setParameter('using', 'id'). - setParameter('value', 'foo'); - - assert.throws( - () => executor.execute(command), - function(err) { - return err instanceof error.InvalidArgumentError - && 'Missing required parameter: id' === err.message; - }); - assert.ok(!send.called); - }); - - it('replaces URL parameters with command parameters', function() { - var command = new Command(CommandName.GET). - setParameter('sessionId', 's123'). - setParameter('url', 'http://www.google.com'); - - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - - return assertSendsSuccessfully(command).then(function(response) { - assertSent( - 'POST', '/session/s123/url', {'url': 'http://www.google.com'}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - describe('uses correct URL', function() { - beforeEach(() => executor = new http.Executor(client)); - - describe('in legacy mode', function() { - test(CommandName.GET_WINDOW_SIZE, {sessionId:'s123'}, false, - 'GET', '/session/s123/window/current/size'); - - test(CommandName.SET_WINDOW_SIZE, - {sessionId:'s123', width: 1, height: 1}, false, - 'POST', '/session/s123/window/current/size', - {width: 1, height: 1}); - - test(CommandName.MAXIMIZE_WINDOW, {sessionId:'s123'}, false, - 'POST', '/session/s123/window/current/maximize'); - - // This is consistent b/w legacy and W3C, just making sure. - test(CommandName.GET, - {sessionId:'s123', url: 'http://www.example.com'}, false, - 'POST', '/session/s123/url', {url: 'http://www.example.com'}); - }); - - describe('in W3C mode', function() { - test(CommandName.GET_WINDOW_SIZE, - {sessionId:'s123'}, true, - 'GET', '/session/s123/window/size'); - - test(CommandName.SET_WINDOW_SIZE, - {sessionId:'s123', width: 1, height: 1}, true, - 'POST', '/session/s123/window/size', {width: 1, height: 1}); - - test(CommandName.MAXIMIZE_WINDOW, {sessionId:'s123'}, true, - 'POST', '/session/s123/window/maximize'); - - // This is consistent b/w legacy and W3C, just making sure. - test(CommandName.GET, - {sessionId:'s123', url: 'http://www.example.com'}, true, - 'POST', '/session/s123/url', {url: 'http://www.example.com'}); - }); - - function test(command, parameters, w3c, - expectedMethod, expectedUrl, opt_expectedParams) { - it(`command=${command}`, function() { - var resp = JSON.stringify({sessionId: 'abc123'}); - send.returns(Promise.resolve(new http.Response(200, {}, resp))); - - let cmd = new Command(command).setParameters(parameters); - executor.w3c = w3c; - return executor.execute(cmd).then(function() { - assertSent( - expectedMethod, expectedUrl, opt_expectedParams || {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - } - }); - }); - - describe('response parsing', function() { - it('extracts value from JSON response', function() { - var responseObj = { - 'status': error.ErrorCode.SUCCESS, - 'value': 'http://www.google.com' - }; - - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(responseObj)))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, 'http://www.google.com'); - }); - }); - - describe('extracts Session from NEW_SESSION response', function() { - beforeEach(() => executor = new http.Executor(client)); - - const command = new Command(CommandName.NEW_SESSION); - - describe('fails if server returns invalid response', function() { - describe('(empty response)', function() { - test(true); - test(false); - - function test(w3c) { - it('w3c === ' + w3c, function() { - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - executor.w3c = w3c; - return executor.execute(command).then( - () => assert.fail('expected to fail'), - (e) => { - if (!e.message.startsWith('Unable to parse')) { - throw e; - } - }); - }); - } - }); - - describe('(no session ID)', function() { - test(true); - test(false); - - function test(w3c) { - it('w3c === ' + w3c, function() { - let resp = {value:{name: 'Bob'}}; - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(resp)))); - executor.w3c = w3c; - return executor.execute(command).then( - () => assert.fail('expected to fail'), - (e) => { - if (!e.message.startsWith('Unable to parse')) { - throw e; - } - }); - }); - } - }); - }); - - it('handles legacy response', function() { - var rawResponse = {sessionId: 's123', status: 0, value: {name: 'Bob'}}; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - assert.ok(!executor.w3c); - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - - let caps = response.getCapabilities(); - assert.ok(caps instanceof Capabilities); - assert.equal(caps.get('name'), 'Bob'); - - assert.ok(!executor.w3c); - }); - }); - - it('auto-upgrades on W3C response', function() { - let rawResponse = { - value: { - sessionId: 's123', - value: { - name: 'Bob' - } - } - }; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - assert.ok(!executor.w3c); - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - - let caps = response.getCapabilities(); - assert.ok(caps instanceof Capabilities); - assert.equal(caps.get('name'), 'Bob'); - - assert.ok(executor.w3c); - }); - }); - - it('if w3c, does not downgrade on legacy response', function() { - var rawResponse = {sessionId: 's123', status: 0, value: null}; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - executor.w3c = true; - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - assert.equal(response.getCapabilities().size, 0); - assert.ok(executor.w3c, 'should never downgrade'); - }); - }); - - it('handles legacy new session failures', function() { - let rawResponse = { - status: error.ErrorCode.NO_SUCH_ELEMENT, - value: {message: 'hi'} - }; - - send.returns(Promise.resolve( - new http.Response(500, {}, JSON.stringify(rawResponse)))); - - return executor.execute(command) - .then(() => assert.fail('should have failed'), - e => { - assert.ok(e instanceof error.NoSuchElementError); - assert.equal(e.message, 'hi'); - }); - }); - - it('handles w3c new session failures', function() { - let rawResponse = - {value: {error: 'no such element', message: 'oops'}}; - - send.returns(Promise.resolve( - new http.Response(500, {}, JSON.stringify(rawResponse)))); - - return executor.execute(command) - .then(() => assert.fail('should have failed'), - e => { - assert.ok(e instanceof error.NoSuchElementError); - assert.equal(e.message, 'oops'); - }); - }); - }); - - describe('extracts Session from DESCRIBE_SESSION response', function() { - let command; - - beforeEach(function() { - executor = new http.Executor(client); - command = new Command(CommandName.DESCRIBE_SESSION) - .setParameter('sessionId', 'foo'); - }); - - describe('fails if server returns invalid response', function() { - describe('(empty response)', function() { - test(true); - test(false); - - function test(w3c) { - it('w3c === ' + w3c, function() { - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - executor.w3c = w3c; - return executor.execute(command).then( - () => assert.fail('expected to fail'), - (e) => { - if (!e.message.startsWith('Unable to parse')) { - throw e; - } - }); - }); - } - }); - - describe('(no session ID)', function() { - test(true); - test(false); - - function test(w3c) { - it('w3c === ' + w3c, function() { - let resp = {value:{name: 'Bob'}}; - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(resp)))); - executor.w3c = w3c; - return executor.execute(command).then( - () => assert.fail('expected to fail'), - (e) => { - if (!e.message.startsWith('Unable to parse')) { - throw e; - } - }); - }); - } - }); - }); - - it('handles legacy response', function() { - var rawResponse = {sessionId: 's123', status: 0, value: {name: 'Bob'}}; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - assert.ok(!executor.w3c); - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - - let caps = response.getCapabilities(); - assert.ok(caps instanceof Capabilities); - assert.equal(caps.get('name'), 'Bob'); - - assert.ok(!executor.w3c); - }); - }); - - it('does not auto-upgrade on W3C response', function() { - var rawResponse = {value: {sessionId: 's123', value: {name: 'Bob'}}}; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - assert.ok(!executor.w3c); - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - - let caps = response.getCapabilities(); - assert.ok(caps instanceof Capabilities); - assert.equal(caps.get('name'), 'Bob'); - - assert.ok(!executor.w3c); - }); - }); - - it('if w3c, does not downgrade on legacy response', function() { - var rawResponse = {sessionId: 's123', status: 0, value: null}; - - send.returns(Promise.resolve( - new http.Response(200, {}, JSON.stringify(rawResponse)))); - - executor.w3c = true; - return executor.execute(command).then(function(response) { - assert.ok(response instanceof Session); - assert.equal(response.getId(), 's123'); - assert.equal(response.getCapabilities().size, 0); - assert.ok(executor.w3c, 'should never downgrade'); - }); - }); - }); - - it('handles JSON null', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve(new http.Response(200, {}, 'null'))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, null); - }); - }); - - describe('falsy values', function() { - test(0); - test(false); - test(''); - - function test(value) { - it(`value=${value}`, function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(200, {}, - JSON.stringify({status: 0, value: value})))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, value); - }); - }); - } - }); - - it('handles non-object JSON', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve(new http.Response(200, {}, '123'))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, 123); - }); - }); - - it('returns body text when 2xx but not JSON', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(200, {}, 'hello, world\r\ngoodbye, world!'))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, 'hello, world\ngoodbye, world!'); - }); - }); - - it('returns body text when 2xx but invalid JSON', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(200, {}, '['))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, '['); - }); - }); - - it('returns null if no body text and 2xx', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, null); - }); - }); - - it('returns normalized body text when 2xx but not JSON', function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve(new http.Response(200, {}, '\r\n\n\n\r\n'))); - - return executor.execute(command).then(function(response) { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - assert.strictEqual(response, '\n\n\n\n'); - }); - }); - - it('throws UnsupportedOperationError for 404 and body not JSON', - function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(404, {}, 'hello, world\r\ngoodbye, world!'))); - - return executor.execute(command) - .then( - () => assert.fail('should have failed'), - checkError( - error.UnsupportedOperationError, - 'hello, world\ngoodbye, world!')); - }); - - it('throws WebDriverError for generic 4xx when body not JSON', - function() { - var command = new Command(CommandName.GET_CURRENT_URL) - .setParameter('sessionId', 's123'); - - send.returns(Promise.resolve( - new http.Response(500, {}, 'hello, world\r\ngoodbye, world!'))); - - return executor.execute(command) - .then( - () => assert.fail('should have failed'), - checkError( - error.WebDriverError, - 'hello, world\ngoodbye, world!')) - .then(function() { - assertSent('GET', '/session/s123/url', {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - }); - - it('canDefineNewCommands', function() { - executor.defineCommand('greet', 'GET', '/person/:name'); - - var command = new Command('greet'). - setParameter('name', 'Bob'); - - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - - return assertSendsSuccessfully(command).then(function(response) { - assertSent('GET', '/person/Bob', {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - it('canRedefineStandardCommands', function() { - executor.defineCommand(CommandName.GO_BACK, 'POST', '/custom/back'); - - var command = new Command(CommandName.GO_BACK). - setParameter('times', 3); - - send.returns(Promise.resolve(new http.Response(200, {}, ''))); - - return assertSendsSuccessfully(command).then(function(response) { - assertSent('POST', '/custom/back', {'times': 3}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - it('accepts promised http clients', function() { - executor = new http.Executor(Promise.resolve(client)); - - var resp = JSON.stringify({sessionId: 'abc123'}); - send.returns(Promise.resolve(new http.Response(200, {}, resp))); - - let command = new Command(CommandName.NEW_SESSION); - return executor.execute(command).then(response => { - assertSent( - 'POST', '/session', {}, - [['Accept', 'application/json; charset=utf-8']]); - }); - }); - - function entries(map) { - let entries = []; - for (let e of map.entries()) { - entries.push(e); - } - return entries; - } - - function checkError(type, message) { - return function(e) { - if (e instanceof type) { - assert.strictEqual(e.message, message); - } else { - throw e; - } - }; - } - - function assertSent(method, path, data, headers) { - assert.ok(send.calledWith(sinon.match(function(value) { - assert.equal(value.method, method); - assert.equal(value.path, path); - assert.deepEqual(value.data, data); - assert.deepEqual(entries(value.headers), headers); - return true; - }))); - } - - function assertSendsSuccessfully(command) { - return executor.execute(command).then(function(response) { - return response; - }); - } - - function assertFailsToSend(command, opt_onError) { - return executor.execute(command).then( - () => {throw Error('should have failed')}, - (e) => {return e}); - } - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/logging_test.js b/node_modules/selenium-webdriver/test/lib/logging_test.js deleted file mode 100644 index 29d2af40f..000000000 --- a/node_modules/selenium-webdriver/test/lib/logging_test.js +++ /dev/null @@ -1,272 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); -const sinon = require('sinon'); -const logging = require('../../lib/logging'); - -describe('logging', function() { - let mgr, root, clock; - - beforeEach(function setUp() { - mgr = new logging.LogManager; - root = mgr.getLogger(''); - - clock = sinon.useFakeTimers(); - }); - - afterEach(function tearDown() { - clock.restore(); - }); - - describe('LogManager', function() { - describe('getLogger()', function() { - it('handles falsey input', function() { - assert.strictEqual(root, mgr.getLogger()); - assert.strictEqual(root, mgr.getLogger('')); - assert.strictEqual(root, mgr.getLogger(null)); - assert.strictEqual(root, mgr.getLogger(0)); - }); - - it('creates parent loggers', function() { - let logger = mgr.getLogger('foo.bar.baz'); - assert.strictEqual(logger.parent_, mgr.getLogger('foo.bar')); - - logger = logger.parent_; - assert.strictEqual(logger.parent_, mgr.getLogger('foo')); - - logger = logger.parent_; - assert.strictEqual(logger.parent_, mgr.getLogger('')); - - assert.strictEqual(logger.parent_.parent_, null); - }); - }); - }); - - describe('Logger', function() { - describe('getEffectiveLevel()', function() { - it('defaults to OFF', function() { - assert.strictEqual(root.getLevel(), logging.Level.OFF); - assert.strictEqual(root.getEffectiveLevel(), logging.Level.OFF); - - root.setLevel(null); - assert.strictEqual(root.getLevel(), null); - assert.strictEqual(root.getEffectiveLevel(), logging.Level.OFF); - }); - - it('uses own level if set', function() { - let logger = mgr.getLogger('foo.bar.baz'); - assert.strictEqual(logger.getLevel(), null); - assert.strictEqual(logger.getEffectiveLevel(), logging.Level.OFF); - - logger.setLevel(logging.Level.INFO); - assert.strictEqual(logger.getLevel(), logging.Level.INFO); - assert.strictEqual(logger.getEffectiveLevel(), logging.Level.INFO); - }); - - it('uses level from set on nearest parent', function() { - let ancestor = mgr.getLogger('foo'); - ancestor.setLevel(logging.Level.SEVERE); - - let logger = mgr.getLogger('foo.bar.baz'); - assert.strictEqual(logger.getLevel(), null); - assert.strictEqual(logger.getEffectiveLevel(), logging.Level.SEVERE); - }); - }); - - describe('isLoggable()', function() { - it('compares level against logger\'s effective level', function() { - const log1 = mgr.getLogger('foo'); - log1.setLevel(logging.Level.WARNING); - - const log2 = mgr.getLogger('foo.bar.baz'); - - assert(!log2.isLoggable(logging.Level.FINEST)); - assert(!log2.isLoggable(logging.Level.INFO)); - assert(log2.isLoggable(logging.Level.WARNING)); - assert(log2.isLoggable(logging.Level.SEVERE)); - - log2.setLevel(logging.Level.INFO); - - assert(!log2.isLoggable(logging.Level.FINEST)); - assert(log2.isLoggable(logging.Level.INFO)); - assert(log2.isLoggable(logging.Level.WARNING)); - assert(log2.isLoggable(logging.Level.SEVERE)); - - log2.setLevel(logging.Level.ALL); - - assert(log2.isLoggable(logging.Level.FINEST)); - assert(log2.isLoggable(logging.Level.INFO)); - assert(log2.isLoggable(logging.Level.WARNING)); - assert(log2.isLoggable(logging.Level.SEVERE)); - }); - - it('Level.OFF is never loggable', function() { - function test(level) { - root.setLevel(level); - assert(!root.isLoggable(logging.Level.OFF), - 'OFF should not be loggable at ' + level); - } - - test(logging.Level.ALL); - test(logging.Level.INFO); - test(logging.Level.OFF); - }); - }); - - describe('log()', function() { - it('does not invoke loggable if message is not loggable', function() { - const log = mgr.getLogger('foo'); - log.setLevel(logging.Level.OFF); - - let callback = sinon.spy(); - log.addHandler(callback); - root.addHandler(callback); - - assert(!callback.called); - }); - - it('invokes handlers for each parent logger', function() { - const cb1 = sinon.spy(); - const cb2 = sinon.spy(); - const cb3 = sinon.spy(); - const cb4 = sinon.spy(); - - const log1 = mgr.getLogger('foo'); - const log2 = mgr.getLogger('foo.bar'); - const log3 = mgr.getLogger('foo.bar.baz'); - const log4 = mgr.getLogger('foo.bar.baz.quot'); - - log1.addHandler(cb1); - log1.setLevel(logging.Level.INFO); - - log2.addHandler(cb2); - log2.setLevel(logging.Level.WARNING); - - log3.addHandler(cb3); - log3.setLevel(logging.Level.FINER); - - clock.tick(123456); - - log4.finest('this is the finest message'); - log4.finer('this is a finer message'); - log4.info('this is an info message'); - log4.warning('this is a warning message'); - log4.severe('this is a severe message'); - - assert.equal(4, cb1.callCount); - assert.equal(4, cb2.callCount); - assert.equal(4, cb3.callCount); - - const entry1 = new logging.Entry( - logging.Level.FINER, - '[foo.bar.baz.quot] this is a finer message', - 123456); - const entry2 = new logging.Entry( - logging.Level.INFO, - '[foo.bar.baz.quot] this is an info message', - 123456); - const entry3 = new logging.Entry( - logging.Level.WARNING, - '[foo.bar.baz.quot] this is a warning message', - 123456); - const entry4 = new logging.Entry( - logging.Level.SEVERE, - '[foo.bar.baz.quot] this is a severe message', - 123456); - - check(cb1.getCall(0).args[0], entry1); - check(cb1.getCall(1).args[0], entry2); - check(cb1.getCall(2).args[0], entry3); - check(cb1.getCall(3).args[0], entry4); - - check(cb2.getCall(0).args[0], entry1); - check(cb2.getCall(1).args[0], entry2); - check(cb2.getCall(2).args[0], entry3); - check(cb2.getCall(3).args[0], entry4); - - check(cb3.getCall(0).args[0], entry1); - check(cb3.getCall(1).args[0], entry2); - check(cb3.getCall(2).args[0], entry3); - check(cb3.getCall(3).args[0], entry4); - - function check(entry, expected) { - assert.equal(entry.level, expected.level, 'wrong level'); - assert.equal(entry.message, expected.message, 'wrong message'); - assert.equal(entry.timestamp, expected.timestamp, 'wrong time'); - } - }); - - it('does not invoke removed handler', function() { - root.setLevel(logging.Level.INFO); - const cb = sinon.spy(); - - root.addHandler(cb); - root.info('hi'); - assert.equal(1, cb.callCount); - - assert(root.removeHandler(cb)); - root.info('bye'); - assert.equal(1, cb.callCount); - - assert(!root.removeHandler(cb)); - }); - }); - }); - - describe('getLevel()', function() { - it('converts named levels', function() { - assert.strictEqual(logging.Level.DEBUG, logging.getLevel('DEBUG')); - assert.strictEqual(logging.Level.ALL, logging.getLevel('FAKE')); - }); - - it('converts numeric levels', function() { - assert.strictEqual( - logging.Level.DEBUG, - logging.getLevel(logging.Level.DEBUG.value)); - }); - - it('normalizes numeric levels', function() { - assert.strictEqual( - logging.Level.OFF, - logging.getLevel(logging.Level.OFF.value * 2)); - - let diff = logging.Level.SEVERE.value - logging.Level.WARNING.value; - assert.strictEqual( - logging.Level.WARNING, - logging.getLevel(logging.Level.WARNING.value + (diff * .5))); - - assert.strictEqual(logging.Level.ALL, logging.getLevel(0)); - assert.strictEqual(logging.Level.ALL, logging.getLevel(-1)); - }); - }); - - describe('Preferences', function() { - it('can be converted to JSON', function() { - let prefs = new logging.Preferences; - assert.equal('{}', JSON.stringify(prefs)); - - prefs.setLevel('foo', logging.Level.DEBUG); - assert.equal('{"foo":"DEBUG"}', JSON.stringify(prefs)); - - prefs.setLevel(logging.Type.BROWSER, logging.Level.FINE); - assert.equal('{"foo":"DEBUG","browser":"FINE"}', JSON.stringify(prefs)); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/promise_aplus_test.js b/node_modules/selenium-webdriver/test/lib/promise_aplus_test.js deleted file mode 100644 index 207f490a1..000000000 --- a/node_modules/selenium-webdriver/test/lib/promise_aplus_test.js +++ /dev/null @@ -1,78 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const promise = require('../../lib/promise'); -const {enablePromiseManager} = require('../../lib/test/promise'); - -describe('Promises/A+ Compliance Tests', function() { - enablePromiseManager(() => { - // The promise spec does not define behavior for unhandled rejections and - // assumes they are effectively swallowed. This is not the case with our - // implementation, so we have to disable error propagation to test that the - // rest of our behavior is compliant. - // We run the tests with a separate instance of the control flow to ensure - // disablign error propagation does not impact other tests. - var flow = new promise.ControlFlow(); - flow.setPropagateUnhandledRejections(false); - - // Skip the tests in 2.2.6.1/2. We are not compliant in these scenarios. - var realDescribe = global.describe; - global.describe = function(name, fn) { - realDescribe(name, function() { - var prefix = 'Promises/A+ Compliance Tests ' - + 'SELENIUM_PROMISE_MANAGER=true 2.2.6: ' - + '`then` may be called multiple times on the same promise.'; - var suffix = 'even when one handler is added inside another handler'; - if (this.fullTitle().startsWith(prefix) - && this.fullTitle().endsWith(suffix)) { - var realSpecify = global.specify; - try { - global.specify = function(name) { - realSpecify(name); - }; - fn(); - } finally { - global.specify = realSpecify; - } - } else { - fn(); - } - }); - }; - - require('promises-aplus-tests').mocha({ - resolved: function(value) { - return new promise.Promise((fulfill) => fulfill(value), flow); - }, - rejected: function(error) { - return new promise.Promise((_, reject) => reject(error), flow); - }, - deferred: function() { - var d = new promise.Deferred(flow); - return { - resolve: d.fulfill, - reject: d.reject, - promise: d.promise - }; - } - }); - - global.describe = realDescribe; - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/promise_error_test.js b/node_modules/selenium-webdriver/test/lib/promise_error_test.js deleted file mode 100644 index b89a2f875..000000000 --- a/node_modules/selenium-webdriver/test/lib/promise_error_test.js +++ /dev/null @@ -1,884 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -/** - * @fileoverview Contains tests against promise error handling. Many tests use - * NativePromise to control test termination independent of promise - * (and notably promise.ControlFlow). - */ - -'use strict'; - -const testutil = require('./testutil'); - -const assert = require('assert'); -const promise = require('../../lib/promise'); -const {enablePromiseManager} = require('../../lib/test/promise'); - -const NativePromise = Promise; -const StubError = testutil.StubError; -const throwStubError = testutil.throwStubError; -const assertIsStubError = testutil.assertIsStubError; - -describe('promise error handling', function() { - enablePromiseManager(() => { - var flow, uncaughtExceptions; - - beforeEach(function setUp() { - if (promise.USE_PROMISE_MANAGER) { - flow = promise.controlFlow(); - uncaughtExceptions = []; - flow.on('uncaughtException', onUncaughtException); - } - }); - - afterEach(function tearDown() { - if (promise.USE_PROMISE_MANAGER) { - return waitForIdle(flow).then(function() { - assert.deepEqual( - [], uncaughtExceptions, 'There were uncaught exceptions'); - flow.reset(); - }); - } - }); - - function onUncaughtException(e) { - uncaughtExceptions.push(e); - } - - function waitForAbort(opt_flow, opt_n) { - var n = opt_n || 1; - var theFlow = opt_flow || flow; - theFlow.removeAllListeners( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION); - return new NativePromise(function(fulfill, reject) { - theFlow.once('idle', function() { - reject(Error('expected flow to report an unhandled error')); - }); - - var errors = []; - theFlow.on('uncaughtException', onError); - function onError(e) { - errors.push(e); - if (errors.length === n) { - theFlow.removeListener('uncaughtException', onError); - fulfill(n === 1 ? errors[0] : errors); - } - } - }); - } - - function waitForIdle(opt_flow) { - var theFlow = opt_flow || flow; - return new NativePromise(function(fulfill, reject) { - if (theFlow.isIdle()) { - fulfill(); - return; - } - theFlow.once('idle', fulfill); - theFlow.once('uncaughtException', reject); - }); - } - - it('testRejectedPromiseTriggersErrorCallback', function() { - return promise.rejected(new StubError). - then(assert.fail, assertIsStubError); - }); - - describe('callback throws trigger subsequent error callback', function() { - it('fulfilled promise', function() { - return promise.fulfilled(). - then(throwStubError). - then(assert.fail, assertIsStubError); - }); - - it('rejected promise', function() { - var e = Error('not the droids you are looking for'); - return promise.rejected(e). - then(assert.fail, throwStubError). - then(assert.fail, assertIsStubError); - }); - }); - - describe('callback returns rejected promise triggers subsequent errback', function() { - it('from fulfilled callback', function() { - return promise.fulfilled().then(function() { - return promise.rejected(new StubError); - }).then(assert.fail, assertIsStubError); - }); - - it('from rejected callback', function() { - var e = Error('not the droids you are looking for'); - return promise.rejected(e). - then(assert.fail, function() { - return promise.rejected(new StubError); - }). - then(assert.fail, assertIsStubError); - }); - }); - - it('testReportsUnhandledRejectionsThroughTheControlFlow', function() { - promise.rejected(new StubError); - return waitForAbort().then(assertIsStubError); - }); - - describe('multiple unhandled rejections outside a task', function() { - it('are reported in order they occurred', function() { - var e1 = Error('error 1'); - var e2 = Error('error 2'); - - promise.rejected(e1); - promise.rejected(e2); - - return waitForAbort(flow).then(function(error) { - assert.ok( - error instanceof promise.MultipleUnhandledRejectionError); - // TODO: switch to Array.from when we drop node 0.12.x - var errors = []; - for (var e of error.errors) { - errors.push(e); - } - assert.deepEqual([e1, e2], errors); - }); - }); - }); - - describe('does not report unhandled rejection when', function() { - it('handler added before next tick', function() { - promise.rejected(new StubError).then(assert.fail, assertIsStubError); - return waitForIdle(); - }); - - it('added async but before next tick', function() { - var called = false; - return new NativePromise(function(fulfill, reject) { - var aPromise; - NativePromise.resolve().then(function() { - aPromise.then(assert.fail, function(e) { - called = true; - assertIsStubError(e); - }); - waitForIdle().then(fulfill, reject); - }); - aPromise = promise.rejected(new StubError); - }).then(function() { - assert.ok(called); - }) - }); - }); - - it('testTaskThrows', function() { - return flow.execute(throwStubError).then(assert.fail, assertIsStubError); - }); - - it('testTaskReturnsRejectedPromise', function() { - return flow.execute(function() { - return promise.rejected(new StubError) - }).then(assert.fail, assertIsStubError); - }); - - it('testTaskHasUnhandledRejection', function() { - return flow.execute(function() { - promise.rejected(new StubError) - }).then(assert.fail, assertIsStubError); - }); - - it('testTaskfails_returnedPromiseIsUnhandled', function() { - flow.execute(throwStubError); - return waitForAbort().then(assertIsStubError); - }); - - it('testTaskHasUnhandledRejection_cancelsRemainingSubTasks', function() { - var seen = []; - flow.execute(function() { - promise.rejected(new StubError); - - flow.execute(() => seen.push('a')) - .then(() => seen.push('b'), (e) => seen.push(e)); - flow.execute(() => seen.push('c')) - .then(() => seen.push('b'), (e) => seen.push(e)); - }); - - return waitForAbort() - .then(assertIsStubError) - .then(() => assert.deepEqual([], seen)); - }); - - describe('nested task failures', function() { - it('returns up to paren', function() { - return flow.execute(function() { - return flow.execute(function() { - return flow.execute(throwStubError); - }); - }).then(assert.fail, assertIsStubError); - }); - - it('task throws; uncaught error bubbles up', function() { - flow.execute(function() { - flow.execute(function() { - flow.execute(throwStubError); - }); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('task throws; uncaught error bubbles up; is caught at root', function() { - flow.execute(function() { - flow.execute(function() { - flow.execute(throwStubError); - }); - }).then(assert.fail, assertIsStubError); - return waitForIdle(); - }); - - it('unhandled rejection bubbles up', function() { - flow.execute(function() { - flow.execute(function() { - flow.execute(function() { - promise.rejected(new StubError); - }); - }); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('unhandled rejection bubbles up; caught at root', function() { - flow.execute(function() { - flow.execute(function() { - promise.rejected(new StubError); - }); - }).then(assert.fail, assertIsStubError); - return waitForIdle(); - }); - - it('mixtureof hanging and free subtasks', function() { - flow.execute(function() { - return flow.execute(function() { - flow.execute(throwStubError); - }); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('cancels remaining tasks', function() { - var seen = []; - flow.execute(function() { - flow.execute(() => promise.rejected(new StubError)); - flow.execute(() => seen.push('a')) - .then(() => seen.push('b'), (e) => seen.push(e)); - flow.execute(() => seen.push('c')) - .then(() => seen.push('b'), (e) => seen.push(e)); - }); - - return waitForAbort() - .then(assertIsStubError) - .then(() => assert.deepEqual([], seen)); - }); - }); - - it('testTaskReturnsPromiseLikeObjectThatInvokesErrback', function() { - return flow.execute(function() { - return { - 'then': function(_, errback) { - errback('abc123'); - } - }; - }).then(assert.fail, function(value) { - assert.equal('abc123', value); - }); - }); - - describe('ControlFlow#wait();', function() { - describe('condition throws;', function() { - it('failure is caught', function() { - return flow.wait(throwStubError, 50).then(assert.fail, assertIsStubError); - }); - - it('failure is not caught', function() { - flow.wait(throwStubError, 50); - return waitForAbort().then(assertIsStubError); - }); - }); - - describe('condition returns promise', function() { - it('failure is caught', function() { - return flow.wait(function() { - return promise.rejected(new StubError); - }, 50).then(assert.fail, assertIsStubError); - }); - - it('failure is not caught', function() { - flow.wait(function() { - return promise.rejected(new StubError); - }, 50); - return waitForAbort().then(assertIsStubError); - }); - }); - - describe('condition has unhandled promise rejection', function() { - it('failure is caught', function() { - return flow.wait(function() { - promise.rejected(new StubError); - }, 50).then(assert.fail, assertIsStubError); - }); - - it('failure is not caught', function() { - flow.wait(function() { - promise.rejected(new StubError); - }, 50); - return waitForAbort().then(assertIsStubError); - }); - }); - - describe('condition has subtask failure', function() { - it('failure is caught', function() { - return flow.wait(function() { - flow.execute(function() { - flow.execute(throwStubError); - }); - }, 50).then(assert.fail, assertIsStubError); - }); - - it('failure is not caught', function() { - flow.wait(function() { - flow.execute(function() { - flow.execute(throwStubError); - }); - }, 50); - return waitForAbort().then(assertIsStubError); - }); - }); - }); - - describe('errback throws a new error', function() { - it('start with normal promise', function() { - var error = Error('an error'); - return promise.rejected(error). - catch(function(e) { - assert.equal(e, error); - throw new StubError; - }). - catch(assertIsStubError); - }); - - it('start with task result', function() { - var error = Error('an error'); - return flow.execute(function() { - throw error; - }). - catch(function(e) { - assert.equal(e, error); - throw new StubError; - }). - catch(assertIsStubError); - }); - - it('start with normal promise; uncaught error', function() { - var error = Error('an error'); - promise.rejected(error). - catch(function(e) { - assert.equal(e, error); - throw new StubError; - }); - return waitForAbort().then(assertIsStubError); - }); - - it('start with task result; uncaught error', function() { - var error = Error('an error'); - flow.execute(function() { - throw error; - }). - catch(function(e) { - assert.equal(e, error); - throw new StubError; - }); - return waitForAbort().then(assertIsStubError); - }); - }); - - it('thrownPromiseCausesCallbackRejection', function() { - let p = promise.fulfilled(1234); - return promise.fulfilled().then(function() { - throw p; - }).then(assert.fail, function(value) { - assert.strictEqual(p, value); - }); - }); - - describe('task throws promise', function() { - it('promise was fulfilled', function() { - var toThrow = promise.fulfilled(1234); - flow.execute(function() { - throw toThrow; - }).then(assert.fail, function(value) { - assert.equal(toThrow, value); - return toThrow; - }).then(function(value) { - assert.equal(1234, value); - }); - return waitForIdle(); - }); - - it('promise was rejected', function() { - var toThrow = promise.rejected(new StubError); - toThrow.catch(function() {}); // For tearDown. - flow.execute(function() { - throw toThrow; - }).then(assert.fail, function(e) { - assert.equal(toThrow, e); - return e; - }).then(assert.fail, assertIsStubError); - return waitForIdle(); - }); - }); - - it('testFailsTaskIfThereIsAnUnhandledErrorWhileWaitingOnTaskResult', function() { - var d = promise.defer(); - flow.execute(function() { - promise.rejected(new StubError); - return d.promise; - }).then(assert.fail, assertIsStubError); - - return waitForIdle().then(function() { - return d.promise; - }).then(assert.fail, function(e) { - assert.equal('CancellationError: StubError', e.toString()); - }); - }); - - it('testFailsParentTaskIfAsyncScheduledTaskFails', function() { - var d = promise.defer(); - flow.execute(function() { - flow.execute(throwStubError); - return d.promise; - }).then(assert.fail, assertIsStubError); - - return waitForIdle().then(function() { - return d.promise; - }).then(assert.fail, function(e) { - assert.equal('CancellationError: StubError', e.toString()); - }); - }); - - describe('long stack traces', function() { - afterEach(() => promise.LONG_STACK_TRACES = false); - - it('always includes task stacks in failures', function() { - promise.LONG_STACK_TRACES = false; - flow.execute(function() { - flow.execute(function() { - flow.execute(throwStubError, 'throw error'); - }, 'two'); - }, 'three'). - then(assert.fail, function(e) { - assertIsStubError(e); - if (typeof e.stack !== 'string') { - return; - } - var messages = e.stack.split(/\n/).filter(function(line, index) { - return /^From: /.test(line); - }); - assert.deepEqual([ - 'From: Task: throw error', - 'From: Task: two', - 'From: Task: three' - ], messages); - }); - return waitForIdle(); - }); - - it('does not include completed tasks', function () { - flow.execute(function() {}, 'succeeds'); - flow.execute(throwStubError, 'kaboom').then(assert.fail, function(e) { - assertIsStubError(e); - if (typeof e.stack !== 'string') { - return; - } - var messages = e.stack.split(/\n/).filter(function(line, index) { - return /^From: /.test(line); - }); - assert.deepEqual(['From: Task: kaboom'], messages); - }); - return waitForIdle(); - }); - - it('does not include promise chain when disabled', function() { - promise.LONG_STACK_TRACES = false; - flow.execute(function() { - flow.execute(function() { - return promise.fulfilled(). - then(function() {}). - then(function() {}). - then(throwStubError); - }, 'eventually assert.fails'); - }, 'start'). - then(assert.fail, function(e) { - assertIsStubError(e); - if (typeof e.stack !== 'string') { - return; - } - var messages = e.stack.split(/\n/).filter(function(line, index) { - return /^From: /.test(line); - }); - assert.deepEqual([ - 'From: Task: eventually assert.fails', - 'From: Task: start' - ], messages); - }); - return waitForIdle(); - }); - - it('includes promise chain when enabled', function() { - promise.LONG_STACK_TRACES = true; - flow.execute(function() { - flow.execute(function() { - return promise.fulfilled(). - then(function() {}). - then(function() {}). - then(throwStubError); - }, 'eventually assert.fails'); - }, 'start'). - then(assert.fail, function(e) { - assertIsStubError(e); - if (typeof e.stack !== 'string') { - return; - } - var messages = e.stack.split(/\n/).filter(function(line, index) { - return /^From: /.test(line); - }); - assert.deepEqual([ - 'From: Promise: then', - 'From: Task: eventually assert.fails', - 'From: Task: start' - ], messages); - }); - return waitForIdle(); - }); - }); - - describe('frame cancels remaining tasks', function() { - it('on unhandled task failure', function() { - var run = false; - return flow.execute(function() { - flow.execute(throwStubError); - flow.execute(function() { run = true; }); - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.ok(!run); - }); - }); - - it('on unhandled promise rejection', function() { - var run = false; - return flow.execute(function() { - promise.rejected(new StubError); - flow.execute(function() { run = true; }); - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.ok(!run); - }); - }); - - it('if task throws', function() { - var run = false; - return flow.execute(function() { - flow.execute(function() { run = true; }); - throw new StubError; - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.ok(!run); - }); - }); - - describe('task callbacks scheduled in another frame', function() { - flow = promise.controlFlow(); - function noop() {} - - let subTask; - - before(function() { - flow.execute(function() { - // This task will be discarded and never run because of the error below. - subTask = flow.execute(() => 'abc'); - throw new StubError('stub'); - }).catch(noop); - }); - - function assertCancellation(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal( - 'Task was discarded due to a previous failure: stub', e.message); - } - - it('are rejected with cancellation error', function() { - let result; - return Promise.resolve().then(function() { - return flow.execute(function() { - result = subTask.then(assert.fail); - }); - }) - .then(() => result) - .then(assert.fail, assertCancellation); - }); - - it('cancellation errors propagate through callbacks (1)', function() { - let result; - return Promise.resolve().then(function() { - return flow.execute(function() { - result = subTask - .then(assert.fail, assertCancellation) - .then(() => 'abc123'); - }); - }) - .then(() => result) - .then(value => assert.equal('abc123', value)); - }); - - it('cancellation errors propagate through callbacks (2)', function() { - let result; - return Promise.resolve().then(function() { - return flow.execute(function() { - result = subTask.then(assert.fail) - .then(noop, assertCancellation) - .then(() => 'fin'); - }); - }) - // Verify result actually computed successfully all the way through. - .then(() => result) - .then(value => assert.equal('fin', value)); - }); - }); - }); - - it('testRegisteredTaskCallbacksAreDroppedWhenTaskIsCancelled_return', function() { - var seen = []; - return flow.execute(function() { - flow.execute(throwStubError); - - flow.execute(function() { - seen.push(1); - }).then(function() { - seen.push(2); - }, function() { - seen.push(3); - }); - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.deepEqual([], seen); - }); - }); - - it('testRegisteredTaskCallbacksAreDroppedWhenTaskIsCancelled_withReturn', function() { - var seen = []; - return flow.execute(function() { - flow.execute(throwStubError); - - return flow.execute(function() { - seen.push(1); - }).then(function() { - seen.push(2); - }, function() { - seen.push(3); - }); - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.deepEqual([], seen); - }); - }); - - it('testTasksWithinACallbackAreDroppedIfContainingTaskIsAborted', function() { - var seen = []; - return flow.execute(function() { - flow.execute(throwStubError); - - // None of the callbacks on this promise should execute because the - // task assert.failure above is never handled, causing the containing task to - // abort. - promise.fulfilled().then(function() { - seen.push(1); - return flow.execute(function() { - seen.push(2); - }); - }).finally(function() { - seen.push(3); - }); - - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.deepEqual([], seen); - }); - }); - - it('testTaskIsCancelledAfterWaitTimeout', function() { - var seen = []; - return flow.execute(function() { - flow.wait(function() { - return promise.delayed(50); - }, 5); - - return flow.execute(function() { - seen.push(1); - }).then(function() { - seen.push(2); - }, function() { - seen.push(3); - }); - }).then(assert.fail, function() { - assert.deepEqual([], seen); - }); - }); - - describe('task callbacks get cancellation error if registered after task was cancelled', function() { - it('(a)', function() { - var task; - flow.execute(function() { - flow.execute(throwStubError); - task = flow.execute(function() {}); - }).then(assert.fail, assertIsStubError); - return waitForIdle().then(function() { - return task.then(assert.fail, function(e) { - assert.ok(e instanceof promise.CancellationError); - }); - }); - }); - - it('(b)', function() { - var seen = []; - - var task; - flow.execute(function() { - flow.execute(throwStubError); - task = flow.execute(function() {}); - - task.then(() => seen.push(1)) - .then(() => seen.push(2)); - task.then(() => seen.push(3)) - .then(() => seen.push(4)); - - }).then(assert.fail, assertIsStubError); - - return waitForIdle().then(function() { - return task.then(assert.fail, function(e) { - seen.push(5); - assert.ok(e instanceof promise.CancellationError); - }); - }).then(() => assert.deepEqual([5], seen)); - }); - }); - - it('unhandledRejectionInParallelTaskQueue', function() { - var seen = []; - function schedule(name) { - return flow.execute(() => seen.push(name), name); - } - - flow.async(function() { - schedule('a.1'); - flow.execute(throwStubError, 'a.2 (throws)'); - }); - - var b3; - flow.async(function() { - schedule('b.1'); - schedule('b.2'); - b3 = schedule('b.3'); - }); - - var c3; - flow.async(function() { - schedule('c.1'); - schedule('c.2'); - c3 = schedule('c.3'); - }); - - function assertWasCancelled(p) { - return p.then(assert.fail, function(e) { - assert.ok(e instanceof promise.CancellationError); - }); - } - - return waitForAbort() - .then(function() { - assert.deepEqual(['a.1', 'b.1', 'c.1', 'b.2', 'c.2'], seen); - }) - .then(() => assertWasCancelled(b3)) - .then(() => assertWasCancelled(c3)); - }); - - it('errorsInAsyncFunctionsAreReportedAsUnhandledRejection', function() { - flow.removeAllListeners(); // For tearDown. - - var task; - return new Promise(function(fulfill) { - flow.once('uncaughtException', fulfill); - flow.async(function() { - task = flow.execute(function() {}); - throw Error('boom'); - }); - }).then(function(error) { - assert.ok(error instanceof promise.CancellationError); - return task.catch(function(error) { - assert.ok(error instanceof promise.CancellationError); - }); - }); - }); - - describe('does not wait for values thrown from callbacks to be resolved', function() { - it('(a)', function() { - var p1 = promise.fulfilled(); - var reason = promise.fulfilled('should not see me'); - return p1.then(function() { - throw reason; - }).then(assert.fail, function(e) { - assert.equal(reason, e); - }); - }); - - it('(b)', function() { - var p1 = promise.fulfilled(); - var reason = promise.rejected('should not see me'); - reason.catch(function() {}); // For tearDown. - return p1.then(function() { - throw reason; - }).then(assert.fail, function(e) { - assert.equal(reason, e); - }); - }); - - it('(c)', function() { - var p1 = promise.fulfilled(); - var reason = promise.defer(); - setTimeout(() => reason.fulfill('should not see me'), 100); - return p1.then(function() { - throw reason.promise; - }).then(assert.fail, function(e) { - assert.equal(reason.promise, e); - }); - }); - - it('(d)', function() { - var p1 = promise.fulfilled(); - var reason = {then: function() {}}; // A thenable like object. - return p1.then(function() { - throw reason; - }).then(assert.fail, function(e) { - assert.equal(reason, e); - }); - }); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/promise_flow_test.js b/node_modules/selenium-webdriver/test/lib/promise_flow_test.js deleted file mode 100644 index 407fd547e..000000000 --- a/node_modules/selenium-webdriver/test/lib/promise_flow_test.js +++ /dev/null @@ -1,2288 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); -const fail = assert.fail; -const sinon = require('sinon'); - -const testutil = require('./testutil'); -const {TimeoutError} = require('../../lib/error'); -const promise = require('../../lib/promise'); -const {enablePromiseManager} = require('../../lib/test/promise'); - -const NativePromise = Promise; - -// Aliases for readability. -const StubError = testutil.StubError; -const assertIsStubError = testutil.assertIsStubError; -const callbackPair = testutil.callbackPair; -const throwStubError = testutil.throwStubError; - -describe('promise control flow', function() { - enablePromiseManager(() => { - let flow, flowHistory, messages, uncaughtExceptions; - - beforeEach(function setUp() { - promise.LONG_STACK_TRACES = false; - flow = new promise.ControlFlow(); - promise.setDefaultFlow(flow); - messages = []; - flowHistory = []; - - uncaughtExceptions = []; - flow.on(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, - onUncaughtException); - }); - - afterEach(function tearDown() { - flow.removeAllListeners( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION); - assert.deepEqual([], uncaughtExceptions, - 'There were uncaught exceptions'); - flow.reset(); - promise.LONG_STACK_TRACES = false; - }); - - function onUncaughtException(e) { - uncaughtExceptions.push(e); - } - - function defer() { - let d = {}; - let promise = new Promise((resolve, reject) => { - Object.assign(d, {resolve, reject}); - }); - d.promise = promise; - return d; - } - - function waitForAbort(opt_flow) { - var theFlow = opt_flow || flow; - theFlow.removeAllListeners( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION); - return new NativePromise(function(fulfill, reject) { - theFlow.once(promise.ControlFlow.EventType.IDLE, function() { - reject(Error('expected flow to report an unhandled error')); - }); - theFlow.once( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, - fulfill); - }); - } - - function waitForIdle(opt_flow) { - var theFlow = opt_flow || flow; - return new NativePromise(function(fulfill, reject) { - theFlow.once(promise.ControlFlow.EventType.IDLE, fulfill); - theFlow.once( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, reject); - }); - } - - function timeout(ms) { - return new NativePromise(function(fulfill) { - setTimeout(fulfill, ms); - }); - } - - - function schedule(msg, opt_return) { - return scheduleAction(msg, function() { - return opt_return; - }); - } - - /** - * @param {string} value The value to push. - * @param {promise.Promise=} opt_taskPromise Promise to return from - * the task. - * @return {!promise.Promise} The result. - */ - function schedulePush(value, opt_taskPromise) { - return scheduleAction(value, function() { - messages.push(value); - return opt_taskPromise; - }); - } - - /** - * @param {string} msg Debug message. - * @param {!Function} actionFn The function. - * @return {!promise.Promise} The function result. - */ - function scheduleAction(msg, actionFn) { - return promise.controlFlow().execute(function() { - flowHistory.push(msg); - return actionFn(); - }, msg); - } - - /** - * @param {!Function} condition The condition function. - * @param {number=} opt_timeout The timeout. - * @param {string=} opt_message Optional message. - * @return {!promise.Promise} The wait result. - */ - function scheduleWait(condition, opt_timeout, opt_message) { - var msg = opt_message || ''; - // It's not possible to hook into when the wait itself is scheduled, so - // we record each iteration of the wait loop. - var count = 0; - return promise.controlFlow().wait(function() { - flowHistory.push((count++) + ': ' + msg); - return condition(); - }, opt_timeout, msg); - } - - function asyncRun(fn, opt_self) { - NativePromise.resolve().then(() => fn.call(opt_self)); - } - - function assertFlowHistory(var_args) { - var expected = Array.prototype.slice.call(arguments, 0); - assert.deepEqual(expected, flowHistory); - } - - function assertMessages(var_args) { - var expected = Array.prototype.slice.call(arguments, 0); - assert.deepEqual(expected, messages); - } - - function assertingMessages(var_args) { - var args = Array.prototype.slice.call(arguments, 0); - return () => assertMessages.apply(null, args); - } - - function assertFlowIs(flow) { - assert.equal(flow, promise.controlFlow()); - } - - describe('testScheduling', function() { - it('aSimpleFunction', function() { - schedule('go'); - return waitForIdle().then(function() { - assertFlowHistory('go'); - }); - }); - - it('aSimpleFunctionWithANonPromiseReturnValue', function() { - schedule('go', 123).then(function(value) { - assert.equal(123, value); - }); - return waitForIdle().then(function() { - assertFlowHistory('go'); - }); - }); - - it('aSimpleSequence', function() { - schedule('a'); - schedule('b'); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('invokesCallbacksWhenTaskIsDone', function() { - var d = new promise.Deferred(); - var called = false; - var done = schedule('a', d.promise).then(function(value) { - called = true; - assert.equal(123, value); - }); - return timeout(5).then(function() { - assert.ok(!called); - d.fulfill(123); - return done; - }). - then(function() { - assertFlowHistory('a'); - }); - }); - - it('blocksUntilPromiseReturnedByTaskIsResolved', function() { - var done = promise.defer(); - schedulePush('a', done.promise); - schedulePush('b'); - setTimeout(function() { - done.fulfill(); - messages.push('c'); - }, 25); - return waitForIdle().then(assertingMessages('a', 'c', 'b')); - }); - - it('waitsForReturnedPromisesToResolve', function() { - var d1 = new promise.Deferred(); - var d2 = new promise.Deferred(); - - var callback = sinon.spy(); - schedule('a', d1.promise).then(callback); - - return timeout(5).then(function() { - assert(!callback.called); - d1.fulfill(d2.promise); - return timeout(5); - }).then(function() { - assert(!callback.called); - d2.fulfill('fluffy bunny'); - return waitForIdle(); - }).then(function() { - assert(callback.called); - assert.equal('fluffy bunny', callback.getCall(0).args[0]); - assertFlowHistory('a'); - }); - }); - - it('executesTasksInAFutureTurnAfterTheyAreScheduled', function() { - var count = 0; - function incr() { count++; } - - scheduleAction('', incr); - assert.equal(0, count); - return waitForIdle().then(function() { - assert.equal(1, count); - }); - }); - - it('executesOneTaskPerTurnOfTheEventLoop', function() { - var order = []; - function go() { - order.push(order.length / 2); - asyncRun(function() { - order.push('-'); - }); - } - - scheduleAction('', go); - scheduleAction('', go); - return waitForIdle().then(function() { - assert.deepEqual([0, '-', 1, '-'], order); - }) - }); - - it('firstScheduledTaskIsWithinACallback', function() { - promise.fulfilled().then(function() { - schedule('a'); - schedule('b'); - schedule('c'); - }).then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - return waitForIdle(); - }); - - it('newTasksAddedWhileWaitingOnTaskReturnedPromise1', function() { - scheduleAction('a', function() { - var d = promise.defer(); - setTimeout(function() { - schedule('c'); - d.fulfill(); - }, 10); - return d.promise; - }); - schedule('b'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('newTasksAddedWhileWaitingOnTaskReturnedPromise2', function() { - scheduleAction('a', function() { - var d = promise.defer(); - setTimeout(function() { - schedule('c'); - asyncRun(d.fulfill); - }, 10); - return d.promise; - }); - schedule('b'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'b'); - }); - }); - }); - - describe('testFraming', function() { - it('callbacksRunInANewFrame', function() { - schedule('a').then(function() { - schedule('c'); - }); - schedule('b'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'b'); - }); - }); - - it('lotsOfNesting', function() { - schedule('a').then(function() { - schedule('c').then(function() { - schedule('e').then(function() { - schedule('g'); - }); - schedule('f'); - }); - schedule('d'); - }); - schedule('b'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'e', 'g', 'f', 'd', 'b'); - }); - }); - - it('callbackReturnsPromiseThatDependsOnATask_1', function() { - schedule('a').then(function() { - schedule('b'); - return promise.delayed(5).then(function() { - return schedule('c'); - }); - }); - schedule('d'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd'); - }); - }); - - it('callbackReturnsPromiseThatDependsOnATask_2', function() { - schedule('a').then(function() { - schedule('b'); - return promise.delayed(5). - then(function() { return promise.delayed(5) }). - then(function() { return promise.delayed(5) }). - then(function() { return promise.delayed(5) }). - then(function() { return schedule('c'); }); - }); - schedule('d'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd'); - }); - }); - - it('eachCallbackWaitsForAllScheduledTasksToComplete', function() { - schedule('a'). - then(function() { - schedule('b'); - schedule('c'); - }). - then(function() { - schedule('d'); - }); - schedule('e'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('eachCallbackWaitsForReturnTasksToComplete', function() { - schedule('a'). - then(function() { - schedule('b'); - return schedule('c'); - }). - then(function() { - schedule('d'); - }); - schedule('e'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('callbacksOnAResolvedPromiseInsertIntoTheCurrentFlow', function() { - promise.fulfilled().then(function() { - schedule('b'); - }); - schedule('a'); - - return waitForIdle().then(function() { - assertFlowHistory('b', 'a'); - }); - }); - - it('callbacksInterruptTheFlowWhenPromiseIsResolved', function() { - schedule('a').then(function() { - schedule('c'); - }); - schedule('b'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'b'); - }); - }); - - it('allCallbacksInAFrameAreScheduledWhenPromiseIsResolved', function() { - var a = schedule('a'); - a.then(function() { schedule('b'); }); - schedule('c'); - a.then(function() { schedule('d'); }); - schedule('e'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('tasksScheduledInInActiveFrameDoNotGetPrecedence', function() { - var d = promise.fulfilled(); - schedule('a'); - schedule('b'); - d.then(function() { schedule('c'); }); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('tasksScheduledInAFrameGetPrecedence_1', function() { - var a = schedule('a'); - schedule('b').then(function() { - a.then(function() { - schedule('c'); - schedule('d'); - }); - var e = schedule('e'); - a.then(function() { - schedule('f'); - e.then(function() { - schedule('g'); - }); - schedule('h'); - }); - schedule('i'); - }); - schedule('j'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'); - }); - }); - }); - - describe('testErrorHandling', function() { - it('thrownErrorsArePassedToTaskErrback', function() { - scheduleAction('function that throws', throwStubError). - then(fail, assertIsStubError); - return waitForIdle(); - }); - - it('thrownErrorsPropagateThroughPromiseChain', function() { - scheduleAction('function that throws', throwStubError). - then(fail). - then(fail, assertIsStubError); - return waitForIdle(); - }); - - it('catchesErrorsFromFailedTasksInAFrame', function() { - schedule('a').then(function() { - schedule('b'); - scheduleAction('function that throws', throwStubError); - }). - then(fail, assertIsStubError); - return waitForIdle(); - }); - - it('abortsIfOnlyTaskReturnsAnUnhandledRejection', function() { - scheduleAction('function that returns rejected promise', function() { - return promise.rejected(new StubError); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('abortsIfThereIsAnUnhandledRejection', function() { - promise.rejected(new StubError); - schedule('this should not run'); - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory(/* none */); - }); - }); - - it('abortsSequenceIfATaskFails', function() { - schedule('a'); - schedule('b'); - scheduleAction('c', throwStubError); - schedule('d'); // Should never execute. - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('abortsFromUnhandledFramedTaskFailures_1', function() { - schedule('outer task').then(function() { - scheduleAction('inner task', throwStubError); - }); - schedule('this should not run'); - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('outer task', 'inner task'); - }); - }); - - it('abortsFromUnhandledFramedTaskFailures_2', function() { - schedule('a').then(function() { - schedule('b').then(function() { - scheduleAction('c', throwStubError); - // This should not execute. - schedule('d'); - }); - }); - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('abortsWhenErrorBubblesUpFromFullyResolvingAnObject', function() { - var callback = sinon.spy(); - - scheduleAction('', function() { - var obj = {'foo': promise.rejected(new StubError)}; - return promise.fullyResolved(obj).then(callback); - }); - - return waitForAbort(). - then(assertIsStubError). - then(() => assert(!callback.called)); - }); - - it('abortsWhenErrorBubblesUpFromFullyResolvingAnObject_withCallback', function() { - var callback1 = sinon.spy(); - var callback2 = sinon.spy(); - - scheduleAction('', function() { - var obj = {'foo': promise.rejected(new StubError)}; - return promise.fullyResolved(obj).then(callback1); - }).then(callback2); - - return waitForAbort(). - then(assertIsStubError). - then(() => assert(!callback1.called)). - then(() => assert(!callback2.called)); - }); - - it('canCatchErrorsFromNestedTasks', function() { - var errback = sinon.spy(); - schedule('a'). - then(function() { - return scheduleAction('b', throwStubError); - }). - catch(errback); - return waitForIdle().then(function() { - assert(errback.called); - assertIsStubError(errback.getCall(0).args[0]); - }); - }); - - it('nestedCommandFailuresCanBeCaughtAndSuppressed', function() { - var errback = sinon.spy(); - schedule('a').then(function() { - return schedule('b').then(function() { - return schedule('c').then(function() { - throw new StubError; - }); - }); - }).catch(errback); - schedule('d'); - return waitForIdle(). - then(function() { - assert(errback.called); - assertIsStubError(errback.getCall(0).args[0]); - assertFlowHistory('a', 'b', 'c', 'd'); - }); - }); - - it('aTaskWithAnUnhandledPromiseRejection', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - promise.rejected(new StubError); - }); - schedule('should never run'); - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'sub-tasks'); - }); - }); - - it('aTaskThatReutrnsARejectedPromise', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - return promise.rejected(new StubError); - }); - schedule('should never run'); - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'sub-tasks'); - }); - }); - - it('discardsSubtasksIfTaskThrows', function() { - var pair = callbackPair(null, assertIsStubError); - scheduleAction('a', function() { - schedule('b'); - schedule('c'); - throwStubError(); - }).then(pair.callback, pair.errback); - schedule('d'); - - return waitForIdle(). - then(pair.assertErrback). - then(function() { - assertFlowHistory('a', 'd'); - }); - }); - - it('discardsRemainingSubtasksIfASubtaskFails', function() { - var pair = callbackPair(null, assertIsStubError); - scheduleAction('a', function() { - schedule('b'); - scheduleAction('c', throwStubError); - schedule('d'); - }).then(pair.callback, pair.errback); - schedule('e'); - - return waitForIdle(). - then(pair.assertErrback). - then(function() { - assertFlowHistory('a', 'b', 'c', 'e'); - }); - }); - }); - - describe('testTryModelingFinally', function() { - it('happyPath', function() { - /* Model: - try { - doFoo(); - doBar(); - } finally { - doBaz(); - } - */ - schedulePush('foo'). - then(() => schedulePush('bar')). - finally(() => schedulePush('baz')); - return waitForIdle().then(assertingMessages('foo', 'bar', 'baz')); - }); - - it('firstTryFails', function() { - /* Model: - try { - doFoo(); - doBar(); - } finally { - doBaz(); - } - */ - - scheduleAction('doFoo and throw', function() { - messages.push('foo'); - throw new StubError; - }). - then(function() { schedulePush('bar'); }). - finally(function() { schedulePush('baz'); }); - - return waitForAbort(). - then(assertIsStubError). - then(assertingMessages('foo', 'baz')); - }); - - it('secondTryFails', function() { - /* Model: - try { - doFoo(); - doBar(); - } finally { - doBaz(); - } - */ - - schedulePush('foo'). - then(function() { - return scheduleAction('doBar and throw', function() { - messages.push('bar'); - throw new StubError; - }); - }). - finally(function() { - return schedulePush('baz'); - }); - return waitForAbort(). - then(assertIsStubError). - then(assertingMessages('foo', 'bar', 'baz')); - }); - }); - - describe('testTaskCallbacksInterruptFlow', function() { - it('(base case)', function() { - schedule('a').then(function() { - schedule('b'); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskDependsOnImmediatelyFulfilledPromise', function() { - scheduleAction('a', function() { - return promise.fulfilled(); - }).then(function() { - schedule('b'); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskDependsOnPreviouslyFulfilledPromise', function() { - var aPromise = promise.fulfilled(123); - scheduleAction('a', function() { - return aPromise; - }).then(function(value) { - assert.equal(123, value); - schedule('b'); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskDependsOnAsyncPromise', function() { - scheduleAction('a', function() { - return promise.delayed(25); - }).then(function() { - schedule('b'); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('promiseChainedToTaskInterruptFlow', function() { - schedule('a').then(function() { - return promise.fulfilled(); - }).then(function() { - return promise.fulfilled(); - }).then(function() { - schedule('b'); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('nestedTaskCallbacksInterruptFlowWhenResolved', function() { - schedule('a').then(function() { - schedule('b').then(function() { - schedule('c'); - }); - }); - schedule('d'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd'); - }); - }); - }); - - describe('testDelayedNesting', function() { - - it('1', function() { - var a = schedule('a'); - schedule('b').then(function() { - a.then(function() { schedule('c'); }); - schedule('d'); - }); - schedule('e'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('2', function() { - var a = schedule('a'); - schedule('b').then(function() { - a.then(function() { schedule('c'); }); - schedule('d'); - a.then(function() { schedule('e'); }); - }); - schedule('f'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e', 'f'); - }); - }); - - it('3', function() { - var a = schedule('a'); - schedule('b').then(function() { - a.then(function() { schedule('c'); }); - a.then(function() { schedule('d'); }); - }); - schedule('e'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('4', function() { - var a = schedule('a'); - schedule('b').then(function() { - a.then(function() { schedule('c'); }).then(function() { - schedule('d'); - }); - a.then(function() { schedule('e'); }); - }); - schedule('f'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e', 'f'); - }); - }); - - it('5', function() { - var a = schedule('a'); - schedule('b').then(function() { - var c; - a.then(function() { c = schedule('c'); }).then(function() { - schedule('d'); - a.then(function() { schedule('e'); }); - c.then(function() { schedule('f'); }); - schedule('g'); - }); - a.then(function() { schedule('h'); }); - }); - schedule('i'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'); - }); - }); - }); - - describe('testWaiting', function() { - it('onAConditionThatIsAlwaysTrue', function() { - scheduleWait(function() { return true;}, 0, 'waiting on true'); - return waitForIdle().then(function() { - assertFlowHistory('0: waiting on true'); - }); - }); - - it('aSimpleCountingCondition', function() { - var count = 0; - scheduleWait(function() { - return ++count == 3; - }, 100, 'counting to 3'); - - return waitForIdle().then(function() { - assert.equal(3, count); - }); - }); - - it('aConditionThatReturnsAPromise', function() { - var d = new promise.Deferred(); - var count = 0; - - scheduleWait(function() { - count += 1; - return d.promise; - }, 0, 'waiting for promise'); - - return timeout(50).then(function() { - assert.equal(1, count); - d.fulfill(123); - return waitForIdle(); - }); - }); - - it('aConditionThatReturnsAPromise_2', function() { - var count = 0; - scheduleWait(function() { - return promise.fulfilled(++count == 3); - }, 100, 'waiting for promise'); - - return waitForIdle().then(function() { - assert.equal(3, count); - }); - }); - - it('aConditionThatReturnsATaskResult', function() { - var count = 0; - scheduleWait(function() { - return scheduleAction('increment count', function() { - return ++count == 3; - }); - }, 100, 'counting to 3'); - schedule('post wait'); - - return waitForIdle().then(function() { - assert.equal(3, count); - assertFlowHistory( - '0: counting to 3', 'increment count', - '1: counting to 3', 'increment count', - '2: counting to 3', 'increment count', - 'post wait'); - }); - }); - - it('conditionContainsASubtask', function() { - var count = 0; - scheduleWait(function() { - schedule('sub task'); - return ++count == 3; - }, 100, 'counting to 3'); - schedule('post wait'); - - return waitForIdle().then(function() { - assert.equal(3, count); - assertFlowHistory( - '0: counting to 3', 'sub task', - '1: counting to 3', 'sub task', - '2: counting to 3', 'sub task', - 'post wait'); - }); - }); - - it('cancelsWaitIfScheduledTaskFails', function() { - var pair = callbackPair(null, assertIsStubError); - scheduleWait(function() { - scheduleAction('boom', throwStubError); - schedule('this should not run'); - return true; - }, 100, 'waiting to go boom').then(pair.callback, pair.errback); - schedule('post wait'); - - return waitForIdle(). - then(pair.assertErrback). - then(function() { - assertFlowHistory( - '0: waiting to go boom', 'boom', - 'post wait'); - }); - }); - - it('failsIfConditionThrows', function() { - var callbacks = callbackPair(null, assertIsStubError); - scheduleWait(throwStubError, 0, 'goes boom'). - then(callbacks.callback, callbacks.errback); - schedule('post wait'); - - return waitForIdle(). - then(callbacks.assertErrback). - then(function() { - assertFlowHistory('0: goes boom', 'post wait'); - }); - }); - - it('failsIfConditionReturnsARejectedPromise', function() { - var callbacks = callbackPair(null, assertIsStubError); - scheduleWait(function() { - return promise.rejected(new StubError); - }, 0, 'goes boom').then(callbacks.callback, callbacks.errback); - schedule('post wait'); - - return waitForIdle(). - then(callbacks.assertErrback). - then(function() { - assertFlowHistory('0: goes boom', 'post wait'); - }); - }); - - it('failsIfConditionHasUnhandledRejection', function() { - var callbacks = callbackPair(null, assertIsStubError); - scheduleWait(function() { - promise.controlFlow().execute(throwStubError); - }, 0, 'goes boom').then(callbacks.callback, callbacks.errback); - schedule('post wait'); - - return waitForIdle(). - then(callbacks.assertErrback). - then(function() { - assertFlowHistory('0: goes boom', 'post wait'); - }); - }); - - it('failsIfConditionHasAFailedSubtask', function() { - var callbacks = callbackPair(null, assertIsStubError); - var count = 0; - scheduleWait(function() { - scheduleAction('maybe throw', function() { - if (++count == 2) { - throw new StubError; - } - }); - }, 100, 'waiting').then(callbacks.callback, callbacks.errback); - schedule('post wait'); - - return waitForIdle().then(function() { - assert.equal(2, count); - assertFlowHistory( - '0: waiting', 'maybe throw', - '1: waiting', 'maybe throw', - 'post wait'); - }); - }); - - it('pollingLoopWaitsForAllScheduledTasksInCondition', function() { - var count = 0; - scheduleWait(function() { - scheduleAction('increment count', function() { ++count; }); - return count >= 3; - }, 100, 'counting to 3'); - schedule('post wait'); - - return waitForIdle().then(function() { - assert.equal(4, count); - assertFlowHistory( - '0: counting to 3', 'increment count', - '1: counting to 3', 'increment count', - '2: counting to 3', 'increment count', - '3: counting to 3', 'increment count', - 'post wait'); - }); - }); - - it('waitsForeverOnAZeroTimeout', function() { - var done = false; - setTimeout(function() { - done = true; - }, 150); - var waitResult = scheduleWait(function() { - return done; - }, 0); - - return timeout(75).then(function() { - assert.ok(!done); - return timeout(100); - }).then(function() { - assert.ok(done); - return waitResult; - }); - }); - - it('waitsForeverIfTimeoutOmitted', function() { - var done = false; - setTimeout(function() { - done = true; - }, 150); - var waitResult = scheduleWait(function() { - return done; - }); - - return timeout(75).then(function() { - assert.ok(!done); - return timeout(100); - }).then(function() { - assert.ok(done); - return waitResult; - }); - }); - - it('timesOut_nonZeroTimeout', function() { - var count = 0; - scheduleWait(function() { - count += 1; - var ms = count === 2 ? 65 : 5; - return promise.delayed(ms).then(function() { - return false; - }); - }, 60, 'counting to 3'); - return waitForAbort().then(function(e) { - switch (count) { - case 1: - assertFlowHistory('0: counting to 3'); - break; - case 2: - assertFlowHistory('0: counting to 3', '1: counting to 3'); - break; - default: - fail('unexpected polling count: ' + count); - } - assert.ok(e instanceof TimeoutError, 'Unexpected error: ' + e); - assert.ok( - /^counting to 3\nWait timed out after \d+ms$/.test(e.message)); - }); - }); - - it('shouldFailIfConditionReturnsARejectedPromise', function() { - scheduleWait(function() { - return promise.rejected(new StubError); - }, 100, 'returns rejected promise on first pass'); - return waitForAbort().then(assertIsStubError); - }); - - it('scheduleWithIntermittentWaits', function() { - schedule('a'); - scheduleWait(function() { return true; }, 0, 'wait 1'); - schedule('b'); - scheduleWait(function() { return true; }, 0, 'wait 2'); - schedule('c'); - scheduleWait(function() { return true; }, 0, 'wait 3'); - - return waitForIdle().then(function() { - assertFlowHistory('a', '0: wait 1', 'b', '0: wait 2', 'c', '0: wait 3'); - }); - }); - - it('scheduleWithIntermittentAndNestedWaits', function() { - schedule('a'); - scheduleWait(function() { return true; }, 0, 'wait 1'). - then(function() { - schedule('d'); - scheduleWait(function() { return true; }, 0, 'wait 2'); - schedule('e'); - }); - schedule('b'); - scheduleWait(function() { return true; }, 0, 'wait 3'); - schedule('c'); - scheduleWait(function() { return true; }, 0, 'wait 4'); - - return waitForIdle().then(function() { - assertFlowHistory( - 'a', '0: wait 1', 'd', '0: wait 2', 'e', 'b', '0: wait 3', 'c', - '0: wait 4'); - }); - }); - - it('requiresConditionToBeAPromiseOrFunction', function() { - assert.throws(function() { - flow.wait(1234, 0); - }); - flow.wait(function() { return true;}, 0); - flow.wait(promise.fulfilled(), 0); - return waitForIdle(); - }); - - it('promiseThatDoesNotResolveBeforeTimeout', function() { - var d = promise.defer(); - flow.wait(d.promise, 5).then(fail, function(e) { - assert.ok(e instanceof TimeoutError, 'Unexpected error: ' + e); - assert.ok( - /Timed out waiting for promise to resolve after \d+ms/ - .test(e.message), - 'unexpected error message: ' + e.message); - }); - return waitForIdle(); - }); - - it('unboundedWaitOnPromiseResolution', function() { - var messages = []; - var d = promise.defer(); - var waitResult = flow.wait(d.promise).then(function(value) { - messages.push('b'); - assert.equal(1234, value); - }); - setTimeout(function() { - messages.push('a'); - }, 5); - - timeout(10).then(function() { - assert.deepEqual(['a'], messages); - d.fulfill(1234); - return waitResult; - }).then(function() { - assert.deepEqual(['a', 'b'], messages); - }); - - return waitForIdle(); - }); - }); - - describe('testSubtasks', function() { - it('(base case)', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - schedule('c'); - schedule('d'); - }); - schedule('b'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'sub-tasks', 'c', 'd', 'b'); - }); - }); - - it('nesting', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - schedule('b'); - scheduleAction('sub-sub-tasks', function() { - schedule('c'); - schedule('d'); - }); - schedule('e'); - }); - schedule('f'); - - return waitForIdle().then(function() { - assertFlowHistory( - 'a', 'sub-tasks', 'b', 'sub-sub-tasks', 'c', 'd', 'e', 'f'); - }); - }); - - it('taskReturnsSubTaskResult_1', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - return schedule('c'); - }); - schedule('b'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'sub-tasks', 'c', 'b'); - }); - }); - - it('taskReturnsSubTaskResult_2', function() { - let pair = callbackPair((value) => assert.equal(123, value)); - schedule('a'); - schedule('sub-tasks', promise.fulfilled(123)).then(pair.callback); - schedule('b'); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'sub-tasks','b'); - pair.assertCallback(); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_1', function() { - scheduleAction('a', function() { - return promise.delayed(10).then(function() { - schedule('b'); - }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_2', function() { - scheduleAction('a', function() { - return promise.fulfilled().then(function() { - schedule('b'); - }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_3', function() { - scheduleAction('a', function() { - return promise.delayed(10).then(function() { - return schedule('b'); - }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_4', function() { - scheduleAction('a', function() { - return promise.delayed(5).then(function() { - return promise.delayed(5).then(function() { - return schedule('b'); - }); - }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_5', function() { - scheduleAction('a', function() { - return promise.delayed(5).then(function() { - return promise.delayed(5).then(function() { - return promise.delayed(5).then(function() { - return promise.delayed(5).then(function() { - return schedule('b'); - }); - }); - }); - }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('taskReturnsPromiseThatDependsOnSubtask_6', function() { - scheduleAction('a', function() { - return promise.delayed(5). - then(function() { return promise.delayed(5) }). - then(function() { return promise.delayed(5) }). - then(function() { return promise.delayed(5) }). - then(function() { return schedule('b'); }); - }); - schedule('c'); - return waitForIdle().then(function() { - assertFlowHistory('a', 'b', 'c'); - }); - }); - - it('subTaskFails_1', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - scheduleAction('sub-task that fails', throwStubError); - }); - schedule('should never execute'); - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'sub-tasks', 'sub-task that fails'); - }); - }); - - it('subTaskFails_2', function() { - schedule('a'); - scheduleAction('sub-tasks', function() { - return promise.rejected(new StubError); - }); - schedule('should never execute'); - - return waitForAbort(). - then(assertIsStubError). - then(function() { - assertFlowHistory('a', 'sub-tasks'); - }); - }); - - it('subTaskFails_3', function() { - var callbacks = callbackPair(null, assertIsStubError); - - schedule('a'); - scheduleAction('sub-tasks', function() { - return promise.rejected(new StubError); - }).then(callbacks.callback, callbacks.errback); - schedule('b'); - - return waitForIdle(). - then(function() { - assertFlowHistory('a', 'sub-tasks', 'b'); - callbacks.assertErrback(); - }); - }); - }); - - describe('testEventLoopWaitsOnPendingPromiseRejections', function() { - it('oneRejection', function() { - var d = new promise.Deferred; - scheduleAction('one', function() { - return d.promise; - }); - scheduleAction('two', function() {}); - - return timeout(50).then(function() { - assertFlowHistory('one'); - d.reject(new StubError); - return waitForAbort(); - }). - then(assertIsStubError). - then(function() { - assertFlowHistory('one'); - }); - }); - - it('multipleRejections', function() { - var once = Error('once'); - var twice = Error('twice'); - - scheduleAction('one', function() { - promise.rejected(once); - promise.rejected(twice); - }); - var twoResult = scheduleAction('two', function() {}); - - flow.removeAllListeners( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION); - return new NativePromise(function(fulfill, reject) { - setTimeout(function() { - reject(Error('Should have reported the two errors by now')); - }, 50); - flow.on( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, - fulfill); - }).then(function(e) { - assert.ok(e instanceof promise.MultipleUnhandledRejectionError, - 'Not a MultipleUnhandledRejectionError'); - let errors = Array.from(e.errors); - assert.deepEqual([once, twice], errors); - assertFlowHistory('one'); - }); - }); - }); - - describe('testCancelsPromiseReturnedByCallbackIfFrameFails', function() { - it('promiseCallback', function() { - var chainPair = callbackPair(null, assertIsStubError); - var deferredPair = callbackPair(null, function(e) { - assert.equal('CancellationError: StubError', e.toString(), - 'callback result should be cancelled'); - }); - - var d = new promise.Deferred(); - d.promise.then(deferredPair.callback, deferredPair.errback); - - promise.fulfilled(). - then(function() { - scheduleAction('boom', throwStubError); - schedule('this should not run'); - return d.promise; - }). - then(chainPair.callback, chainPair.errback); - - return waitForIdle().then(function() { - assertFlowHistory('boom'); - chainPair.assertErrback('chain errback not invoked'); - deferredPair.assertErrback('deferred errback not invoked'); - }); - }); - - it('taskCallback', function() { - var chainPair = callbackPair(null, assertIsStubError); - var deferredPair = callbackPair(null, function(e) { - assert.equal('CancellationError: StubError', e.toString(), - 'callback result should be cancelled'); - }); - - var d = new promise.Deferred(); - d.promise.then(deferredPair.callback, deferredPair.errback); - - schedule('a'). - then(function() { - scheduleAction('boom', throwStubError); - schedule('this should not run'); - return d.promise; - }). - then(chainPair.callback, chainPair.errback); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'boom'); - chainPair.assertErrback('chain errback not invoked'); - deferredPair.assertErrback('deferred errback not invoked'); - }); - }); - }); - - it('testMaintainsOrderInCallbacksWhenATaskReturnsAPromise', function() { - schedule('__start__', promise.fulfilled()). - then(function() { - messages.push('a'); - schedulePush('b'); - messages.push('c'); - }). - then(function() { - messages.push('d'); - }); - schedulePush('e'); - - return waitForIdle().then(function() { - assertFlowHistory('__start__', 'b', 'e'); - assertMessages('a', 'c', 'b', 'd', 'e'); - }); - }); - - it('testOwningFlowIsActivatedForExecutingTasks', function() { - var defaultFlow = promise.controlFlow(); - var order = []; - - promise.createFlow(function(flow) { - assertFlowIs(flow); - order.push(0); - - defaultFlow.execute(function() { - assertFlowIs(defaultFlow); - order.push(1); - }); - }); - - return waitForIdle().then(function() { - assertFlowIs(defaultFlow); - assert.deepEqual([0, 1], order); - }); - }); - - it('testCreateFlowReturnsPromisePairedWithCreatedFlow', function() { - return new NativePromise(function(fulfill, reject) { - var newFlow; - promise.createFlow(function(flow) { - newFlow = flow; - assertFlowIs(newFlow); - }).then(function() { - assertFlowIs(newFlow); - waitForIdle(newFlow).then(fulfill, reject); - }); - }); - }); - - it('testDeferredFactoriesCreateForActiveFlow_defaultFlow', function() { - var e = Error(); - var defaultFlow = promise.controlFlow(); - promise.fulfilled().then(function() { - assertFlowIs(defaultFlow); - }); - promise.rejected(e).then(null, function(err) { - assert.equal(e, err); - assertFlowIs(defaultFlow); - }); - promise.defer().promise.then(function() { - assertFlowIs(defaultFlow); - }); - - return waitForIdle(); - }); - - it('testDeferredFactoriesCreateForActiveFlow_newFlow', function() { - var e = Error(); - var newFlow = new promise.ControlFlow; - newFlow.execute(function() { - promise.fulfilled().then(function() { - assertFlowIs(newFlow); - }); - - promise.rejected(e).then(null, function(err) { - assert.equal(e, err); - assertFlowIs(newFlow); - }); - - let d = promise.defer(); - d.promise.then(function() { - assertFlowIs(newFlow); - }); - d.fulfill(); - }).then(function() { - assertFlowIs(newFlow); - }); - - return waitForIdle(newFlow); - }); - - it('testFlowsSynchronizeWithThemselvesNotEachOther', function() { - var defaultFlow = promise.controlFlow(); - schedulePush('a', 'a'); - promise.controlFlow().timeout(500); - schedulePush('b', 'b'); - - promise.createFlow(function(flow2) { - assertFlowIs(flow2); - schedulePush('c', 'c'); - schedulePush('d', 'd'); - }); - - return waitForIdle().then(function() { - assertMessages('a', 'c', 'd', 'b'); - }); - }); - - it('testUnhandledErrorsAreReportedToTheOwningFlow', function() { - var error1 = Error('e1'); - var error2 = Error('e2'); - - var defaultFlow = promise.controlFlow(); - defaultFlow.removeAllListeners('uncaughtException'); - - var flow1Error = defer(); - flow1Error.promise.then(function(value) { - assert.equal(error2, value); - }); - - var flow2Error = defer(); - flow2Error.promise.then(function(value) { - assert.equal(error1, value); - }); - - promise.createFlow(function(flow) { - flow.once('uncaughtException', flow2Error.resolve); - promise.rejected(error1); - - defaultFlow.once('uncaughtException', flow1Error.resolve); - defaultFlow.execute(function() { - promise.rejected(error2); - }); - }); - - return NativePromise.all([flow1Error.promise, flow2Error.promise]); - }); - - it('testCanSynchronizeFlowsByReturningPromiseFromOneToAnother', function() { - var flow1 = new promise.ControlFlow; - var flow1Done = defer(); - flow1.once('idle', flow1Done.resolve); - flow1.once('uncaughtException', flow1Done.reject); - - var flow2 = new promise.ControlFlow; - var flow2Done = defer(); - flow2.once('idle', flow2Done.resolve); - flow2.once('uncaughtException', flow2Done.reject); - - flow1.execute(function() { - schedulePush('a', 'a'); - return promise.delayed(25); - }, 'start flow 1'); - - flow2.execute(function() { - schedulePush('b', 'b'); - schedulePush('c', 'c'); - flow2.execute(function() { - return flow1.execute(function() { - schedulePush('d', 'd'); - }, 'flow 1 task'); - }, 'inject flow1 result into flow2'); - schedulePush('e', 'e'); - }, 'start flow 2'); - - return NativePromise.all([flow1Done.promise, flow2Done.promise]). - then(function() { - assertMessages('a', 'b', 'c', 'd', 'e'); - }); - }); - - it('testFramesWaitToCompleteForPendingRejections', function() { - return new NativePromise(function(fulfill, reject) { - - promise.controlFlow().execute(function() { - promise.rejected(new StubError); - }).then(fulfill, reject); - - }). - then(() => fail('expected to fail'), assertIsStubError); - }); - - it('testSynchronizeErrorsPropagateToOuterFlow', function() { - var outerFlow = new promise.ControlFlow; - var innerFlow = new promise.ControlFlow; - - var block = defer(); - innerFlow.execute(function() { - return block.promise; - }, 'block inner flow'); - - outerFlow.execute(function() { - block.resolve(); - return innerFlow.execute(function() { - promise.rejected(new StubError); - }, 'trigger unhandled rejection error'); - }, 'run test'); - - return NativePromise.all([ - waitForIdle(innerFlow), - waitForAbort(outerFlow).then(assertIsStubError) - ]); - }); - - it('testFailsIfErrbackThrows', function() { - promise.rejected('').then(null, throwStubError); - return waitForAbort().then(assertIsStubError); - }); - - it('testFailsIfCallbackReturnsRejectedPromise', function() { - promise.fulfilled().then(function() { - return promise.rejected(new StubError); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('testAbortsFrameIfTaskFails', function() { - promise.fulfilled().then(function() { - promise.controlFlow().execute(throwStubError); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('testAbortsFramePromisedChainedFromTaskIsNotHandled', function() { - promise.fulfilled().then(function() { - promise.controlFlow().execute(function() {}). - then(throwStubError); - }); - return waitForAbort().then(assertIsStubError); - }); - - it('testTrapsChainedUnhandledRejectionsWithinAFrame', function() { - var pair = callbackPair(null, assertIsStubError); - promise.fulfilled().then(function() { - promise.controlFlow().execute(function() {}). - then(throwStubError); - }).then(pair.callback, pair.errback); - - return waitForIdle().then(pair.assertErrback); - }); - - it('testCancelsRemainingTasksIfFrameThrowsDuringScheduling', function() { - var task1, task2; - var pair = callbackPair(null, assertIsStubError); - var flow = promise.controlFlow(); - flow.execute(function() { - task1 = flow.execute(function() {}); - task2 = flow.execute(function() {}); - throw new StubError; - }).then(pair.callback, pair.errback); - - return waitForIdle(). - then(pair.assertErrback). - then(function() { - pair = callbackPair(); - return task1.then(pair.callback, pair.errback); - }). - then(function() { - pair.assertErrback(); - pair = callbackPair(); - return task2.then(pair.callback, pair.errback); - }). - then(function() { - pair.assertErrback(); - }); - }); - - it('testCancelsRemainingTasksInFrameIfATaskFails', function() { - var task; - var pair = callbackPair(null, assertIsStubError); - var flow = promise.controlFlow(); - flow.execute(function() { - flow.execute(throwStubError); - task = flow.execute(function() {}); - }).then(pair.callback, pair.errback); - - return waitForIdle().then(pair.assertErrback).then(function() { - pair = callbackPair(); - task.then(pair.callback, pair.errback); - }).then(function() { - pair.assertErrback(); - }); - }); - - it('testDoesNotModifyRejectionErrorIfPromiseNotInsideAFlow', function() { - var error = Error('original message'); - var originalStack = error.stack; - var originalStr = error.toString(); - - var pair = callbackPair(null, function(e) { - assert.equal(error, e); - assert.equal('original message', e.message); - assert.equal(originalStack, e.stack); - assert.equal(originalStr, e.toString()); - }); - - promise.rejected(error).then(pair.callback, pair.errback); - return waitForIdle().then(pair.assertErrback); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/444 */ - it('testMaintainsOrderWithPromiseChainsCreatedWithinAForeach_1', function() { - var messages = []; - flow.execute(function() { - return promise.fulfilled(['a', 'b', 'c', 'd']); - }, 'start').then(function(steps) { - steps.forEach(function(step) { - promise.fulfilled(step) - .then(function() { - messages.push(step + '.1'); - }).then(function() { - messages.push(step + '.2'); - }); - }) - }); - return waitForIdle().then(function() { - assert.deepEqual( - ['a.1', 'a.2', 'b.1', 'b.2', 'c.1', 'c.2', 'd.1', 'd.2'], - messages); - }); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/444 */ - it('testMaintainsOrderWithPromiseChainsCreatedWithinAForeach_2', function() { - var messages = []; - flow.execute(function() { - return promise.fulfilled(['a', 'b', 'c', 'd']); - }, 'start').then(function(steps) { - steps.forEach(function(step) { - promise.fulfilled(step) - .then(function() { - messages.push(step + '.1'); - }).then(function() { - flow.execute(function() {}, step + '.2').then(function() { - messages.push(step + '.2'); - }); - }); - }) - }); - return waitForIdle().then(function() { - assert.deepEqual( - ['a.1', 'a.2', 'b.1', 'b.2', 'c.1', 'c.2', 'd.1', 'd.2'], - messages); - }); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/444 */ - it('testMaintainsOrderWithPromiseChainsCreatedWithinAForeach_3', function() { - var messages = []; - flow.execute(function() { - return promise.fulfilled(['a', 'b', 'c', 'd']); - }, 'start').then(function(steps) { - steps.forEach(function(step) { - promise.fulfilled(step) - .then(function(){}) - .then(function() { - messages.push(step + '.1'); - return flow.execute(function() {}, step + '.1'); - }).then(function() { - flow.execute(function() {}, step + '.2').then(function(text) { - messages.push(step + '.2'); - }); - }); - }) - }); - return waitForIdle().then(function() { - assert.deepEqual( - ['a.1', 'a.2', 'b.1', 'b.2', 'c.1', 'c.2', 'd.1', 'd.2'], - messages); - }); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/363 */ - it('testTasksScheduledInASeparateTurnOfTheEventLoopGetASeparateTaskQueue_2', function() { - scheduleAction('a', () => promise.delayed(10)); - schedule('b'); - setTimeout(() => schedule('c'), 0); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'b'); - }); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/363 */ - it('testTasksScheduledInASeparateTurnOfTheEventLoopGetASeparateTaskQueue_2', function() { - scheduleAction('a', () => promise.delayed(10)); - schedule('b'); - schedule('c'); - setTimeout(function() { - schedule('d'); - scheduleAction('e', () => promise.delayed(10)); - schedule('f'); - }, 0); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'd', 'e', 'b', 'c', 'f'); - }); - }); - - /** See https://github.com/SeleniumHQ/selenium/issues/363 */ - it('testCanSynchronizeTasksFromAdjacentTaskQueues', function() { - var task1 = scheduleAction('a', () => promise.delayed(10)); - schedule('b'); - setTimeout(function() { - scheduleAction('c', () => task1); - schedule('d'); - }, 0); - - return waitForIdle().then(function() { - assertFlowHistory('a', 'c', 'd', 'b'); - }); - }); - - describe('testCancellingAScheduledTask', function() { - it('1', function() { - var called = false; - var task1 = scheduleAction('a', () => called = true); - task1.cancel('no soup for you'); - - return waitForIdle().then(function() { - assert.ok(!called); - assertFlowHistory(); - return task1.catch(function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('no soup for you', e.message); - }); - }); - }); - - it('2', function() { - schedule('a'); - var called = false; - var task2 = scheduleAction('b', () => called = true); - schedule('c'); - - task2.cancel('no soup for you'); - - return waitForIdle().then(function() { - assert.ok(!called); - assertFlowHistory('a', 'c'); - return task2.catch(function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('no soup for you', e.message); - }); - }); - }); - - it('3', function() { - var called = false; - var task = scheduleAction('a', () => called = true); - task.cancel(new StubError); - - return waitForIdle().then(function() { - assert.ok(!called); - assertFlowHistory(); - return task.catch(function(e) { - assert.ok(e instanceof promise.CancellationError); - }); - }); - }); - - it('4', function() { - var seen = []; - var task = scheduleAction('a', () => seen.push(1)) - .then(() => seen.push(2)) - .then(() => seen.push(3)) - .then(() => seen.push(4)) - .then(() => seen.push(5)); - task.cancel(new StubError); - - return waitForIdle().then(function() { - assert.deepEqual([], seen); - assertFlowHistory(); - return task.catch(function(e) { - assert.ok(e instanceof promise.CancellationError); - }); - }); - }); - - it('fromWithinAnExecutingTask', function() { - var called = false; - var task; - scheduleAction('a', function() { - task.cancel('no soup for you'); - }); - task = scheduleAction('b', () => called = true); - schedule('c'); - - return waitForIdle().then(function() { - assert.ok(!called); - assertFlowHistory('a', 'c'); - return task.catch(function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('no soup for you', e.message); - }); - }); - }); - }); - - it('testCancellingAPendingTask', function() { - var order = []; - var unresolved = promise.defer(); - - var innerTask; - var outerTask = scheduleAction('a', function() { - order.push(1); - - // Schedule a task that will never finish. - innerTask = scheduleAction('a.1', function() { - return unresolved.promise; - }); - - // Since the outerTask is cancelled below, innerTask should be cancelled - // with a DiscardedTaskError, which means its callbacks are silently - // dropped - so this should never execute. - innerTask.catch(function(e) { - order.push(2); - }); - }); - schedule('b'); - - outerTask.catch(function(e) { - order.push(3); - assert.ok(e instanceof promise.CancellationError); - assert.equal('no soup for you', e.message); - }); - - unresolved.promise.catch(function(e) { - order.push(4); - assert.ok(e instanceof promise.CancellationError); - }); - - return timeout(10).then(function() { - assert.deepEqual([1], order); - - outerTask.cancel('no soup for you'); - return waitForIdle(); - }).then(function() { - assertFlowHistory('a', 'a.1', 'b'); - assert.deepEqual([1, 3, 4], order); - }); - }); - - it('testCancellingAPendingPromiseCallback', function() { - var called = false; - - var root = promise.fulfilled(); - root.then(function() { - cb2.cancel('no soup for you'); - }); - - var cb2 = root.then(fail, fail); // These callbacks should never be called. - cb2.then(fail, function(e) { - called = true; - assert.ok(e instanceof promise.CancellationError); - assert.equal('no soup for you', e.message); - }); - - return waitForIdle().then(function() { - assert.ok(called); - }); - }); - - describe('testResetFlow', function() { - it('1', function() { - var called = 0; - var task = flow.execute(() => called++); - task.finally(() => called++); - - return new Promise(function(fulfill) { - flow.once('reset', fulfill); - flow.reset(); - - }).then(function() { - assert.equal(0, called); - return task; - - }).then(fail, function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('ControlFlow was reset', e.message); - }); - }); - - it('2', function() { - var called = 0; - var task1 = flow.execute(() => called++); - task1.finally(() => called++); - - var task2 = flow.execute(() => called++); - task2.finally(() => called++); - - var task3 = flow.execute(() => called++); - task3.finally(() => called++); - - return new Promise(function(fulfill) { - flow.once('reset', fulfill); - flow.reset(); - - }).then(function() { - assert.equal(0, called); - }); - }); - }); - - describe('testPromiseFulfilledInsideTask', function() { - it('1', function() { - var order = []; - - flow.execute(function() { - var d = promise.defer(); - - d.promise.then(() => order.push('a')); - d.promise.then(() => order.push('b')); - d.promise.then(() => order.push('c')); - d.fulfill(); - - flow.execute(() => order.push('d')); - - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c', 'd', 'fin'], order); - }); - }); - - it('2', function() { - var order = []; - - flow.execute(function() { - flow.execute(() => order.push('a')); - flow.execute(() => order.push('b')); - - var d = promise.defer(); - d.promise.then(() => order.push('c')); - d.promise.then(() => order.push('d')); - d.fulfill(); - - flow.execute(() => order.push('e')); - - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c', 'd', 'e', 'fin'], order); - }); - }); - - it('3', function() { - var order = []; - var d = promise.defer(); - d.promise.then(() => order.push('c')); - d.promise.then(() => order.push('d')); - - flow.execute(function() { - flow.execute(() => order.push('a')); - flow.execute(() => order.push('b')); - - d.promise.then(() => order.push('e')); - d.fulfill(); - - flow.execute(() => order.push('f')); - - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['c', 'd', 'a', 'b', 'e', 'f', 'fin'], order); - }); - }); - - it('4', function() { - var order = []; - var d = promise.defer(); - d.promise.then(() => order.push('a')); - d.promise.then(() => order.push('b')); - - flow.execute(function() { - flow.execute(function() { - order.push('c'); - flow.execute(() => order.push('d')); - d.promise.then(() => order.push('e')); - }); - flow.execute(() => order.push('f')); - - d.promise.then(() => order.push('g')); - d.fulfill(); - - flow.execute(() => order.push('h')); - - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'fin'], order); - }); - }); - }); - - describe('testSettledPromiseCallbacksInsideATask', function() { - it('1', function() { - var order = []; - var p = promise.fulfilled(); - - flow.execute(function() { - flow.execute(() => order.push('a')); - p.then(() => order.push('b')); - flow.execute(() => order.push('c')); - p.then(() => order.push('d')); - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c', 'd', 'fin'], order); - }); - }); - - it('2', function() { - var order = []; - - flow.execute(function() { - flow.execute(() => order.push('a')) - .then( () => order.push('c')); - flow.execute(() => order.push('b')); - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'c', 'b', 'fin'], order); - }); - }); - }); - - it('testTasksDoNotWaitForNewlyCreatedPromises', function() { - var order = []; - - flow.execute(function() { - var d = promise.defer(); - - // This is a normal promise, not a task, so the task for this callback is - // considered volatile. Volatile tasks should be skipped when they reach - // the front of the task queue. - d.promise.then(() => order.push('a')); - - flow.execute(() => order.push('b')); - flow.execute(function() { - flow.execute(() => order.push('c')); - d.promise.then(() => order.push('d')); - d.fulfill(); - }); - flow.execute(() => order.push('e')); - - }).then(() => order.push('fin')); - - return waitForIdle().then(function() { - assert.deepEqual(['b', 'a', 'c', 'd', 'e', 'fin'], order); - }); - }); - - it('testCallbackDependenciesDoNotDeadlock', function() { - var order = []; - var root = promise.defer(); - var dep = promise.fulfilled().then(function() { - order.push('a'); - return root.promise.then(function() { - order.push('b'); - }); - }); - // This callback depends on |dep|, which depends on another callback - // attached to |root| via a chain. - root.promise.then(function() { - order.push('c'); - return dep.then(() => order.push('d')); - }).then(() => order.push('fin')); - - setTimeout(() => root.fulfill(), 20); - - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c', 'd', 'fin'], order); - }); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/promise_generator_test.js b/node_modules/selenium-webdriver/test/lib/promise_generator_test.js deleted file mode 100644 index b3388da78..000000000 --- a/node_modules/selenium-webdriver/test/lib/promise_generator_test.js +++ /dev/null @@ -1,310 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); -const promise = require('../../lib/promise'); -const {enablePromiseManager, promiseManagerSuite} = require('../../lib/test/promise'); - -describe('promise.consume()', function() { - promiseManagerSuite(() => { - it('requires inputs to be generator functions', function() { - assert.throws(function() { - promise.consume(function() {}); - }); - }); - - it('handles a basic generator with no yielded promises', function() { - var values = []; - return promise.consume(function* () { - var i = 0; - while (i < 4) { - i = yield i + 1; - values.push(i); - } - }).then(function() { - assert.deepEqual([1, 2, 3, 4], values); - }); - }); - - it('handles a promise yielding generator', function() { - var values = []; - return promise.consume(function* () { - var i = 0; - while (i < 4) { - // Test that things are actually async here. - setTimeout(function() { - values.push(i * 2); - }, 10); - - yield promise.delayed(10).then(function() { - values.push(i++); - }); - } - }).then(function() { - assert.deepEqual([0, 0, 2, 1, 4, 2, 6, 3], values); - }); - }); - - it('assignments to yielded promises get fulfilled value', function() { - return promise.consume(function* () { - let x = yield Promise.resolve(2); - assert.equal(2, x); - }); - }); - - it('uses final return value as fulfillment value', function() { - return promise.consume(function* () { - yield 1; - yield 2; - return 3; - }).then(function(value) { - assert.equal(3, value); - }); - }); - - it('throws rejected promise errors within the generator', function() { - var values = []; - return promise.consume(function* () { - values.push('a'); - var e = Error('stub error'); - try { - yield Promise.reject(e); - values.push('b'); - } catch (ex) { - assert.equal(e, ex); - values.push('c'); - } - values.push('d'); - }).then(function() { - assert.deepEqual(['a', 'c', 'd'], values); - }); - }); - - it('aborts the generator if there is an unhandled rejection', function() { - var values = []; - var e = Error('stub error'); - return promise.consume(function* () { - values.push(1); - yield promise.rejected(e); - values.push(2); - }).catch(function() { - assert.deepEqual([1], values); - }); - }); - - it('yield waits for promises', function() { - let values = []; - let blocker = promise.delayed(100).then(() => { - assert.deepEqual([1], values); - return 2; - }); - - return promise.consume(function* () { - values.push(1); - values.push(yield blocker, 3); - }).then(function() { - assert.deepEqual([1, 2, 3], values); - }); - }); - - it('accepts custom scopes', function() { - return promise.consume(function* () { - return this.name; - }, {name: 'Bob'}).then(function(value) { - assert.equal('Bob', value); - }); - }); - - it('accepts initial generator arguments', function() { - return promise.consume(function* (a, b) { - assert.equal('red', a); - assert.equal('apples', b); - }, null, 'red', 'apples'); - }); - }); - - enablePromiseManager(() => { - it('is possible to cancel promise generators', function() { - var values = []; - var p = promise.consume(function* () { - var i = 0; - while (i < 3) { - yield promise.delayed(100).then(function() { - values.push(i++); - }); - } - }); - return promise.delayed(75).then(function() { - p.cancel(); - return p.catch(function() { - return promise.delayed(300); - }); - }).then(function() { - assert.deepEqual([0], values); - }); - }); - - it('executes generator within the control flow', function() { - var promises = [ - promise.defer(), - promise.defer() - ]; - var values = []; - - setTimeout(function() { - assert.deepEqual([], values); - promises[0].fulfill(1); - }, 100); - - setTimeout(function() { - assert.deepEqual([1], values); - promises[1].fulfill(2); - }, 200); - - return promise.controlFlow().execute(function* () { - values.push(yield promises[0].promise); - values.push(yield promises[1].promise); - values.push('fin'); - }).then(function() { - assert.deepEqual([1, 2, 'fin'], values); - }); - }); - - it('handles tasks scheduled in generator', function() { - var flow = promise.controlFlow(); - return flow.execute(function* () { - var x = yield flow.execute(function() { - return promise.delayed(10).then(function() { - return 1; - }); - }); - - var y = yield flow.execute(function() { - return 2; - }); - - return x + y; - }).then(function(value) { - assert.equal(3, value); - }); - }); - - it('blocks the control flow while processing generator', function() { - var values = []; - return promise.controlFlow().wait(function* () { - yield values.push(1); - values.push(yield promise.delayed(10).then(function() { - return 2; - })); - yield values.push(3); - return values.length === 6; - }, 250).then(function() { - assert.deepEqual([1, 2, 3, 1, 2, 3], values); - }); - }); - - it('ControlFlow.wait() will timeout on long generator', function() { - var values = []; - return promise.controlFlow().wait(function* () { - var i = 0; - while (i < 3) { - yield promise.delayed(100).then(function() { - values.push(i++); - }); - } - }, 75).catch(function() { - assert.deepEqual( - [0, 1, 2], values, 'Should complete one loop of wait condition'); - }); - }); - - describe('generators in promise callbacks', function() { - it('works with no initial value', function() { - var promises = [ - promise.defer(), - promise.defer() - ]; - var values = []; - - setTimeout(function() { - promises[0].fulfill(1); - }, 50); - - setTimeout(function() { - promises[1].fulfill(2); - }, 100); - - return promise.fulfilled().then(function*() { - values.push(yield promises[0].promise); - values.push(yield promises[1].promise); - values.push('fin'); - }).then(function() { - assert.deepEqual([1, 2, 'fin'], values); - }); - }); - - it('starts the generator with promised value', function() { - var promises = [ - promise.defer(), - promise.defer() - ]; - var values = []; - - setTimeout(function() { - promises[0].fulfill(1); - }, 50); - - setTimeout(function() { - promises[1].fulfill(2); - }, 100); - - return promise.fulfilled(3).then(function*(value) { - var p1 = yield promises[0].promise; - var p2 = yield promises[1].promise; - values.push(value + p1); - values.push(value + p2); - values.push('fin'); - }).then(function() { - assert.deepEqual([4, 5, 'fin'], values); - }); - }); - - it('throws yielded rejections within the generator callback', function() { - var d = promise.defer(); - var e = Error('stub'); - - setTimeout(function() { - d.reject(e); - }, 50); - - return promise.fulfilled().then(function*() { - var threw = false; - try { - yield d.promise; - } catch (ex) { - threw = true; - assert.equal(e, ex); - } - assert.ok(threw); - }); - }); - }); - }); -}); - diff --git a/node_modules/selenium-webdriver/test/lib/promise_test.js b/node_modules/selenium-webdriver/test/lib/promise_test.js deleted file mode 100644 index 8da1cd89e..000000000 --- a/node_modules/selenium-webdriver/test/lib/promise_test.js +++ /dev/null @@ -1,1109 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); - -const testutil = require('./testutil'); -const promise = require('../../lib/promise'); -const {enablePromiseManager, promiseManagerSuite} = require('../../lib/test/promise'); - -// Aliases for readability. -const NativePromise = Promise; -const StubError = testutil.StubError; -const assertIsStubError = testutil.assertIsStubError; -const callbackHelper = testutil.callbackHelper; -const callbackPair = testutil.callbackPair; -const throwStubError = testutil.throwStubError; -const fail = () => assert.fail(); - -// Refer to promise_aplus_test for promise compliance with standard behavior. -describe('promise', function() { - var app, uncaughtExceptions; - - beforeEach(function setUp() { - if (promise.USE_PROMISE_MANAGER) { - promise.LONG_STACK_TRACES = false; - uncaughtExceptions = []; - - app = promise.controlFlow(); - app.on(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, - (e) => uncaughtExceptions.push(e)); - } - }); - - afterEach(function tearDown() { - if (promise.USE_PROMISE_MANAGER) { - app.reset(); - promise.setDefaultFlow(new promise.ControlFlow); - assert.deepEqual([], uncaughtExceptions, - 'Did not expect any uncaught exceptions'); - promise.LONG_STACK_TRACES = false; - } - }); - - const assertIsPromise = (p) => assert.ok(promise.isPromise(p)); - const assertNotPromise = (v) => assert.ok(!promise.isPromise(v)); - - function defer() { - let d = {}; - let promise = new Promise((resolve, reject) => { - Object.assign(d, {resolve, reject}); - }); - d.promise = promise; - return d; - } - - function createRejectedPromise(reason) { - var p = Promise.reject(reason); - p.catch(function() {}); // Silence unhandled rejection handlers. - return p; - } - - enablePromiseManager(() => { - it('testCanDetectPromiseLikeObjects', function() { - assertIsPromise(new promise.Promise(function(fulfill) { - fulfill(); - })); - assertIsPromise(new promise.Deferred().promise); - assertIsPromise(Promise.resolve(123)); - assertIsPromise({then:function() {}}); - - assertNotPromise(new promise.Deferred()); - assertNotPromise(undefined); - assertNotPromise(null); - assertNotPromise(''); - assertNotPromise(true); - assertNotPromise(false); - assertNotPromise(1); - assertNotPromise({}); - assertNotPromise({then:1}); - assertNotPromise({then:true}); - assertNotPromise({then:''}); - }); - - describe('then', function() { - it('returnsOwnPromiseIfNoCallbacksWereGiven', function() { - var deferred = new promise.Deferred(); - assert.equal(deferred.promise, deferred.promise.then()); - assert.equal(deferred.promise, deferred.promise.catch()); - assert.equal(deferred.promise, promise.when(deferred.promise)); - }); - - it('stillConsideredUnHandledIfNoCallbacksWereGivenOnCallsToThen', function() { - promise.rejected(new StubError).then(); - var handler = callbackHelper(assertIsStubError); - - // so tearDown() doesn't throw - app.removeAllListeners(); - app.on(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, handler); - return NativePromise.resolve() - // Macro yield so the uncaught exception has a chance to trigger. - .then(() => new NativePromise(resolve => setTimeout(resolve, 0))) - .then(() => handler.assertCalled()); - }); - }); - - describe('finally', function() { - it('nonFailingCallbackDoesNotSuppressOriginalError', function() { - var done = callbackHelper(assertIsStubError); - return promise.rejected(new StubError). - finally(function() {}). - catch(done). - finally(done.assertCalled); - }); - - it('failingCallbackSuppressesOriginalError', function() { - var done = callbackHelper(assertIsStubError); - return promise.rejected(new Error('original')). - finally(throwStubError). - catch(done). - finally(done.assertCalled); - }); - - it('callbackThrowsAfterFulfilledPromise', function() { - var done = callbackHelper(assertIsStubError); - return promise.fulfilled(). - finally(throwStubError). - catch(done). - finally(done.assertCalled); - }); - - it('callbackReturnsRejectedPromise', function() { - var done = callbackHelper(assertIsStubError); - return promise.fulfilled(). - finally(function() { - return promise.rejected(new StubError); - }). - catch(done). - finally(done.assertCalled); - }); - }); - - describe('cancel', function() { - it('passesTheCancellationReasonToReject', function() { - var d = new promise.Deferred(); - var res = d.promise.then(assert.fail, function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('because i said so', e.message); - }); - d.promise.cancel('because i said so'); - return res; - }); - - describe('can cancel original promise from its child;', function() { - it('child created by then()', function() { - var d = new promise.Deferred(); - var p = d.promise.then(assert.fail, function(e) { - assert.ok(e instanceof promise.CancellationError); - assert.equal('because i said so', e.message); - return 123; - }); - - p.cancel('because i said so'); - return p.then(v => assert.equal(123, v)); - }); - - it('child linked by resolving with parent', function() { - let parent = promise.defer(); - let child = new promise.Promise(resolve => resolve(parent.promise)); - child.cancel('all done'); - - return parent.promise.then( - () => assert.fail('expected a cancellation'), - e => { - assert.ok(e instanceof promise.CancellationError); - assert.equal('all done', e.message); - }); - }); - - it('grand child through thenable chain', function() { - let p = new promise.Promise(function() {/* never resolve*/}); - - let noop = function() {}; - let gc = p.then(noop).then(noop).then(noop); - gc.cancel('stop!'); - - return p.then( - () => assert.fail('expected to be cancelled'), - (e) => { - assert.ok(e instanceof promise.CancellationError); - assert.equal('stop!', e.message); - }); - }); - - it('grand child through thenable chain started at resolve', function() { - function noop() {} - - let parent = promise.defer(); - let child = new promise.Promise(resolve => resolve(parent.promise)); - let grandChild = child.then(noop).then(noop).then(noop); - grandChild.cancel('all done'); - - return parent.promise.then( - () => assert.fail('expected a cancellation'), - e => { - assert.ok(e instanceof promise.CancellationError); - assert.equal('all done', e.message); - }); - }); - - it('"parent" is a CancellableThenable', function() { - function noop() {} - - class FakeThenable { - constructor(p) { - this.promise = p; - } - - cancel(reason) { - this.promise.cancel(reason); - } - - then(cb, eb) { - let result = this.promise.then(cb, eb); - return new FakeThenable(result); - } - } - promise.CancellableThenable.addImplementation(FakeThenable); - - let root = new promise.Promise(noop); - let thenable = new FakeThenable(root); - assert.ok(promise.Thenable.isImplementation(thenable)); - assert.ok(promise.CancellableThenable.isImplementation(thenable)); - - let child = new promise.Promise(resolve => resolve(thenable)); - assert.ok(child instanceof promise.Promise); - child.cancel('stop!'); - - function assertStopped(p) { - return p.then( - () => assert.fail('not stopped!'), - (e) => { - assert.ok(e instanceof promise.CancellationError); - assert.equal('stop!', e.message); - }); - } - - return assertStopped(child).then(() => assertStopped(root)); - }); - }); - - it('canCancelATimeout', function() { - var p = promise.delayed(25) - .then(assert.fail, (e) => e instanceof promise.CancellationError); - setTimeout(() => p.cancel(), 20); - p.cancel(); - return p; - }); - - it('can cancel timeout from grandchild', function() { - }); - - it('cancelIsANoopOnceAPromiseHasBeenFulfilled', function() { - var p = promise.fulfilled(123); - p.cancel(); - return p.then((v) => assert.equal(123, v)); - }); - - it('cancelIsANoopOnceAPromiseHasBeenRejected', function() { - var p = promise.rejected(new StubError); - p.cancel(); - - var pair = callbackPair(null, assertIsStubError); - return p.then(assert.fail, assertIsStubError); - }); - - it('noopCancelTriggeredOnCallbackOfResolvedPromise', function() { - var d = promise.defer(); - var p = d.promise.then(); - - d.fulfill(); - p.cancel(); // This should not throw. - return p; // This should not trigger a failure. - }); - }); - }); - - promiseManagerSuite(() => { - describe('fulfilled', function() { - it('returns input value if it is already a valid promise', function() { - let p = promise.createPromise(function() {}); - let r = promise.fulfilled(p); - assert.strictEqual(p, r); - }); - - it('creates a new promise fulfilled with input', function() { - return promise.fulfilled(1234).then(v => assert.equal(1234, v)); - }); - - it('can convert thenables to valid promise', function() { - let thenable = {then: function(cb) {cb(1234)}}; - let p = promise.fulfilled(thenable); - assert.notStrictEqual(thenable, p); - return p.then(v => assert.equal(1234, v)); - }); - }); - - describe('when', function() { - it('ReturnsAResolvedPromiseIfGivenANonPromiseValue', function() { - var ret = promise.when('abc'); - assertIsPromise(ret); - return ret.then((value) => assert.equal('abc', value)); - }); - - it('PassesRawErrorsToCallbacks', function() { - var error = new Error('boo!'); - return promise.when(error, function(value) { - assert.equal(error, value); - }); - }); - - it('WaitsForValueToBeResolvedBeforeInvokingCallback', function() { - let d = defer(); - let callback; - let result = promise.when(d.promise, callback = callbackHelper(function(value) { - assert.equal('hi', value); - })); - callback.assertNotCalled(); - d.resolve('hi'); - return result.then(callback.assertCalled); - }); - }); - - describe('fullyResolved', function() { - it('primitives', function() { - function runTest(value) { - var callback, errback; - return promise.fullyResolved(value) - .then((resolved) => assert.equal(value, resolved)); - } - return runTest(true) - .then(() => runTest(function() {})) - .then(() => runTest(null)) - .then(() => runTest(123)) - .then(() => runTest('foo bar')) - .then(() => runTest(undefined)); - }); - - it('arrayOfPrimitives', function() { - var fn = function() {}; - var array = [true, fn, null, 123, '', undefined, 1]; - return promise.fullyResolved(array).then(function(resolved) { - assert.equal(array, resolved); - assert.deepEqual([true, fn, null, 123, '', undefined, 1], - resolved); - }); - }); - - it('nestedArrayOfPrimitives', function() { - var fn = function() {}; - var array = [true, [fn, null, 123], '', undefined]; - return promise.fullyResolved(array) - .then(function(resolved) { - assert.equal(array, resolved); - assert.deepEqual([true, [fn, null, 123], '', undefined], resolved); - assert.deepEqual([fn, null, 123], resolved[1]); - }); - }); - - it('arrayWithPromisedPrimitive', function() { - return promise.fullyResolved([Promise.resolve(123)]) - .then(function(resolved) { - assert.deepEqual([123], resolved); - }); - }); - - it('promiseResolvesToPrimitive', function() { - return promise.fullyResolved(Promise.resolve(123)) - .then((resolved) => assert.equal(123, resolved)); - }); - - it('promiseResolvesToArray', function() { - var fn = function() {}; - var array = [true, [fn, null, 123], '', undefined]; - var aPromise = Promise.resolve(array); - - var result = promise.fullyResolved(aPromise); - return result.then(function(resolved) { - assert.equal(array, resolved); - assert.deepEqual([true, [fn, null, 123], '', undefined], - resolved); - assert.deepEqual([fn, null, 123], resolved[1]); - }); - }); - - it('promiseResolvesToArrayWithPromises', function() { - var nestedPromise = Promise.resolve(123); - var aPromise = Promise.resolve([true, nestedPromise]); - return promise.fullyResolved(aPromise) - .then(function(resolved) { - assert.deepEqual([true, 123], resolved); - }); - }); - - it('rejectsIfArrayPromiseRejects', function() { - var nestedPromise = createRejectedPromise(new StubError); - var aPromise = Promise.resolve([true, nestedPromise]); - - var pair = callbackPair(null, assertIsStubError); - return promise.fullyResolved(aPromise) - .then(assert.fail, assertIsStubError); - }); - - it('rejectsOnFirstArrayRejection', function() { - var e1 = new Error('foo'); - var e2 = new Error('bar'); - var aPromise = Promise.resolve([ - createRejectedPromise(e1), - createRejectedPromise(e2) - ]); - - return promise.fullyResolved(aPromise) - .then(assert.fail, function(error) { - assert.strictEqual(e1, error); - }); - }); - - it('rejectsIfNestedArrayPromiseRejects', function() { - var aPromise = Promise.resolve([ - Promise.resolve([ - createRejectedPromise(new StubError) - ]) - ]); - - return promise.fullyResolved(aPromise) - .then(assert.fail, assertIsStubError); - }); - - it('simpleHash', function() { - var hash = {'a': 123}; - return promise.fullyResolved(hash) - .then(function(resolved) { - assert.strictEqual(hash, resolved); - assert.deepEqual(hash, {'a': 123}); - }); - }); - - it('nestedHash', function() { - var nestedHash = {'foo':'bar'}; - var hash = {'a': 123, 'b': nestedHash}; - - return promise.fullyResolved(hash) - .then(function(resolved) { - assert.strictEqual(hash, resolved); - assert.deepEqual({'a': 123, 'b': {'foo': 'bar'}}, resolved); - assert.strictEqual(nestedHash, resolved['b']); - }); - }); - - it('promiseResolvesToSimpleHash', function() { - var hash = {'a': 123}; - var aPromise = Promise.resolve(hash); - - return promise.fullyResolved(aPromise) - .then((resolved) => assert.strictEqual(hash, resolved)); - }); - - it('promiseResolvesToNestedHash', function() { - var nestedHash = {'foo':'bar'}; - var hash = {'a': 123, 'b': nestedHash}; - var aPromise = Promise.resolve(hash); - - return promise.fullyResolved(aPromise) - .then(function(resolved) { - assert.strictEqual(hash, resolved); - assert.strictEqual(nestedHash, resolved['b']); - assert.deepEqual(hash, {'a': 123, 'b': {'foo': 'bar'}}); - }); - }); - - it('promiseResolvesToHashWithPromises', function() { - var aPromise = Promise.resolve({ - 'a': Promise.resolve(123) - }); - - return promise.fullyResolved(aPromise) - .then(function(resolved) { - assert.deepEqual({'a': 123}, resolved); - }); - }); - - it('rejectsIfHashPromiseRejects', function() { - var aPromise = Promise.resolve({ - 'a': createRejectedPromise(new StubError) - }); - - return promise.fullyResolved(aPromise) - .then(assert.fail, assertIsStubError); - }); - - it('rejectsIfNestedHashPromiseRejects', function() { - var aPromise = Promise.resolve({ - 'a': {'b': createRejectedPromise(new StubError)} - }); - - return promise.fullyResolved(aPromise) - .then(assert.fail, assertIsStubError); - }); - - it('instantiatedObject', function() { - function Foo() { - this.bar = 'baz'; - } - var foo = new Foo; - - return promise.fullyResolved(foo).then(function(resolvedFoo) { - assert.equal(foo, resolvedFoo); - assert.ok(resolvedFoo instanceof Foo); - assert.deepEqual(new Foo, resolvedFoo); - }); - }); - - it('withEmptyArray', function() { - return promise.fullyResolved([]).then(function(resolved) { - assert.deepEqual([], resolved); - }); - }); - - it('withEmptyHash', function() { - return promise.fullyResolved({}).then(function(resolved) { - assert.deepEqual({}, resolved); - }); - }); - - it('arrayWithPromisedHash', function() { - var obj = {'foo': 'bar'}; - var array = [Promise.resolve(obj)]; - - return promise.fullyResolved(array).then(function(resolved) { - assert.deepEqual(resolved, [obj]); - }); - }); - }); - - describe('checkedNodeCall', function() { - it('functionThrows', function() { - return promise.checkedNodeCall(throwStubError) - .then(assert.fail, assertIsStubError); - }); - - it('functionReturnsAnError', function() { - return promise.checkedNodeCall(function(callback) { - callback(new StubError); - }).then(assert.fail, assertIsStubError); - }); - - it('functionReturnsSuccess', function() { - var success = 'success!'; - return promise.checkedNodeCall(function(callback) { - callback(null, success); - }).then((value) => assert.equal(success, value)); - }); - - it('functionReturnsAndThrows', function() { - var error = new Error('boom'); - var error2 = new Error('boom again'); - return promise.checkedNodeCall(function(callback) { - callback(error); - throw error2; - }).then(assert.fail, (e) => assert.equal(error, e)); - }); - - it('functionThrowsAndReturns', function() { - var error = new Error('boom'); - var error2 = new Error('boom again'); - return promise.checkedNodeCall(function(callback) { - setTimeout(() => callback(error), 10); - throw error2; - }).then(assert.fail, (e) => assert.equal(error2, e)); - }); - }); - - describe('all', function() { - it('(base case)', function() { - let deferredObjs = [defer(), defer()]; - var a = [ - 0, 1, - deferredObjs[0].promise, - deferredObjs[1].promise, - 4, 5, 6 - ]; - delete a[5]; - - var pair = callbackPair(function(value) { - assert.deepEqual([0, 1, 2, 3, 4, undefined, 6], value); - }); - - var result = promise.all(a).then(pair.callback, pair.errback); - pair.assertNeither(); - - deferredObjs[0].resolve(2); - pair.assertNeither(); - - deferredObjs[1].resolve(3); - return result.then(() => pair.assertCallback()); - }); - - it('empty array', function() { - return promise.all([]).then((a) => assert.deepEqual([], a)); - }); - - it('usesFirstRejection', function() { - let deferredObjs = [defer(), defer()]; - let a = [deferredObjs[0].promise, deferredObjs[1].promise]; - - var result = promise.all(a).then(assert.fail, assertIsStubError); - deferredObjs[1].reject(new StubError); - setTimeout(() => deferredObjs[0].reject(Error('ignored')), 0); - return result; - }); - }); - - describe('map', function() { - it('(base case)', function() { - var a = [1, 2, 3]; - return promise.map(a, function(value, index, a2) { - assert.equal(a, a2); - assert.equal('number', typeof index, 'not a number'); - return value + 1; - }).then(function(value) { - assert.deepEqual([2, 3, 4], value); - }); - }); - - it('omitsDeleted', function() { - var a = [0, 1, 2, 3, 4, 5, 6]; - delete a[1]; - delete a[3]; - delete a[4]; - delete a[6]; - - var expected = [0, 1, 4, 9, 16, 25, 36]; - delete expected[1]; - delete expected[3]; - delete expected[4]; - delete expected[6]; - - return promise.map(a, function(value) { - return value * value; - }).then(function(value) { - assert.deepEqual(expected, value); - }); - }); - - it('emptyArray', function() { - return promise.map([], function(value) { - return value + 1; - }).then(function(value) { - assert.deepEqual([], value); - }); - }); - - it('inputIsPromise', function() { - var input = defer(); - var result = promise.map(input.promise, function(value) { - return value + 1; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual([2, 3, 4], value); - }); - result = result.then(pair.callback, pair.errback); - - setTimeout(function() { - pair.assertNeither(); - input.resolve([1, 2, 3]); - }, 10); - - return result; - }); - - it('waitsForFunctionResultToResolve', function() { - var innerResults = [ - defer(), - defer() - ]; - - var result = promise.map([1, 2], function(value, index) { - return innerResults[index].promise; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual(['a', 'b'], value); - }); - result = result.then(pair.callback, pair.errback); - - return NativePromise.resolve() - .then(function() { - pair.assertNeither(); - innerResults[0].resolve('a'); - }) - .then(function() { - pair.assertNeither(); - innerResults[1].resolve('b'); - return result; - }) - .then(pair.assertCallback); - }); - - it('rejectsPromiseIfFunctionThrows', function() { - return promise.map([1], throwStubError) - .then(assert.fail, assertIsStubError); - }); - - it('rejectsPromiseIfFunctionReturnsRejectedPromise', function() { - return promise.map([1], function() { - return createRejectedPromise(new StubError); - }).then(assert.fail, assertIsStubError); - }); - - it('stopsCallingFunctionIfPreviousIterationFailed', function() { - var count = 0; - return promise.map([1, 2, 3, 4], function() { - count++; - if (count == 3) { - throw new StubError; - } - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.equal(3, count); - }); - }); - - it('rejectsWithFirstRejectedPromise', function() { - var innerResult = [ - Promise.resolve(), - createRejectedPromise(new StubError), - createRejectedPromise(Error('should be ignored')) - ]; - var count = 0; - return promise.map([1, 2, 3, 4], function(value, index) { - count += 1; - return innerResult[index]; - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.equal(2, count); - }); - }); - - it('preservesOrderWhenMapReturnsPromise', function() { - var deferreds = [ - defer(), - defer(), - defer(), - defer() - ]; - var result = promise.map(deferreds, function(value) { - return value.promise; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual([0, 1, 2, 3], value); - }); - result = result.then(pair.callback, pair.errback); - - return Promise.resolve() - .then(function() { - pair.assertNeither(); - for (let i = deferreds.length; i > 0; i -= 1) { - deferreds[i - 1].resolve(i - 1); - } - return result; - }).then(pair.assertCallback); - }); - }); - - describe('filter', function() { - it('basicFiltering', function() { - var a = [0, 1, 2, 3]; - return promise.filter(a, function(val, index, a2) { - assert.equal(a, a2); - assert.equal('number', typeof index, 'not a number'); - return val > 1; - }).then(function(val) { - assert.deepEqual([2, 3], val); - }); - }); - - it('omitsDeleted', function() { - var a = [0, 1, 2, 3, 4, 5, 6]; - delete a[3]; - delete a[4]; - - return promise.filter(a, function(value) { - return value > 1 && value < 6; - }).then(function(val) { - assert.deepEqual([2, 5], val); - }); - }); - - it('preservesInputs', function() { - var a = [0, 1, 2, 3]; - - return promise.filter(a, function(value, i, a2) { - assert.equal(a, a2); - // Even if a function modifies the input array, the original value - // should be inserted into the new array. - a2[i] = a2[i] - 1; - return a2[i] >= 1; - }).then(function(val) { - assert.deepEqual([2, 3], val); - }); - }); - - it('inputIsPromise', function() { - var input = defer(); - var result = promise.filter(input.promise, function(value) { - return value > 1 && value < 3; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual([2], value); - }); - result = result.then(pair.callback, pair.errback); - return NativePromise.resolve() - .then(function() { - pair.assertNeither(); - input.resolve([1, 2, 3]); - return result; - }) - .then(pair.assertCallback); - }); - - it('waitsForFunctionResultToResolve', function() { - var innerResults = [ - defer(), - defer() - ]; - - var result = promise.filter([1, 2], function(value, index) { - return innerResults[index].promise; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual([2], value); - }); - result = result.then(pair.callback, pair.errback); - return NativePromise.resolve() - .then(function() { - pair.assertNeither(); - innerResults[0].resolve(false); - }) - .then(function() { - pair.assertNeither(); - innerResults[1].resolve(true); - return result; - }) - .then(pair.assertCallback); - }); - - it('rejectsPromiseIfFunctionReturnsRejectedPromise', function() { - return promise.filter([1], function() { - return createRejectedPromise(new StubError); - }).then(assert.fail, assertIsStubError); - }); - - it('stopsCallingFunctionIfPreviousIterationFailed', function() { - var count = 0; - return promise.filter([1, 2, 3, 4], function() { - count++; - if (count == 3) { - throw new StubError; - } - }).then(assert.fail, function(e) { - assertIsStubError(e); - assert.equal(3, count); - }); - }); - - it('rejectsWithFirstRejectedPromise', function() { - var innerResult = [ - Promise.resolve(), - createRejectedPromise(new StubError), - createRejectedPromise(Error('should be ignored')) - ]; - - return promise.filter([1, 2, 3, 4], function(value, index) { - assert.ok(index < innerResult.length); - return innerResult[index]; - }).then(assert.fail, assertIsStubError); - }); - - it('preservesOrderWhenFilterReturnsPromise', function() { - var deferreds = [ - defer(), - defer(), - defer(), - defer() - ]; - var result = promise.filter([0, 1, 2, 3], function(value, index) { - return deferreds[index].promise; - }); - - var pair = callbackPair(function(value) { - assert.deepEqual([1, 2], value); - }); - result = result.then(pair.callback, pair.errback); - - return NativePromise.resolve() - .then(function() { - pair.assertNeither(); - for (let i = deferreds.length - 1; i >= 0; i -= 1) { - deferreds[i].resolve(i > 0 && i < 3); - } - return result; - }).then(pair.assertCallback); - }); - }); - }); - - enablePromiseManager(() => { - it('firesUncaughtExceptionEventIfRejectionNeverHandled', function() { - promise.rejected(new StubError); - var handler = callbackHelper(assertIsStubError); - - // so tearDown() doesn't throw - app.removeAllListeners(); - app.on(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, handler); - - return NativePromise.resolve() - // Macro yield so the uncaught exception has a chance to trigger. - .then(() => new NativePromise(resolve => setTimeout(resolve, 0))) - .then(handler.assertCalled); - }); - - it('cannotResolveADeferredWithItself', function() { - var deferred = new promise.Deferred(); - assert.throws(() => deferred.fulfill(deferred)); - assert.throws(() => deferred.reject(deferred)); - }); - - describe('testLongStackTraces', function() { - beforeEach(() => promise.LONG_STACK_TRACES = false); - afterEach(() => promise.LONG_STACK_TRACES = false); - - it('doesNotAppendStackIfFeatureDisabled', function() { - promise.LONG_STACK_TRACES = false; - - var error = Error('hello'); - var originalStack = error.stack; - return promise.rejected(error). - then(fail). - then(fail). - then(fail). - then(fail, function(e) { - assert.equal(error, e); - assert.equal(originalStack, e.stack); - }); - }); - - function getStackMessages(error) { - return error.stack.split(/\n/).filter(function(line) { - return /^From: /.test(line); - }); - } - - it('appendsInitialPromiseCreation_resolverThrows', function() { - promise.LONG_STACK_TRACES = true; - - var error = Error('hello'); - var originalStack = '(placeholder; will be overwritten later)'; - - return new promise.Promise(function() { - try { - throw error; - } catch (e) { - originalStack = e.stack; - throw e; - } - }).then(fail, function(e) { - assert.strictEqual(error, e); - if (typeof originalStack !== 'string') { - return; - } - assert.notEqual(originalStack, e.stack); - assert.equal(e.stack.indexOf(originalStack), 0, - 'should start with original stack'); - assert.deepEqual(['From: ManagedPromise: new'], getStackMessages(e)); - }); - }); - - it('appendsInitialPromiseCreation_rejectCalled', function() { - promise.LONG_STACK_TRACES = true; - - var error = Error('hello'); - var originalStack = error.stack; - - return new promise.Promise(function(_, reject) { - reject(error); - }).then(fail, function(e) { - assert.equal(error, e); - if (typeof originalStack !== 'string') { - return; - } - assert.notEqual(originalStack, e.stack); - assert.equal(e.stack.indexOf(originalStack), 0, - 'should start with original stack'); - assert.deepEqual(['From: ManagedPromise: new'], getStackMessages(e)); - }); - }); - - it('appendsEachStepToRejectionError', function() { - promise.LONG_STACK_TRACES = true; - - var error = Error('hello'); - var originalStack = '(placeholder; will be overwritten later)'; - - return new promise.Promise(function() { - try { - throw error; - } catch (e) { - originalStack = e.stack; - throw e; - } - }). - then(fail). - catch(function(e) { throw e; }). - then(fail). - catch(function(e) { throw e; }). - then(fail, function(e) { - assert.equal(error, e); - if (typeof originalStack !== 'string') { - return; - } - assert.notEqual(originalStack, e.stack); - assert.equal(e.stack.indexOf(originalStack), 0, - 'should start with original stack'); - assert.deepEqual([ - 'From: ManagedPromise: new', - 'From: Promise: then', - 'From: Promise: catch', - 'From: Promise: then', - 'From: Promise: catch', - ], getStackMessages(e)); - }); - }); - - it('errorOccursInCallbackChain', function() { - promise.LONG_STACK_TRACES = true; - - var error = Error('hello'); - var originalStack = '(placeholder; will be overwritten later)'; - - return promise.fulfilled(). - then(function() {}). - then(function() {}). - then(function() { - try { - throw error; - } catch (e) { - originalStack = e.stack; - throw e; - } - }). - catch(function(e) { throw e; }). - then(fail, function(e) { - assert.equal(error, e); - if (typeof originalStack !== 'string') { - return; - } - assert.notEqual(originalStack, e.stack); - assert.equal(e.stack.indexOf(originalStack), 0, - 'should start with original stack'); - assert.deepEqual([ - 'From: Promise: then', - 'From: Promise: catch', - ], getStackMessages(e)); - }); - }); - }); - }); - - it('testAddThenableImplementation', function() { - function tmp() {} - assert.ok(!promise.Thenable.isImplementation(new tmp())); - promise.Thenable.addImplementation(tmp); - assert.ok(promise.Thenable.isImplementation(new tmp())); - - class tmpClass {} - assert.ok(!promise.Thenable.isImplementation(new tmpClass())); - promise.Thenable.addImplementation(tmpClass); - assert.ok(promise.Thenable.isImplementation(new tmpClass())); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/testutil.js b/node_modules/selenium-webdriver/test/lib/testutil.js deleted file mode 100644 index e68ca28ba..000000000 --- a/node_modules/selenium-webdriver/test/lib/testutil.js +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); -const sinon = require('sinon'); - - -class StubError extends Error { - constructor(opt_msg) { - super(opt_msg); - this.name = this.constructor.name; - } -} -exports.StubError = StubError; - -exports.throwStubError = function() { - throw new StubError; -}; - -exports.assertIsStubError = function(value) { - assert.ok(value instanceof StubError, value + ' is not a ' + StubError.name); -}; - -exports.assertIsInstance = function(ctor, value) { - assert.ok(value instanceof ctor, 'Not a ' + ctor.name + ': ' + value); -}; - -function callbackPair(cb, eb) { - if (cb && eb) { - throw new TypeError('can only specify one of callback or errback'); - } - - let callback = cb ? sinon.spy(cb) : sinon.spy(); - let errback = eb ? sinon.spy(eb) : sinon.spy(); - - function assertCallback() { - assert.ok(callback.called, 'callback not called'); - assert.ok(!errback.called, 'errback called'); - if (callback.threw()) { - throw callback.exceptions[0]; - } - } - - function assertErrback() { - assert.ok(!callback.called, 'callback called'); - assert.ok(errback.called, 'errback not called'); - if (errback.threw()) { - throw errback.exceptions[0]; - } - } - - function assertNeither() { - assert.ok(!callback.called, 'callback called'); - assert.ok(!errback.called, 'errback called'); - } - - return { - callback, - errback, - assertCallback, - assertErrback, - assertNeither - }; -} -exports.callbackPair = callbackPair; - - -exports.callbackHelper = function(cb) { - let pair = callbackPair(cb); - let wrapped = pair.callback.bind(null); - wrapped.assertCalled = () => pair.assertCallback(); - wrapped.assertNotCalled = () => pair.assertNeither(); - return wrapped; -}; diff --git a/node_modules/selenium-webdriver/test/lib/until_test.js b/node_modules/selenium-webdriver/test/lib/until_test.js deleted file mode 100644 index 3226a467a..000000000 --- a/node_modules/selenium-webdriver/test/lib/until_test.js +++ /dev/null @@ -1,478 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const assert = require('assert'); - -const By = require('../../lib/by').By; -const CommandName = require('../../lib/command').Name; -const error = require('../../lib/error'); -const promise = require('../../lib/promise'); -const until = require('../../lib/until'); -const webdriver = require('../../lib/webdriver'), - WebElement = webdriver.WebElement; - -describe('until', function() { - let driver, executor; - - class TestExecutor { - constructor() { - this.handlers_ = {}; - } - - on(cmd, handler) { - this.handlers_[cmd] = handler; - return this; - } - - execute(cmd) { - let self = this; - return Promise.resolve().then(function() { - if (!self.handlers_[cmd.getName()]) { - throw new error.UnknownCommandError(cmd.getName()); - } - return self.handlers_[cmd.getName()](cmd); - }); - } - } - - function fail(opt_msg) { - throw new assert.AssertionError({message: opt_msg}); - } - - beforeEach(function setUp() { - executor = new TestExecutor(); - driver = new webdriver.WebDriver('session-id', executor); - }); - - describe('ableToSwitchToFrame', function() { - it('failsFastForNonSwitchErrors', function() { - let e = Error('boom'); - executor.on(CommandName.SWITCH_TO_FRAME, function() { - throw e; - }); - return driver.wait(until.ableToSwitchToFrame(0), 100) - .then(fail, (e2) => assert.strictEqual(e2, e)); - }); - - const ELEMENT_ID = 'some-element-id'; - const ELEMENT_INDEX = 1234; - - function onSwitchFrame(expectedId) { - if (typeof expectedId === 'string') { - expectedId = WebElement.buildId(expectedId); - } else { - assert.equal(typeof expectedId, 'number', 'must be string or number'); - } - return cmd => { - assert.deepEqual( - cmd.getParameter('id'), expectedId, 'frame ID not specified'); - return true; - }; - } - - it('byIndex', function() { - executor.on(CommandName.SWITCH_TO_FRAME, onSwitchFrame(ELEMENT_INDEX)); - return driver.wait(until.ableToSwitchToFrame(ELEMENT_INDEX), 100); - }); - - it('byWebElement', function() { - executor.on(CommandName.SWITCH_TO_FRAME, onSwitchFrame(ELEMENT_ID)); - - var el = new webdriver.WebElement(driver, ELEMENT_ID); - return driver.wait(until.ableToSwitchToFrame(el), 100); - }); - - it('byWebElementPromise', function() { - executor.on(CommandName.SWITCH_TO_FRAME, onSwitchFrame(ELEMENT_ID)); - var el = new webdriver.WebElementPromise(driver, - Promise.resolve(new webdriver.WebElement(driver, ELEMENT_ID))); - return driver.wait(until.ableToSwitchToFrame(el), 100); - }); - - it('byLocator', function() { - executor.on(CommandName.FIND_ELEMENTS, () => [WebElement.buildId(ELEMENT_ID)]); - executor.on(CommandName.SWITCH_TO_FRAME, onSwitchFrame(ELEMENT_ID)); - return driver.wait(until.ableToSwitchToFrame(By.id('foo')), 100); - }); - - it('byLocator_elementNotInitiallyFound', function() { - let foundResponses = [[], [], [WebElement.buildId(ELEMENT_ID)]]; - executor.on(CommandName.FIND_ELEMENTS, () => foundResponses.shift()); - executor.on(CommandName.SWITCH_TO_FRAME, onSwitchFrame(ELEMENT_ID)); - - return driver.wait(until.ableToSwitchToFrame(By.id('foo')), 2000) - .then(() => assert.deepEqual(foundResponses, [])); - }); - - it('timesOutIfNeverAbletoSwitchFrames', function() { - var count = 0; - executor.on(CommandName.SWITCH_TO_FRAME, function() { - count += 1; - throw new error.NoSuchFrameError; - }); - - return driver.wait(until.ableToSwitchToFrame(0), 100) - .then(fail, function(e) { - assert.ok(count > 0); - assert.ok( - e.message.startsWith('Waiting to be able to switch to frame'), - 'Wrong message: ' + e.message); - }); - }); - }); - - describe('alertIsPresent', function() { - it('failsFastForNonAlertSwitchErrors', function() { - return driver.wait(until.alertIsPresent(), 100).then(fail, function(e) { - assert.ok(e instanceof error.UnknownCommandError); - assert.equal(e.message, CommandName.GET_ALERT_TEXT); - }); - }); - - it('waitsForAlert', function() { - var count = 0; - executor.on(CommandName.GET_ALERT_TEXT, function() { - if (count++ < 3) { - throw new error.NoSuchAlertError; - } else { - return true; - } - }).on(CommandName.DISMISS_ALERT, () => true); - - return driver.wait(until.alertIsPresent(), 1000).then(function(alert) { - assert.equal(count, 4); - return alert.dismiss(); - }); - }); - - // TODO: Remove once GeckoDriver doesn't throw this unwanted error. - // See https://github.com/SeleniumHQ/selenium/pull/2137 - describe('workaround for GeckoDriver', function() { - it('doesNotFailWhenCannotConvertNullToObject', function() { - var count = 0; - executor.on(CommandName.GET_ALERT_TEXT, function() { - if (count++ < 3) { - throw new error.WebDriverError(`can't convert null to object`); - } else { - return true; - } - }).on(CommandName.DISMISS_ALERT, () => true); - - return driver.wait(until.alertIsPresent(), 1000).then(function(alert) { - assert.equal(count, 4); - return alert.dismiss(); - }); - }); - - it('keepsRaisingRegularWebdriverError', function() { - var webDriverError = new error.WebDriverError; - - executor.on(CommandName.GET_ALERT_TEXT, function() { - throw webDriverError; - }); - - return driver.wait(until.alertIsPresent(), 1000).then(function() { - throw new Error('driver did not fail against WebDriverError'); - }, function(error) { - assert.equal(error, webDriverError); - }); - }) - }); - }); - - it('testUntilTitleIs', function() { - var titles = ['foo', 'bar', 'baz']; - executor.on(CommandName.GET_TITLE, () => titles.shift()); - - return driver.wait(until.titleIs('bar'), 3000).then(function() { - assert.deepStrictEqual(titles, ['baz']); - }); - }); - - it('testUntilTitleContains', function() { - var titles = ['foo', 'froogle', 'google']; - executor.on(CommandName.GET_TITLE, () => titles.shift()); - - return driver.wait(until.titleContains('oogle'), 3000).then(function() { - assert.deepStrictEqual(titles, ['google']); - }); - }); - - it('testUntilTitleMatches', function() { - var titles = ['foo', 'froogle', 'aaaabc', 'aabbbc', 'google']; - executor.on(CommandName.GET_TITLE, () => titles.shift()); - - return driver.wait(until.titleMatches(/^a{2,3}b+c$/), 3000) - .then(function() { - assert.deepStrictEqual(titles, ['google']); - }); - }); - - it('testUntilUrlIs', function() { - var urls = ['http://www.foo.com', 'https://boo.com', 'http://docs.yes.com']; - executor.on(CommandName.GET_CURRENT_URL, () => urls.shift()); - - return driver.wait(until.urlIs('https://boo.com'), 3000).then(function() { - assert.deepStrictEqual(urls, ['http://docs.yes.com']); - }); - }); - - it('testUntilUrlContains', function() { - var urls = - ['http://foo.com', 'https://groups.froogle.com', 'http://google.com']; - executor.on(CommandName.GET_CURRENT_URL, () => urls.shift()); - - return driver.wait(until.urlContains('oogle.com'), 3000).then(function() { - assert.deepStrictEqual(urls, ['http://google.com']); - }); - }); - - it('testUntilUrlMatches', function() { - var urls = ['foo', 'froogle', 'aaaabc', 'aabbbc', 'google']; - executor.on(CommandName.GET_CURRENT_URL, () => urls.shift()); - - return driver.wait(until.urlMatches(/^a{2,3}b+c$/), 3000) - .then(function() { - assert.deepStrictEqual(urls, ['google']); - }); - }); - - it('testUntilElementLocated', function() { - var responses = [ - [], - [WebElement.buildId('abc123'), WebElement.buildId('foo')], - ['end'] - ]; - executor.on(CommandName.FIND_ELEMENTS, () => responses.shift()); - - let element = driver.wait(until.elementLocated(By.id('quux')), 2000); - assert.ok(element instanceof webdriver.WebElementPromise); - return element.getId().then(function(id) { - assert.deepStrictEqual(responses, [['end']]); - assert.equal(id, 'abc123'); - }); - }); - - describe('untilElementLocated, elementNeverFound', function() { - function runNoElementFoundTest(locator, locatorStr) { - executor.on(CommandName.FIND_ELEMENTS, () => []); - - function expectedFailure() { - fail('expected condition to timeout'); - } - - return driver.wait(until.elementLocated(locator), 100) - .then(expectedFailure, function(error) { - var expected = 'Waiting for element to be located ' + locatorStr; - var lines = error.message.split(/\n/, 2); - assert.equal(lines[0], expected); - - let regex = /^Wait timed out after \d+ms$/; - assert.ok(regex.test(lines[1]), - `Lines <${lines[1]}> does not match ${regex}`); - }); - } - - it('byLocator', function() { - return runNoElementFoundTest( - By.id('quux'), 'By(css selector, *[id="quux"])'); - }); - - it('byHash', function() { - return runNoElementFoundTest( - {id: 'quux'}, 'By(css selector, *[id="quux"])'); - }); - - it('byFunction', function() { - return runNoElementFoundTest(function() {}, 'by function()'); - }); - }); - - it('testUntilElementsLocated', function() { - var responses = [ - [], - [WebElement.buildId('abc123'), WebElement.buildId('foo')], - ['end'] - ]; - executor.on(CommandName.FIND_ELEMENTS, () => responses.shift()); - - return driver.wait(until.elementsLocated(By.id('quux')), 2000) - .then(function(els) { - return Promise.all(els.map(e => e.getId())); - }).then(function(ids) { - assert.deepStrictEqual(responses, [['end']]); - assert.equal(ids.length, 2); - assert.equal(ids[0], 'abc123'); - assert.equal(ids[1], 'foo'); - }); - }); - - describe('untilElementsLocated, noElementsFound', function() { - function runNoElementsFoundTest(locator, locatorStr) { - executor.on(CommandName.FIND_ELEMENTS, () => []); - - function expectedFailure() { - fail('expected condition to timeout'); - } - - return driver.wait(until.elementsLocated(locator), 100) - .then(expectedFailure, function(error) { - var expected = - 'Waiting for at least one element to be located ' + locatorStr; - var lines = error.message.split(/\n/, 2); - assert.equal(lines[0], expected); - - let regex = /^Wait timed out after \d+ms$/; - assert.ok(regex.test(lines[1]), - `Lines <${lines[1]}> does not match ${regex}`); - }); - } - - it('byLocator', function() { - return runNoElementsFoundTest( - By.id('quux'), 'By(css selector, *[id="quux"])'); - }); - - it('byHash', function() { - return runNoElementsFoundTest( - {id: 'quux'}, 'By(css selector, *[id="quux"])'); - }); - - it('byFunction', function() { - return runNoElementsFoundTest(function() {}, 'by function()'); - }); - }); - - it('testUntilStalenessOf', function() { - let count = 0; - executor.on(CommandName.GET_ELEMENT_TAG_NAME, function() { - while (count < 3) { - count += 1; - return 'body'; - } - throw new error.StaleElementReferenceError('now stale'); - }); - - var el = new webdriver.WebElement(driver, {ELEMENT: 'foo'}); - return driver.wait(until.stalenessOf(el), 2000) - .then(() => assert.equal(count, 3)); - }); - - describe('element state conditions', function() { - function runElementStateTest(predicate, command, responses, var_args) { - let original = new webdriver.WebElement(driver, 'foo'); - let predicateArgs = [original]; - if (arguments.length > 3) { - predicateArgs = predicateArgs.concat(arguments[1]); - command = arguments[2]; - responses = arguments[3]; - } - - assert.ok(responses.length > 1); - - responses = responses.concat(['end']); - executor.on(command, () => responses.shift()); - - let result = driver.wait(predicate.apply(null, predicateArgs), 2000); - assert.ok(result instanceof webdriver.WebElementPromise); - return result.then(function(value) { - assert.ok(value instanceof webdriver.WebElement); - assert.ok(!(value instanceof webdriver.WebElementPromise)); - return value.getId(); - }).then(function(id) { - assert.equal('foo', id); - assert.deepStrictEqual(responses, ['end']); - }); - } - - it('elementIsVisible', function() { - return runElementStateTest( - until.elementIsVisible, - CommandName.IS_ELEMENT_DISPLAYED, [false, false, true]); - }); - - it('elementIsNotVisible', function() { - return runElementStateTest( - until.elementIsNotVisible, - CommandName.IS_ELEMENT_DISPLAYED, [true, true, false]); - }); - - it('elementIsEnabled', function() { - return runElementStateTest( - until.elementIsEnabled, - CommandName.IS_ELEMENT_ENABLED, [false, false, true]); - }); - - it('elementIsDisabled', function() { - return runElementStateTest( - until.elementIsDisabled, - CommandName.IS_ELEMENT_ENABLED, [true, true, false]); - }); - - it('elementIsSelected', function() { - return runElementStateTest( - until.elementIsSelected, - CommandName.IS_ELEMENT_SELECTED, [false, false, true]); - }); - - it('elementIsNotSelected', function() { - return runElementStateTest( - until.elementIsNotSelected, - CommandName.IS_ELEMENT_SELECTED, [true, true, false]); - }); - - it('elementTextIs', function() { - return runElementStateTest( - until.elementTextIs, 'foobar', - CommandName.GET_ELEMENT_TEXT, - ['foo', 'fooba', 'foobar']); - }); - - it('elementTextContains', function() { - return runElementStateTest( - until.elementTextContains, 'bar', - CommandName.GET_ELEMENT_TEXT, - ['foo', 'foobaz', 'foobarbaz']); - }); - - it('elementTextMatches', function() { - return runElementStateTest( - until.elementTextMatches, /fo+bar{3}/, - CommandName.GET_ELEMENT_TEXT, - ['foo', 'foobar', 'fooobarrr']); - }); - }); - - describe('WebElementCondition', function() { - it('fails if wait completes with a non-WebElement value', function() { - let result = driver.wait( - new webdriver.WebElementCondition('testing', () => 123), 1000); - - return result.then( - () => assert.fail('expected to fail'), - function(e) { - assert.ok(e instanceof TypeError); - assert.equal( - 'WebElementCondition did not resolve to a WebElement: ' - + '[object Number]', - e.message); - }); - }); - }); -}); diff --git a/node_modules/selenium-webdriver/test/lib/webdriver_test.js b/node_modules/selenium-webdriver/test/lib/webdriver_test.js deleted file mode 100644 index 65fa5193a..000000000 --- a/node_modules/selenium-webdriver/test/lib/webdriver_test.js +++ /dev/null @@ -1,2309 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -'use strict'; - -const testutil = require('./testutil'); - -const By = require('../../lib/by').By; -const Capabilities = require('../../lib/capabilities').Capabilities; -const Executor = require('../../lib/command').Executor; -const CName = require('../../lib/command').Name; -const error = require('../../lib/error'); -const Button = require('../../lib/input').Button; -const Key = require('../../lib/input').Key; -const logging = require('../../lib/logging'); -const Session = require('../../lib/session').Session; -const promise = require('../../lib/promise'); -const {enablePromiseManager, promiseManagerSuite} = require('../../lib/test/promise'); -const until = require('../../lib/until'); -const Alert = require('../../lib/webdriver').Alert; -const AlertPromise = require('../../lib/webdriver').AlertPromise; -const UnhandledAlertError = require('../../lib/webdriver').UnhandledAlertError; -const WebDriver = require('../../lib/webdriver').WebDriver; -const WebElement = require('../../lib/webdriver').WebElement; -const WebElementPromise = require('../../lib/webdriver').WebElementPromise; - -const assert = require('assert'); -const sinon = require('sinon'); - -const SESSION_ID = 'test_session_id'; - -// Aliases for readability. -const NativePromise = Promise; -const StubError = testutil.StubError; -const assertIsInstance = testutil.assertIsInstance; -const assertIsStubError = testutil.assertIsStubError; -const throwStubError = testutil.throwStubError; -const fail = (msg) => assert.fail(msg); - -describe('WebDriver', function() { - const LOG = logging.getLogger('webdriver.test'); - - // before(function() { - // logging.getLogger('webdriver').setLevel(logging.Level.ALL); - // logging.installConsoleHandler(); - // }); - - // after(function() { - // logging.getLogger('webdriver').setLevel(null); - // logging.removeConsoleHandler(); - // }); - - var driver; - var flow; - var uncaughtExceptions; - - beforeEach(function setUp() { - flow = promise.controlFlow(); - uncaughtExceptions = []; - flow.on('uncaughtException', onUncaughtException); - }); - - afterEach(function tearDown() { - if (!promise.USE_PROMISE_MANAGER) { - return; - } - return waitForIdle(flow).then(function() { - assert.deepEqual([], uncaughtExceptions); - flow.reset(); - }); - }); - - function onUncaughtException(e) { - uncaughtExceptions.push(e); - } - - function defer() { - let d = {}; - let promise = new Promise((resolve, reject) => { - Object.assign(d, {resolve, reject}); - }); - d.promise = promise; - return d; - } - - function waitForIdle(opt_flow) { - if (!promise.USE_PROMISE_MANAGER) { - return Promise.resolve(); - } - var theFlow = opt_flow || flow; - return new Promise(function(fulfill, reject) { - if (theFlow.isIdle()) { - fulfill(); - return; - } - theFlow.once('idle', fulfill); - theFlow.once('uncaughtException', reject); - }); - } - - function waitForAbort(opt_flow, opt_n) { - var n = opt_n || 1; - var theFlow = opt_flow || flow; - theFlow.removeAllListeners( - promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION); - return new Promise(function(fulfill, reject) { - theFlow.once('idle', function() { - reject(Error('expected flow to report an unhandled error')); - }); - - var errors = []; - theFlow.on('uncaughtException', onError); - function onError(e) { - errors.push(e); - if (errors.length === n) { - theFlow.removeListener('uncaughtException', onError); - fulfill(n === 1 ? errors[0] : errors); - } - } - }); - } - - function expectedError(ctor, message) { - return function(e) { - assertIsInstance(ctor, e); - assert.equal(message, e.message); - }; - } - - class Expectation { - constructor(executor, name, opt_parameters) { - this.executor_ = executor; - this.name_ = name; - this.times_ = 1; - this.sessionId_ = SESSION_ID; - this.check_ = null; - this.toDo_ = null; - this.withParameters(opt_parameters || {}); - } - - anyTimes() { - this.times_ = Infinity; - return this; - } - - times(n) { - this.times_ = n; - return this; - } - - withParameters(parameters) { - this.parameters_ = parameters; - if (this.name_ !== CName.NEW_SESSION) { - this.parameters_['sessionId'] = this.sessionId_; - } - return this; - } - - andReturn(code, opt_value) { - this.toDo_ = function(command) { - LOG.info('executing ' + command.getName() + '; returning ' + code); - return Promise.resolve(opt_value !== void(0) ? opt_value : null); - }; - return this; - } - - andReturnSuccess(opt_value) { - this.toDo_ = function(command) { - LOG.info('executing ' + command.getName() + '; returning success'); - return Promise.resolve(opt_value !== void(0) ? opt_value : null); - }; - return this; - } - - andReturnError(error) { - if (typeof error === 'number') { - throw Error('need error type'); - } - this.toDo_ = function(command) { - LOG.info('executing ' + command.getName() + '; returning failure'); - return Promise.reject(error); - }; - return this; - } - - expect(name, opt_parameters) { - this.end(); - return this.executor_.expect(name, opt_parameters); - } - - end() { - if (!this.toDo_) { - this.andReturnSuccess(null); - } - return this.executor_; - } - - execute(command) { - assert.deepEqual(this.parameters_, command.getParameters()); - return this.toDo_(command); - } - } - - class FakeExecutor { - constructor() { - this.commands_ = new Map; - } - - execute(command) { - let expectations = this.commands_.get(command.getName()); - if (!expectations || !expectations.length) { - assert.fail('unexpected command: ' + command.getName()); - return; - } - - let next = expectations[0]; - let result = next.execute(command); - if (next.times_ != Infinity) { - next.times_ -= 1; - if (!next.times_) { - expectations.shift(); - } - } - return result; - } - - expect(commandName, opt_parameters) { - if (!this.commands_.has(commandName)) { - this.commands_.set(commandName, []); - } - let e = new Expectation(this, commandName, opt_parameters); - this.commands_.get(commandName).push(e); - return e; - } - - createDriver(opt_session) { - let session = opt_session || new Session(SESSION_ID, {}); - return new WebDriver(session, this); - } - } - - - ///////////////////////////////////////////////////////////////////////////// - // - // Tests - // - ///////////////////////////////////////////////////////////////////////////// - - - describe('testAttachToSession', function() { - it('sessionIsAvailable', function() { - let aSession = new Session(SESSION_ID, {'browserName': 'firefox'}); - let executor = new FakeExecutor(). - expect(CName.DESCRIBE_SESSION). - withParameters({'sessionId': SESSION_ID}). - andReturnSuccess(aSession). - end(); - - let driver = WebDriver.attachToSession(executor, SESSION_ID); - return driver.getSession().then(v => assert.strictEqual(v, aSession)); - }); - - it('failsToGetSessionInfo', function() { - let e = new Error('boom'); - let executor = new FakeExecutor(). - expect(CName.DESCRIBE_SESSION). - withParameters({'sessionId': SESSION_ID}). - andReturnError(e). - end(); - - let driver = WebDriver.attachToSession(executor, SESSION_ID); - return driver.getSession() - .then(() => assert.fail('should have failed!'), - (actual) => assert.strictEqual(actual, e)); - }); - - it('remote end does not recognize DESCRIBE_SESSION command', function() { - let e = new error.UnknownCommandError; - let executor = new FakeExecutor(). - expect(CName.DESCRIBE_SESSION). - withParameters({'sessionId': SESSION_ID}). - andReturnError(e). - end(); - - let driver = WebDriver.attachToSession(executor, SESSION_ID); - return driver.getSession().then(session => { - assert.ok(session instanceof Session); - assert.strictEqual(session.getId(), SESSION_ID); - assert.equal(session.getCapabilities().size, 0); - }); - }); - - it('usesActiveFlowByDefault', function() { - let executor = new FakeExecutor(). - expect(CName.DESCRIBE_SESSION). - withParameters({'sessionId': SESSION_ID}). - andReturnSuccess({}). - end(); - - var driver = WebDriver.attachToSession(executor, SESSION_ID); - assert.equal(driver.controlFlow(), promise.controlFlow()); - - return waitForIdle(driver.controlFlow()); - }); - - enablePromiseManager(() => { - it('canAttachInCustomFlow', function() { - let executor = new FakeExecutor(). - expect(CName.DESCRIBE_SESSION). - withParameters({'sessionId': SESSION_ID}). - andReturnSuccess({}). - end(); - - var otherFlow = new promise.ControlFlow(); - var driver = WebDriver.attachToSession(executor, SESSION_ID, otherFlow); - assert.equal(otherFlow, driver.controlFlow()); - assert.notEqual(otherFlow, promise.controlFlow()); - - return waitForIdle(otherFlow); - }); - }); - }); - - describe('testCreateSession', function() { - it('happyPathWithCapabilitiesHashObject', function() { - let aSession = new Session(SESSION_ID, {'browserName': 'firefox'}); - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({ - 'desiredCapabilities': {'browserName': 'firefox'} - }). - andReturnSuccess(aSession). - end(); - - var driver = WebDriver.createSession(executor, { - 'browserName': 'firefox' - }); - return driver.getSession().then(v => assert.strictEqual(v, aSession)); - }); - - it('happyPathWithCapabilitiesInstance', function() { - let aSession = new Session(SESSION_ID, {'browserName': 'firefox'}); - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({'desiredCapabilities': {'browserName': 'firefox'}}). - andReturnSuccess(aSession). - end(); - - var driver = WebDriver.createSession(executor, Capabilities.firefox()); - return driver.getSession().then(v => assert.strictEqual(v, aSession)); - }); - - it('handles desired and required capabilities', function() { - let aSession = new Session(SESSION_ID, {'browserName': 'firefox'}); - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({ - 'desiredCapabilities': {'foo': 'bar'}, - 'requiredCapabilities': {'bim': 'baz'} - }). - andReturnSuccess(aSession). - end(); - - let desired = new Capabilities().set('foo', 'bar'); - let required = new Capabilities().set('bim', 'baz'); - var driver = WebDriver.createSession(executor, {desired, required}); - return driver.getSession().then(v => assert.strictEqual(v, aSession)); - }); - - it('failsToCreateSession', function() { - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({'desiredCapabilities': {'browserName': 'firefox'}}). - andReturnError(new StubError()). - end(); - - var driver = - WebDriver.createSession(executor, {'browserName': 'firefox'}); - return driver.getSession().then(fail, assertIsStubError); - }); - - it('invokes quit callback if it fails to create a session', function() { - let called = false; - let executor = new FakeExecutor() - .expect(CName.NEW_SESSION) - .withParameters({'desiredCapabilities': {'browserName': 'firefox'}}) - .andReturnError(new StubError()) - .end(); - - var driver = - WebDriver.createSession(executor, {'browserName': 'firefox'}, - null, null, () => called = true); - return driver.getSession().then(fail, err => { - assert.ok(called); - assertIsStubError(err); - }); - }); - - it('usesActiveFlowByDefault', function() { - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({'desiredCapabilities': {}}). - andReturnSuccess(new Session(SESSION_ID)). - end(); - - var driver = WebDriver.createSession(executor, {}); - assert.equal(promise.controlFlow(), driver.controlFlow()); - - return waitForIdle(driver.controlFlow()); - }); - - enablePromiseManager(() => { - it('canCreateInCustomFlow', function() { - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({'desiredCapabilities': {}}). - andReturnSuccess({}). - end(); - - var otherFlow = new promise.ControlFlow(); - var driver = WebDriver.createSession(executor, {}, otherFlow); - assert.equal(otherFlow, driver.controlFlow()); - assert.notEqual(otherFlow, promise.controlFlow()); - - return waitForIdle(otherFlow); - }); - - describe('creation failures bubble up in control flow', function() { - function runTest(...args) { - let executor = new FakeExecutor() - .expect(CName.NEW_SESSION) - .withParameters({'desiredCapabilities': {'browserName': 'firefox'}}) - .andReturnError(new StubError()) - .end(); - - WebDriver.createSession( - executor, {'browserName': 'firefox'}, ...args); - return waitForAbort().then(assertIsStubError); - } - - it('no onQuit callback', () => runTest()); - it('has onQuit callback', () => runTest(null, null, function() {})); - - it('onQuit callback failure suppress creation failure', function() { - let e = new Error('hi!'); - let executor = new FakeExecutor() - .expect(CName.NEW_SESSION) - .withParameters({'desiredCapabilities': {'browserName': 'firefox'}}) - .andReturnError(new StubError()) - .end(); - - WebDriver.createSession( - executor, {'browserName': 'firefox'}, null, null, - () => {throw e}); - return waitForAbort().then(err => assert.strictEqual(err, e)); - }); - }); - }); - }); - - it('testDoesNotExecuteCommandIfSessionDoesNotResolve', function() { - var session = Promise.reject(new StubError); - return new FakeExecutor().createDriver(session) - .getTitle() - .then(_ => assert.fail('should have failed'), assertIsStubError); - }); - - it('testCommandReturnValuesArePassedToFirstCallback', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE).andReturnSuccess('Google Search'). - end(); - - var driver = executor.createDriver(); - return driver.getTitle() - .then(title => assert.equal('Google Search', title)); - }); - - it('testStopsCommandExecutionWhenAnErrorOccurs', function() { - let e = new error.NoSuchWindowError('window not found'); - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(e). - end(); - - let driver = executor.createDriver(); - return driver.switchTo().window('foo') - .then( - _ => driver.getTitle(), // mock should blow if this gets executed - v => assert.strictEqual(v, e)); - }); - - it('testCanSuppressCommandFailures', function() { - let e = new error.NoSuchWindowError('window not found'); - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(e). - expect(CName.GET_TITLE). - andReturnSuccess('Google Search'). - end(); - - var driver = executor.createDriver(); - driver.switchTo().window('foo') - .catch(v => assert.strictEqual(v, e)); - driver.getTitle(); - return waitForIdle(); - }); - - it('testErrorsPropagateUpToTheRunningApplication', function() { - let e = new error.NoSuchWindowError('window not found'); - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(e). - end(); - - return executor.createDriver() - .switchTo().window('foo') - .then(_ => assert.fail(), v => assert.strictEqual(v, e)); - }); - - it('testErrbacksThatReturnErrorsStillSwitchToCallbackChain', function() { - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(new error.NoSuchWindowError('window not found')). - end(); - - var driver = executor.createDriver(); - return driver.switchTo().window('foo'). - catch(function() { return new StubError; }); - then(assertIsStubError, () => assert.fail()); - }); - - it('testErrbacksThrownCanOverrideOriginalError', function() { - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW, { - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(new error.NoSuchWindowError('window not found')). - end(); - - var driver = executor.createDriver(); - return driver.switchTo().window('foo') - .catch(throwStubError) - .then(assert.fail, assertIsStubError); - }); - - it('testReportsErrorWhenExecutingCommandsAfterExecutingAQuit', function() { - let executor = new FakeExecutor(). - expect(CName.QUIT). - end(); - - let verifyError = expectedError( - error.NoSuchSessionError, - 'This driver instance does not have a valid session ID ' + - '(did you call WebDriver.quit()?) and may no longer be used.'); - - let driver = executor.createDriver(); - return driver.quit() - .then(_ => driver.get('http://www.google.com')) - .then(assert.fail, verifyError); - }); - - it('testCallbackCommandsExecuteBeforeNextCommand', function() { - let executor = new FakeExecutor(). - expect(CName.GET_CURRENT_URL). - expect(CName.GET, {'url': 'http://www.google.com'}). - expect(CName.CLOSE). - expect(CName.GET_TITLE). - end(); - - var driver = executor.createDriver(); - driver.getCurrentUrl().then(function() { - driver.get('http://www.google.com').then(function() { - driver.close(); - }); - }); - driver.getTitle(); - - return waitForIdle(); - }); - - enablePromiseManager(() => { - it('testEachCallbackFrameRunsToCompletionBeforeTheNext', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE). - expect(CName.GET_CURRENT_URL). - expect(CName.GET_CURRENT_WINDOW_HANDLE). - expect(CName.CLOSE). - expect(CName.QUIT). - end(); - - var driver = executor.createDriver(); - driver.getTitle(). - // Everything in this callback... - then(function() { - driver.getCurrentUrl(); - driver.getWindowHandle(); - }). - // ...should execute before everything in this callback. - then(function() { - driver.close(); - }); - // This should execute after everything above - driver.quit(); - - return waitForIdle(); - }); - }); - - describe('returningAPromise', function() { - it('fromACallback', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE). - expect(CName.GET_CURRENT_URL). - andReturnSuccess('http://www.google.com'). - end(); - - var driver = executor.createDriver(); - return driver.getTitle(). - then(function() { - return driver.getCurrentUrl(); - }). - then(function(value) { - assert.equal('http://www.google.com', value); - }); - }); - - it('fromAnErrbackSuppressesTheError', function() { - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW, { - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(new StubError()). - expect(CName.GET_CURRENT_URL). - andReturnSuccess('http://www.google.com'). - end(); - - var driver = executor.createDriver(); - return driver.switchTo().window('foo'). - catch(function(e) { - assertIsStubError(e); - return driver.getCurrentUrl(); - }). - then(url => assert.equal('http://www.google.com', url)); - }); - }); - - describe('customFunctions', function() { - it('returnsANonPromiseValue', function() { - var driver = new FakeExecutor().createDriver(); - return driver.call(() => 'abc123').then(function(value) { - assert.equal('abc123', value); - }); - }); - - enablePromiseManager(() => { - it('executionOrderWithCustomFunctions', function() { - var msg = []; - let executor = new FakeExecutor(). - expect(CName.GET_TITLE).andReturnSuccess('cheese '). - expect(CName.GET_CURRENT_URL).andReturnSuccess('tasty'). - end(); - - var driver = executor.createDriver(); - - var pushMsg = msg.push.bind(msg); - driver.getTitle().then(pushMsg); - driver.call(() => 'is ').then(pushMsg); - driver.getCurrentUrl().then(pushMsg); - driver.call(() => '!').then(pushMsg); - - return waitForIdle().then(function() { - assert.equal('cheese is tasty!', msg.join('')); - }); - }); - }); - - it('passingArgumentsToACustomFunction', function() { - var add = function(a, b) { - return a + b; - }; - var driver = new FakeExecutor().createDriver(); - return driver.call(add, null, 1, 2).then(function(value) { - assert.equal(3, value); - }); - }); - - it('passingPromisedArgumentsToACustomFunction', function() { - var promisedArg = Promise.resolve(2); - var add = function(a, b) { - return a + b; - }; - var driver = new FakeExecutor().createDriver(); - return driver.call(add, null, 1, promisedArg).then(function(value) { - assert.equal(3, value); - }); - }); - - it('passingArgumentsAndScopeToACustomFunction', function() { - function Foo(name) { - this.name = name; - } - Foo.prototype.getName = function() { - return this.name; - }; - var foo = new Foo('foo'); - - var driver = new FakeExecutor().createDriver(); - return driver.call(foo.getName, foo).then(function(value) { - assert.equal('foo', value); - }); - }); - - it('customFunctionThrowsAnError', function() { - var driver = new FakeExecutor().createDriver(); - return driver.call(throwStubError).then(fail, assertIsStubError); - }); - - it('customFunctionSchedulesCommands', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE). - expect(CName.CLOSE). - expect(CName.QUIT). - end(); - - var driver = executor.createDriver(); - driver.call(function() { - driver.getTitle(); - driver.close(); - }); - driver.quit(); - return waitForIdle(); - }); - - it('returnsATaskResultAfterSchedulingAnother', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE). - andReturnSuccess('Google Search'). - expect(CName.CLOSE). - end(); - - var driver = executor.createDriver(); - return driver.call(function() { - var title = driver.getTitle(); - driver.close(); - return title; - }).then(function(title) { - assert.equal('Google Search', title); - }); - }); - - it('hasANestedCommandThatFails', function() { - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW, { - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(new StubError()). - end(); - - var driver = executor.createDriver(); - return driver.call(function() { - return driver.switchTo().window('foo'); - }).then(fail, assertIsStubError); - }); - - enablePromiseManager(() => { - it('doesNotCompleteUntilReturnedPromiseIsResolved', function() { - var order = []; - var driver = new FakeExecutor().createDriver(); - - var d = promise.defer(); - d.promise.then(function() { - order.push('b'); - }); - - driver.call(function() { - order.push('a'); - return d.promise; - }); - driver.call(function() { - order.push('c'); - }); - - // timeout to ensure the first function starts its execution before we - // trigger d's callbacks. - return new Promise(f => setTimeout(f, 0)).then(function() { - assert.deepEqual(['a'], order); - d.fulfill(); - return waitForIdle().then(function() { - assert.deepEqual(['a', 'b', 'c'], order); - }); - }); - }); - }); - - it('returnsADeferredAction', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE).andReturnSuccess('Google'). - end(); - - var driver = executor.createDriver(); - driver.call(function() { - return driver.getTitle(); - }).then(function(title) { - assert.equal('Google', title); - }); - return waitForIdle(); - }); - }); - - describe('nestedCommands', function() { - enablePromiseManager(() => { - it('commandExecutionOrder', function() { - var msg = []; - var driver = new FakeExecutor().createDriver(); - driver.call(msg.push, msg, 'a'); - driver.call(function() { - driver.call(msg.push, msg, 'c'); - driver.call(function() { - driver.call(msg.push, msg, 'e'); - driver.call(msg.push, msg, 'f'); - }); - driver.call(msg.push, msg, 'd'); - }); - driver.call(msg.push, msg, 'b'); - return waitForIdle().then(function() { - assert.equal('acefdb', msg.join('')); - }); - }); - - it('basicUsage', function() { - var msg = []; - var driver = new FakeExecutor().createDriver(); - var pushMsg = msg.push.bind(msg); - driver.call(() => 'cheese ').then(pushMsg); - driver.call(function() { - driver.call(() => 'is ').then(pushMsg); - driver.call(() => 'tasty').then(pushMsg); - }); - driver.call(() => '!').then(pushMsg); - return waitForIdle().then(function() { - assert.equal('cheese is tasty!', msg.join('')); - }); - }); - - it('normalCommandAfterNestedCommandThatReturnsAnAction', function() { - var msg = []; - let executor = new FakeExecutor(). - expect(CName.CLOSE). - end(); - var driver = executor.createDriver(); - driver.call(function() { - return driver.call(function() { - msg.push('a'); - return driver.call(() => 'foobar'); - }); - }); - driver.close().then(function() { - msg.push('b'); - }); - return waitForIdle().then(function() { - assert.equal('ab', msg.join('')); - }); - }); - }); - - it('canReturnValueFromNestedFunction', function() { - var driver = new FakeExecutor().createDriver(); - return driver.call(function() { - return driver.call(function() { - return driver.call(() => 'foobar'); - }); - }).then(function(value) { - assert.equal('foobar', value); - }); - }); - - it('errorsBubbleUp_caught', function() { - var driver = new FakeExecutor().createDriver(); - var result = driver.call(function() { - return driver.call(function() { - return driver.call(throwStubError); - }); - }).then(fail, assertIsStubError); - return Promise.all([waitForIdle(), result]); - }); - - it('errorsBubbleUp_uncaught', function() { - var driver = new FakeExecutor().createDriver(); - return driver.call(function() { - return driver.call(function() { - return driver.call(throwStubError); - }); - }) - .then(_ => assert.fail('should have failed'), assertIsStubError); - }); - - it('canScheduleCommands', function() { - let executor = new FakeExecutor(). - expect(CName.GET_TITLE). - expect(CName.CLOSE). - end(); - - var driver = executor.createDriver(); - driver.call(function() { - driver.call(function() { - driver.getTitle(); - }); - driver.close(); - }); - return waitForIdle(); - }); - }); - - describe('WebElementPromise', function() { - let driver = new FakeExecutor().createDriver(); - - it('resolvesWhenUnderlyingElementDoes', function() { - let el = new WebElement(driver, {'ELEMENT': 'foo'}); - return new WebElementPromise(driver, Promise.resolve(el)) - .then(e => assert.strictEqual(e, el)); - }); - - it('resolvesBeforeCallbacksOnWireValueTrigger', function() { - var el = defer(); - - var element = new WebElementPromise(driver, el.promise); - var messages = []; - - let steps = [ - element.then(_ => messages.push('element resolved')), - element.getId().then(_ => messages.push('wire value resolved')) - ]; - - el.resolve(new WebElement(driver, {'ELEMENT': 'foo'})); - return Promise.all(steps).then(function() { - assert.deepEqual([ - 'element resolved', - 'wire value resolved' - ], messages); - }); - }); - - it('isRejectedIfUnderlyingIdIsRejected', function() { - let element = - new WebElementPromise(driver, Promise.reject(new StubError)); - return element.then(fail, assertIsStubError); - }); - }); - - describe('executeScript', function() { - it('nullReturnValue', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return document.body;', - 'args': [] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - return driver.executeScript('return document.body;') - .then((result) => assert.equal(null, result)); - }); - - it('primitiveReturnValue', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return document.body;', - 'args': [] - }). - andReturnSuccess(123). - end(); - - var driver = executor.createDriver(); - return driver.executeScript('return document.body;') - .then((result) => assert.equal(123, result)); - }); - - it('webElementReturnValue', function() { - var json = WebElement.buildId('foo'); - - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return document.body;', - 'args': [] - }). - andReturnSuccess(json). - end(); - - var driver = executor.createDriver(); - return driver.executeScript('return document.body;') - .then((element) => element.getId()) - .then((id) => assert.equal(id, 'foo')); - }); - - it('arrayReturnValue', function() { - var json = [WebElement.buildId('foo')]; - - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return document.body;', - 'args': [] - }). - andReturnSuccess(json). - end(); - - var driver = executor.createDriver(); - return driver.executeScript('return document.body;') - .then(function(array) { - assert.equal(1, array.length); - return array[0].getId(); - }) - .then((id) => assert.equal('foo', id)); - }); - - it('objectReturnValue', function() { - var json = {'foo': WebElement.buildId('foo')}; - - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return document.body;', - 'args': [] - }). - andReturnSuccess(json). - end(); - - var driver = executor.createDriver(); - var callback; - return driver.executeScript('return document.body;') - .then((obj) => obj['foo'].getId()) - .then((id) => assert.equal(id, 'foo')); - }); - - it('scriptAsFunction', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return (' + function() {} + - ').apply(null, arguments);', - 'args': [] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - return driver.executeScript(function() {}); - }); - - it('simpleArgumentConversion', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return 1;', - 'args': ['abc', 123, true, [123, {'foo': 'bar'}]] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - return driver.executeScript( - 'return 1;', 'abc', 123, true, [123, {'foo': 'bar'}]); - }); - - it('webElementArgumentConversion', function() { - var elementJson = WebElement.buildId('fefifofum'); - - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return 1;', - 'args': [elementJson] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - return driver.executeScript('return 1;', - new WebElement(driver, 'fefifofum')); - }); - - it('webElementPromiseArgumentConversion', function() { - var elementJson = WebElement.buildId('bar'); - - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {'using': 'css selector', 'value': '*[id="foo"]'}). - andReturnSuccess(elementJson). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return 1;', - 'args': [elementJson] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - var element = driver.findElement(By.id('foo')); - return driver.executeScript('return 1;', element); - }); - - it('argumentConversion', function() { - var elementJson = WebElement.buildId('fefifofum'); - - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'return 1;', - 'args': ['abc', 123, true, elementJson, [123, {'foo': 'bar'}]] - }). - andReturnSuccess(null). - end(); - - var driver = executor.createDriver(); - var element = new WebElement(driver, 'fefifofum'); - return driver.executeScript('return 1;', - 'abc', 123, true, element, [123, {'foo': 'bar'}]); - }); - - it('scriptReturnsAnError', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT). - withParameters({ - 'script': 'throw Error(arguments[0]);', - 'args': ['bam'] - }). - andReturnError(new StubError). - end(); - var driver = executor.createDriver(); - return driver.executeScript('throw Error(arguments[0]);', 'bam'). - then(fail, assertIsStubError); - }); - - it('failsIfArgumentIsARejectedPromise', function() { - let executor = new FakeExecutor(); - - var arg = Promise.reject(new StubError); - arg.catch(function() {}); // Suppress default handler. - - var driver = executor.createDriver(); - return driver.executeScript(function() {}, arg). - then(fail, assertIsStubError); - }); - }); - - describe('executeAsyncScript', function() { - it('failsIfArgumentIsARejectedPromise', function() { - var arg = Promise.reject(new StubError); - arg.catch(function() {}); // Suppress default handler. - - var driver = new FakeExecutor().createDriver(); - return driver.executeAsyncScript(function() {}, arg). - then(fail, assertIsStubError); - }); - }); - - describe('findElement', function() { - it('elementNotFound', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnError(new StubError). - end(); - - var driver = executor.createDriver(); - return driver.findElement(By.id('foo')) - .then(assert.fail, assertIsStubError); - }); - - it('elementNotFoundInACallback', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnError(new StubError). - end(); - - var driver = executor.createDriver(); - return Promise.resolve() - .then(_ => driver.findElement(By.id('foo'))) - .then(assert.fail, assertIsStubError); - }); - - it('elementFound', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess(WebElement.buildId('bar')). - expect(CName.CLICK_ELEMENT, {'id': WebElement.buildId('bar')}). - andReturnSuccess(). - end(); - - var driver = executor.createDriver(); - var element = driver.findElement(By.id('foo')); - element.click(); - return waitForIdle(); - }); - - it('canUseElementInCallback', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess(WebElement.buildId('bar')). - expect(CName.CLICK_ELEMENT, {'id': WebElement.buildId('bar')}). - andReturnSuccess(). - end(); - - var driver = executor.createDriver(); - driver.findElement(By.id('foo')).then(function(element) { - element.click(); - }); - return waitForIdle(); - }); - - it('byJs', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': 'return document.body', - 'args': [] - }). - andReturnSuccess(WebElement.buildId('bar')). - expect(CName.CLICK_ELEMENT, {'id': WebElement.buildId('bar')}). - end(); - - var driver = executor.createDriver(); - var element = driver.findElement(By.js('return document.body')); - element.click(); // just to make sure - return waitForIdle(); - }); - - it('byJs_returnsNonWebElementValue', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, {'script': 'return 123', 'args': []}). - andReturnSuccess(123). - end(); - - var driver = executor.createDriver(); - return driver.findElement(By.js('return 123')) - .then(assert.fail, function(e) { - assertIsInstance(TypeError, e); - assert.equal( - 'Custom locator did not return a WebElement', e.message); - }); - }); - - it('byJs_canPassArguments', function() { - var script = 'return document.getElementsByTagName(arguments[0]);'; - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': script, - 'args': ['div'] - }). - andReturnSuccess(WebElement.buildId('one')). - end(); - var driver = executor.createDriver(); - driver.findElement(By.js(script, 'div')); - return waitForIdle(); - }); - - it('customLocator', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENTS, {'using': 'css selector', 'value': 'a'}). - andReturnSuccess([ - WebElement.buildId('foo'), - WebElement.buildId('bar')]). - expect(CName.CLICK_ELEMENT, {'id': WebElement.buildId('foo')}). - andReturnSuccess(). - end(); - - var driver = executor.createDriver(); - var element = driver.findElement(function(d) { - assert.equal(driver, d); - return d.findElements(By.tagName('a')); - }); - return element.click(); - }); - - it('customLocatorThrowsIfresultIsNotAWebElement', function() { - var driver = new FakeExecutor().createDriver(); - return driver.findElement(_ => 1) - .then(assert.fail, function(e) { - assertIsInstance(TypeError, e); - assert.equal( - 'Custom locator did not return a WebElement', e.message); - }); - }); - }); - - describe('findElements', function() { - it('returnsMultipleElements', function() { - var ids = ['foo', 'bar', 'baz']; - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENTS, {'using':'css selector', 'value':'a'}). - andReturnSuccess(ids.map(WebElement.buildId)). - end(); - - var driver = executor.createDriver(); - return driver.findElements(By.tagName('a')) - .then(function(elements) { - return promise.all(elements.map(function(e) { - assert.ok(e instanceof WebElement); - return e.getId(); - })); - }) - .then((actual) => assert.deepEqual(ids, actual)); - }); - - it('byJs', function() { - var ids = ['foo', 'bar', 'baz']; - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': 'return document.getElementsByTagName("div");', - 'args': [] - }). - andReturnSuccess(ids.map(WebElement.buildId)). - end(); - - var driver = executor.createDriver(); - - return driver. - findElements(By.js('return document.getElementsByTagName("div");')). - then(function(elements) { - return promise.all(elements.map(function(e) { - assert.ok(e instanceof WebElement); - return e.getId(); - })); - }). - then((actual) => assert.deepEqual(ids, actual)); - }); - - it('byJs_filtersOutNonWebElementResponses', function() { - var ids = ['foo', 'bar', 'baz']; - var json = [ - WebElement.buildId(ids[0]), - 123, - 'a', - false, - WebElement.buildId(ids[1]), - {'not a web element': 1}, - WebElement.buildId(ids[2]) - ]; - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': 'return document.getElementsByTagName("div");', - 'args': [] - }). - andReturnSuccess(json). - end(); - - var driver = executor.createDriver(); - driver.findElements(By.js('return document.getElementsByTagName("div");')). - then(function(elements) { - return promise.all(elements.map(function(e) { - assert.ok(e instanceof WebElement); - return e.getId(); - })); - }). - then((actual) => assert.deepEqual(ids, actual)); - return waitForIdle(); - }); - - it('byJs_convertsSingleWebElementResponseToArray', function() { - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': 'return document.getElementsByTagName("div");', - 'args': [] - }). - andReturnSuccess(WebElement.buildId('foo')). - end(); - - var driver = executor.createDriver(); - return driver. - findElements(By.js('return document.getElementsByTagName("div");')). - then(function(elements) { - return promise.all(elements.map(function(e) { - assert.ok(e instanceof WebElement); - return e.getId(); - })); - }). - then((actual) => assert.deepEqual(['foo'], actual)); - }); - - it('byJs_canPassScriptArguments', function() { - var script = 'return document.getElementsByTagName(arguments[0]);'; - let executor = new FakeExecutor(). - expect(CName.EXECUTE_SCRIPT, { - 'script': script, - 'args': ['div'] - }). - andReturnSuccess([ - WebElement.buildId('one'), - WebElement.buildId('two') - ]). - end(); - - var driver = executor.createDriver(); - return driver.findElements(By.js(script, 'div')) - then(function(elements) { - return promise.all(elements.map(function(e) { - assert.ok(e instanceof WebElement); - return e.getId(); - })); - }). - then((actual) => assert.deepEqual(['one', 'two'], actual)); - }); - }); - - describe('sendKeys', function() { - it('convertsVarArgsIntoStrings_simpleArgs', function() { - let executor = new FakeExecutor(). - expect(CName.SEND_KEYS_TO_ELEMENT, - {'id': WebElement.buildId('one'), - 'value':'12abc3'.split('')}). - andReturnSuccess(). - end(); - - var driver = executor.createDriver(); - var element = new WebElement(driver, 'one'); - element.sendKeys(1, 2, 'abc', 3); - return waitForIdle(); - }); - - it('convertsVarArgsIntoStrings_promisedArgs', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {'using':'css selector', 'value':'*[id="foo"]'}). - andReturnSuccess(WebElement.buildId('one')). - expect(CName.SEND_KEYS_TO_ELEMENT, - {'id':WebElement.buildId('one'), - 'value':'abc123def'.split('')}). - andReturnSuccess(). - end(); - - var driver = executor.createDriver(); - var element = driver.findElement(By.id('foo')); - return element.sendKeys( - Promise.resolve('abc'), - 123, - Promise.resolve('def')); - }); - - it('sendKeysWithAFileDetector', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {'using':'css selector', 'value':'*[id="foo"]'}). - andReturnSuccess(WebElement.buildId('one')). - expect(CName.SEND_KEYS_TO_ELEMENT, - {'id': WebElement.buildId('one'), - 'value':'modified/path'.split('')}). - andReturnSuccess(). - end(); - - let driver = executor.createDriver(); - let handleFile = function(d, path) { - assert.strictEqual(driver, d); - assert.equal(path, 'original/path'); - return Promise.resolve('modified/path'); - }; - driver.setFileDetector({handleFile}); - - return driver.findElement(By.id('foo')).sendKeys('original/', 'path'); - }); - }); - - describe("switchTo()", function() { - describe("window", function() { - it('should return a resolved promise when the window is found', function() { - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnSuccess(). - end(); - - executor.createDriver().switchTo().window('foo'); - return waitForIdle(); - }); - - it('should propagate exceptions', function() { - let e = new error.NoSuchWindowError('window not found'); - let executor = new FakeExecutor(). - expect(CName.SWITCH_TO_WINDOW). - withParameters({ - 'name': 'foo', - 'handle': 'foo' - }). - andReturnError(e). - end(); - - return executor.createDriver() - .switchTo().window('foo') - .then(assert.fail, v => assert.strictEqual(v, e)); - }); - }); - }); - - describe('elementEquality', function() { - it('isReflexive', function() { - var a = new WebElement(new FakeExecutor().createDriver(), 'foo'); - return WebElement.equals(a, a).then(assert.ok); - }); - - it('failsIfAnInputElementCouldNotBeFound', function() { - let id = Promise.reject(new StubError); - - var driver = new FakeExecutor().createDriver(); - var a = new WebElement(driver, 'foo'); - var b = new WebElementPromise(driver, id); - - return WebElement.equals(a, b).then(fail, assertIsStubError); - }); - }); - - describe('waiting', function() { - describe('supports custom wait functions', function() { - it('waitSucceeds', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess([]). - times(2). - expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess([WebElement.buildId('bar')]). - end(); - - var driver = executor.createDriver(); - driver.wait(function() { - return driver.findElements(By.id('foo')).then(els => els.length > 0); - }, 200); - return waitForIdle(); - }); - - it('waitTimesout_timeoutCaught', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess([]). - anyTimes(). - end(); - - var driver = executor.createDriver(); - return driver.wait(function() { - return driver.findElements(By.id('foo')).then(els => els.length > 0); - }, 25).then(fail, function(e) { - assert.equal('Wait timed out after ', - e.message.substring(0, 'Wait timed out after '.length)); - }); - }); - - enablePromiseManager(() => { - it('waitTimesout_timeoutNotCaught', function() { - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnSuccess([]). - anyTimes(). - end(); - - var driver = executor.createDriver(); - driver.wait(function() { - return driver.findElements(By.id('foo')).then(els => els.length > 0); - }, 25); - return waitForAbort().then(function(e) { - assert.equal('Wait timed out after ', - e.message.substring(0, 'Wait timed out after '.length)); - }); - }); - }); - }); - - describe('supports condition objects', function() { - it('wait succeeds', function() { - let executor = new FakeExecutor() - .expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}) - .andReturnSuccess([]) - .times(2) - .expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}) - .andReturnSuccess([WebElement.buildId('bar')]) - .end(); - - let driver = executor.createDriver(); - return driver.wait(until.elementLocated(By.id('foo')), 200); - }); - - it('wait times out', function() { - let executor = new FakeExecutor() - .expect(CName.FIND_ELEMENTS, - {using: 'css selector', value: '*[id="foo"]'}) - .andReturnSuccess([]) - .anyTimes() - .end(); - - let driver = executor.createDriver(); - return driver.wait(until.elementLocated(By.id('foo')), 5) - .then(fail, err => assert.ok(err instanceof error.TimeoutError)); - }); - }); - - describe('supports promise objects', function() { - it('wait succeeds', function() { - let promise = new Promise(resolve => { - setTimeout(() => resolve(1), 10); - }); - - let driver = new FakeExecutor().createDriver(); - return driver.wait(promise, 200).then(v => assert.equal(v, 1)); - }); - - it('wait times out', function() { - let promise = new Promise(resolve => {/* never resolves */}); - - let driver = new FakeExecutor().createDriver(); - return driver.wait(promise, 5) - .then(fail, err => assert.ok(err instanceof error.TimeoutError)); - }); - - it('wait fails if promise is rejected', function() { - let err = Error('boom'); - let driver = new FakeExecutor().createDriver(); - return driver.wait(Promise.reject(err), 5) - .then(fail, e => assert.strictEqual(e, err)); - }); - }); - - it('fails if not supported condition type provided', function() { - let driver = new FakeExecutor().createDriver(); - assert.throws(() => driver.wait({}, 5), TypeError); - }); - }); - - describe('alert handling', function() { - it('alertResolvesWhenPromisedTextResolves', function() { - let driver = new FakeExecutor().createDriver(); - let deferredText = defer(); - - let alert = new AlertPromise(driver, deferredText.promise); - - deferredText.resolve(new Alert(driver, 'foo')); - return alert.getText().then(text => assert.equal(text, 'foo')); - }); - - it('cannotSwitchToAlertThatIsNotPresent', function() { - let e = new error.NoSuchAlertError; - let executor = new FakeExecutor() - .expect(CName.GET_ALERT_TEXT) - .andReturnError(e) - .end(); - - return executor.createDriver() - .switchTo().alert() - .then(assert.fail, v => assert.strictEqual(v, e)); - }); - - enablePromiseManager(() => { - it('alertsBelongToSameFlowAsParentDriver', function() { - let executor = new FakeExecutor() - .expect(CName.GET_ALERT_TEXT).andReturnSuccess('hello') - .end(); - - var driver = executor.createDriver(); - var otherFlow = new promise.ControlFlow(); - otherFlow.execute(function() { - driver.switchTo().alert().then(function() { - assert.strictEqual( - driver.controlFlow(), promise.controlFlow(), - 'Alert should belong to the same flow as its parent driver'); - }); - }); - - assert.notEqual(otherFlow, driver.controlFlow); - return Promise.all([ - waitForIdle(otherFlow), - waitForIdle(driver.controlFlow()) - ]); - }); - }); - - it('commandsFailIfAlertNotPresent', function() { - let e = new error.NoSuchAlertError; - let executor = new FakeExecutor() - .expect(CName.GET_ALERT_TEXT) - .andReturnError(e) - .end(); - - var driver = executor.createDriver(); - var alert = driver.switchTo().alert(); - - var expectError = (v) => assert.strictEqual(v, e); - - return alert.getText() - .then(fail, expectedError) - .then(() => alert.accept()) - .then(fail, expectedError) - .then(() => alert.dismiss()) - .then(fail, expectError) - .then(() => alert.sendKeys('hi')) - .then(fail, expectError); - }); - }); - - enablePromiseManager(() => { - it('testWebElementsBelongToSameFlowAsParentDriver', function() { - let executor = new FakeExecutor() - .expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}) - .andReturnSuccess(WebElement.buildId('abc123')) - .end(); - - var driver = executor.createDriver(); - var otherFlow = new promise.ControlFlow(); - otherFlow.execute(function() { - driver.findElement({id: 'foo'}).then(function() { - assert.equal(driver.controlFlow(), promise.controlFlow()); - }); - }); - - assert.notEqual(otherFlow, driver.controlFlow); - return Promise.all([ - waitForIdle(otherFlow), - waitForIdle(driver.controlFlow()) - ]); - }); - }); - - it('testFetchingLogs', function() { - let executor = new FakeExecutor(). - expect(CName.GET_LOG, {'type': 'browser'}). - andReturnSuccess([ - {'level': 'INFO', 'message': 'hello', 'timestamp': 1234}, - {'level': 'DEBUG', 'message': 'abc123', 'timestamp': 5678} - ]). - end(); - - var driver = executor.createDriver(); - return driver.manage().logs().get('browser').then(function(entries) { - assert.equal(2, entries.length); - - assert.ok(entries[0] instanceof logging.Entry); - assert.equal(logging.Level.INFO.value, entries[0].level.value); - assert.equal('hello', entries[0].message); - assert.equal(1234, entries[0].timestamp); - - assert.ok(entries[1] instanceof logging.Entry); - assert.equal(logging.Level.DEBUG.value, entries[1].level.value); - assert.equal('abc123', entries[1].message); - assert.equal(5678, entries[1].timestamp); - }); - }); - - it('testCommandsFailIfInitialSessionCreationFailed', function() { - var session = Promise.reject(new StubError); - - var driver = new FakeExecutor().createDriver(session); - var navigateResult = driver.get('some-url').then(fail, assertIsStubError); - var quitResult = driver.quit().then(fail, assertIsStubError); - - return waitForIdle().then(function() { - return promise.all(navigateResult, quitResult); - }); - }); - - it('testWebElementCommandsFailIfInitialDriverCreationFailed', function() { - var session = Promise.reject(new StubError); - var driver = new FakeExecutor().createDriver(session); - return driver.findElement(By.id('foo')).click(). - then(fail, assertIsStubError); - }); - - it('testWebElementCommansFailIfElementCouldNotBeFound', function() { - let e = new error.NoSuchElementError('Unable to find element'); - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnError(e). - end(); - - var driver = executor.createDriver(); - return driver.findElement(By.id('foo')).click() - .then(fail, v => assert.strictEqual(v, e)); - }); - - it('testCannotFindChildElementsIfParentCouldNotBeFound', function() { - let e = new error.NoSuchElementError('Unable to find element'); - let executor = new FakeExecutor(). - expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}). - andReturnError(e). - end(); - - var driver = executor.createDriver(); - return driver.findElement(By.id('foo')) - .findElement(By.id('bar')) - .findElement(By.id('baz')) - .then(fail, v => assert.strictEqual(v, e)); - }); - - describe('actions()', function() { - it('failsIfInitialDriverCreationFailed', function() { - let session = Promise.reject(new StubError('no session for you')); - let driver = new FakeExecutor().createDriver(session); - driver.getSession().catch(function() {}); - return driver. - actions(). - mouseDown(). - mouseUp(). - perform(). - catch(assertIsStubError); - }); - - describe('mouseMove', function() { - it('noElement', function() { - let executor = new FakeExecutor() - .expect(CName.MOVE_TO, {'xoffset': 0, 'yoffset': 125}) - .andReturnSuccess() - .end(); - - return executor.createDriver(). - actions(). - mouseMove({x: 0, y: 125}). - perform(); - }); - - it('element', function() { - let executor = new FakeExecutor() - .expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="foo"]'}) - .andReturnSuccess(WebElement.buildId('abc123')) - .expect(CName.MOVE_TO, - {'element': 'abc123', 'xoffset': 0, 'yoffset': 125}) - .andReturnSuccess() - .end(); - - var driver = executor.createDriver(); - var element = driver.findElement(By.id('foo')); - return driver.actions() - .mouseMove(element, {x: 0, y: 125}) - .perform(); - }); - }); - - it('supportsMouseDown', function() { - let executor = new FakeExecutor() - .expect(CName.MOUSE_DOWN, {'button': Button.LEFT}) - .andReturnSuccess() - .end(); - - return executor.createDriver(). - actions(). - mouseDown(). - perform(); - }); - - it('testActionSequence', function() { - let executor = new FakeExecutor() - .expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="a"]'}) - .andReturnSuccess(WebElement.buildId('id1')) - .expect(CName.FIND_ELEMENT, - {using: 'css selector', value: '*[id="b"]'}) - .andReturnSuccess(WebElement.buildId('id2')) - .expect(CName.SEND_KEYS_TO_ACTIVE_ELEMENT, - {'value': [Key.SHIFT]}) - .andReturnSuccess() - .expect(CName.MOVE_TO, {'element': 'id1'}) - .andReturnSuccess() - .expect(CName.CLICK, {'button': Button.LEFT}) - .andReturnSuccess() - .expect(CName.MOVE_TO, {'element': 'id2'}) - .andReturnSuccess() - .expect(CName.CLICK, {'button': Button.LEFT}) - .andReturnSuccess() - .end(); - - var driver = executor.createDriver(); - var element1 = driver.findElement(By.id('a')); - var element2 = driver.findElement(By.id('b')); - - return driver.actions() - .keyDown(Key.SHIFT) - .click(element1) - .click(element2) - .perform(); - }); - }); - - describe('touchActions()', function() { - it('failsIfInitialDriverCreationFailed', function() { - let session = Promise.reject(new StubError); - let driver = new FakeExecutor().createDriver(session); - driver.getSession().catch(function() {}); - return driver. - touchActions(). - scroll({x: 3, y: 4}). - perform(). - catch(assertIsStubError); - }); - - it('testTouchActionSequence', function() { - let executor = new FakeExecutor() - .expect(CName.TOUCH_DOWN, {x: 1, y: 2}).andReturnSuccess() - .expect(CName.TOUCH_MOVE, {x: 3, y: 4}).andReturnSuccess() - .expect(CName.TOUCH_UP, {x: 5, y: 6}).andReturnSuccess() - .end(); - - var driver = executor.createDriver(); - return driver.touchActions() - .tapAndHold({x: 1, y: 2}) - .move({x: 3, y: 4}) - .release({x: 5, y: 6}) - .perform(); - }); - }); - - describe('manage()', function() { - describe('setTimeouts()', function() { - describe('throws if no timeouts are specified', function() { - let driver; - before(() => driver = new FakeExecutor().createDriver()); - - it('; no arguments', function() { - assert.throws(() => driver.manage().setTimeouts(), TypeError); - }); - - it('; ignores unrecognized timeout keys', function() { - assert.throws( - () => driver.manage().setTimeouts({foo: 123}), TypeError); - }); - - it('; ignores positional arguments', function() { - assert.throws( - () => driver.manage().setTimeouts(1234, 56), TypeError); - }); - }); - - describe('throws timeout is not a number, null, or undefined', () => { - let driver; - before(() => driver = new FakeExecutor().createDriver()); - - function checkError(e) { - return e instanceof TypeError - && /expected "(script|pageLoad|implicit)" to be a number/.test( - e.message); - } - - it('script', function() { - assert.throws( - () => driver.manage().setTimeouts({script: 'abc'}), - checkError); - }); - - it('pageLoad', function() { - assert.throws( - () => driver.manage().setTimeouts({pageLoad: 'abc'}), - checkError); - }); - - it('implicit', function() { - assert.throws( - () => driver.manage().setTimeouts({implicit: 'abc'}), - checkError); - }); - }); - - it('can set multiple timeouts', function() { - let executor = new FakeExecutor() - .expect(CName.SET_TIMEOUT, {script:1, pageLoad: 2, implicit: 3}) - .andReturnSuccess() - .end(); - let driver = executor.createDriver(); - return driver.manage() - .setTimeouts({script: 1, pageLoad: 2, implicit: 3}); - }); - - it('falls back to legacy wire format if W3C version fails', () => { - let executor = new FakeExecutor() - .expect(CName.SET_TIMEOUT, {implicit: 3}) - .andReturnError(Error('oops')) - .expect(CName.SET_TIMEOUT, {type: 'implicit', ms: 3}) - .andReturnSuccess() - .end(); - let driver = executor.createDriver(); - return driver.manage().setTimeouts({implicit: 3}); - }); - - describe('deprecated API calls setTimeouts()', function() { - it('implicitlyWait()', function() { - let executor = new FakeExecutor() - .expect(CName.SET_TIMEOUT, {implicit: 3}) - .andReturnSuccess() - .end(); - let driver = executor.createDriver(); - return driver.manage().timeouts().implicitlyWait(3); - }); - - it('setScriptTimeout()', function() { - let executor = new FakeExecutor() - .expect(CName.SET_TIMEOUT, {script: 3}) - .andReturnSuccess() - .end(); - let driver = executor.createDriver(); - return driver.manage().timeouts().setScriptTimeout(3); - }); - - it('pageLoadTimeout()', function() { - let executor = new FakeExecutor() - .expect(CName.SET_TIMEOUT, {pageLoad: 3}) - .andReturnSuccess() - .end(); - let driver = executor.createDriver(); - return driver.manage().timeouts().pageLoadTimeout(3); - }); - }); - }); - }); - - describe('generator support', function() { - var driver; - - beforeEach(function() { - driver = new WebDriver( - new Session('test-session', {}), - new ExplodingExecutor()); - }); - - it('canUseGeneratorsWithWebDriverCall', function() { - return driver.call(function* () { - var x = yield Promise.resolve(1); - var y = yield Promise.resolve(2); - return x + y; - }).then(function(value) { - assert.deepEqual(3, value); - }); - }); - - it('canDefineScopeOnGeneratorCall', function() { - return driver.call(function* () { - var x = yield Promise.resolve(1); - return this.name + x; - }, {name: 'Bob'}).then(function(value) { - assert.deepEqual('Bob1', value); - }); - }); - - it('canSpecifyArgsOnGeneratorCall', function() { - return driver.call(function* (a, b) { - var x = yield Promise.resolve(1); - var y = yield Promise.resolve(2); - return [x + y, a, b]; - }, null, 'abc', 123).then(function(value) { - assert.deepEqual([3, 'abc', 123], value); - }); - }); - - it('canUseGeneratorWithWebDriverWait', function() { - var values = []; - return driver.wait(function* () { - yield values.push(1); - values.push(yield promise.delayed(10).then(function() { - return 2; - })); - yield values.push(3); - return values.length === 6; - }, 250).then(function() { - assert.deepEqual([1, 2, 3, 1, 2, 3], values); - }); - }); - - /** - * @constructor - * @implements {CommandExecutor} - */ - function ExplodingExecutor() {} - - - /** @override */ - ExplodingExecutor.prototype.execute = function(command, cb) { - cb(Error('Unsupported operation')); - }; - }); - - describe('wire format', function() { - const FAKE_DRIVER = new FakeExecutor().createDriver(); - - describe('can serialize', function() { - function runSerializeTest(input, want) { - let executor = new FakeExecutor(). - expect(CName.NEW_SESSION). - withParameters({'desiredCapabilities': want}). - andReturnSuccess({'browserName': 'firefox'}). - end(); - return WebDriver.createSession(executor, input) - .getSession(); - } - - it('function as a string', function() { - function foo() { return 'foo'; } - return runSerializeTest(foo, '' + foo); - }); - - it('object with toJSON()', function() { - return runSerializeTest( - new Date(605728511546), - '1989-03-12T17:55:11.546Z'); - }); - - it('Session', function() { - return runSerializeTest(new Session('foo', {}), 'foo'); - }); - - it('Capabilities', function() { - var prefs = new logging.Preferences(); - prefs.setLevel(logging.Type.BROWSER, logging.Level.DEBUG); - - var caps = Capabilities.chrome(); - caps.setLoggingPrefs(prefs); - - return runSerializeTest( - caps, - { - 'browserName': 'chrome', - 'loggingPrefs': {'browser': 'DEBUG'} - }); - }); - - it('WebElement', function() { - return runSerializeTest( - new WebElement(FAKE_DRIVER, 'fefifofum'), - WebElement.buildId('fefifofum')); - }); - - it('WebElementPromise', function() { - return runSerializeTest( - new WebElementPromise( - FAKE_DRIVER, - Promise.resolve(new WebElement(FAKE_DRIVER, 'fefifofum'))), - WebElement.buildId('fefifofum')); - }); - - describe('an array', function() { - it('with Serializable', function() { - return runSerializeTest([new Session('foo', {})], ['foo']); - }); - - it('with WebElement', function() { - return runSerializeTest( - [new WebElement(FAKE_DRIVER, 'fefifofum')], - [WebElement.buildId('fefifofum')]); - }); - - it('with WebElementPromise', function() { - return runSerializeTest( - [new WebElementPromise( - FAKE_DRIVER, - Promise.resolve(new WebElement(FAKE_DRIVER, 'fefifofum')))], - [WebElement.buildId('fefifofum')]); - }); - - it('complex array', function() { - var expected = [ - 'abc', 123, true, WebElement.buildId('fefifofum'), - [123, {'foo': 'bar'}] - ]; - - var element = new WebElement(FAKE_DRIVER, 'fefifofum'); - var input = ['abc', 123, true, element, [123, {'foo': 'bar'}]]; - return runSerializeTest(input, expected); - }); - - it('nested promises', function() { - return runSerializeTest( - ['abc', Promise.resolve([123, Promise.resolve(true)])], - ['abc', [123, true]]); - }); - }); - - describe('an object', function() { - it('literal', function() { - var expected = {sessionId: 'foo'}; - return runSerializeTest({sessionId: 'foo'}, expected); - }); - - it('with sub-objects', function() { - var expected = {sessionId: {value: 'foo'}}; - return runSerializeTest( - {sessionId: {value: 'foo'}}, expected); - }); - - it('with values that have toJSON', function() { - return runSerializeTest( - {a: {b: new Date(605728511546)}}, - {a: {b: '1989-03-12T17:55:11.546Z'}}); - }); - - it('with a Session', function() { - return runSerializeTest( - {a: new Session('foo', {})}, - {a: 'foo'}); - }); - - it('nested', function() { - var elementJson = WebElement.buildId('fefifofum'); - var expected = { - 'script': 'return 1', - 'args': ['abc', 123, true, elementJson, [123, {'foo': 'bar'}]], - 'sessionId': 'foo' - }; - - var element = new WebElement(FAKE_DRIVER, 'fefifofum'); - var parameters = { - 'script': 'return 1', - 'args':['abc', 123, true, element, [123, {'foo': 'bar'}]], - 'sessionId': new Session('foo', {}) - }; - - return runSerializeTest(parameters, expected); - }); - }); - }); - - describe('can deserialize', function() { - function runDeserializeTest(original, want) { - let executor = new FakeExecutor() - .expect(CName.GET_CURRENT_URL) - .andReturnSuccess(original) - .end(); - let driver = executor.createDriver(); - return driver.getCurrentUrl().then(function(got) { - assert.deepEqual(got, want); - }); - } - - it('primitives', function() { - return Promise.all([ - runDeserializeTest(1, 1), - runDeserializeTest('', ''), - runDeserializeTest(true, true), - runDeserializeTest(undefined, undefined), - runDeserializeTest(null, null) - ]); - }); - - it('simple object', function() { - return runDeserializeTest( - {sessionId: 'foo'}, - {sessionId: 'foo'}); - }); - - it('nested object', function() { - return runDeserializeTest( - {'foo': {'bar': 123}}, - {'foo': {'bar': 123}}); - }); - - it('array', function() { - return runDeserializeTest( - [{'foo': {'bar': 123}}], - [{'foo': {'bar': 123}}]); - }); - - it('passes through function properties', function() { - function bar() {} - return runDeserializeTest( - [{foo: {'bar': 123}, func: bar}], - [{foo: {'bar': 123}, func: bar}]); - }); - }); - }); -}); |