Kargi-Sitesi/node_modules/selenium-webdriver/test/lib/promise_test.js

1109 lines
35 KiB
JavaScript

// 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()));
});
});