'use strict'; var assert = require('assert'); var adapter = require('./promise-adapter'); var P = global[Zone.__symbol__('Promise')]; var someRejectionReason = {message: 'some rejection reason'}; var anotherReason = {message: 'another rejection reason'}; process.on( 'unhandledRejection', function(reason, promise) { console.log('unhandledRejection', reason); }); describe('mocha promise sanity check', () => { it('passes with a resolved promise', () => { return P.resolve(3); }); it('passes with a rejected then resolved promise', () => { return P.reject(someRejectionReason).catch(x => 'this should be resolved'); }); var ifPromiseIt = P === Promise ? it : it.skip; ifPromiseIt('is the native Promise', () => { assert.equal(P, Promise); }); }); describe('onFinally', () => { describe('no callback', () => { specify('from resolved', (done) => { adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally() .then( function onFulfilled(x) { assert.strictEqual(x, 3); done(); }, function onRejected() { done(new Error('should not be called')); }); }); specify('from rejected', (done) => { adapter.rejected(someRejectionReason) .catch((e) => { assert.strictEqual(e, someRejectionReason); throw e; }) .finally() .then( function onFulfilled() { done(new Error('should not be called')); }, function onRejected(reason) { assert.strictEqual(reason, someRejectionReason); done(); }); }); }); describe('throws an exception', () => { specify('from resolved', (done) => { adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); throw someRejectionReason; }) .then( function onFulfilled() { done(new Error('should not be called')); }, function onRejected(reason) { assert.strictEqual(reason, someRejectionReason); done(); }); }); specify('from rejected', (done) => { adapter.rejected(anotherReason) .finally(function onFinally() { assert(arguments.length === 0); throw someRejectionReason; }) .then( function onFulfilled() { done(new Error('should not be called')); }, function onRejected(reason) { assert.strictEqual(reason, someRejectionReason); done(); }); }); }); describe('returns a non-promise', () => { specify('from resolved', (done) => { adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); return 4; }) .then( function onFulfilled(x) { assert.strictEqual(x, 3); done(); }, function onRejected() { done(new Error('should not be called')); }); }); specify('from rejected', (done) => { adapter.rejected(anotherReason) .catch((e) => { assert.strictEqual(e, anotherReason); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); throw someRejectionReason; }) .then( function onFulfilled() { done(new Error('should not be called')); }, function onRejected(e) { assert.strictEqual(e, someRejectionReason); done(); }); }); }); describe('returns a pending-forever promise', () => { specify('from resolved', (done) => { var timeout; adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 0.1e3); return new P(() => {}); // forever pending }) .then( function onFulfilled(x) { clearTimeout(timeout); done(new Error('should not be called')); }, function onRejected() { clearTimeout(timeout); done(new Error('should not be called')); }); }); specify('from rejected', (done) => { var timeout; adapter.rejected(someRejectionReason) .catch((e) => { assert.strictEqual(e, someRejectionReason); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 0.1e3); return new P(() => {}); // forever pending }) .then( function onFulfilled(x) { clearTimeout(timeout); done(new Error('should not be called')); }, function onRejected() { clearTimeout(timeout); done(new Error('should not be called')); }); }); }); describe('returns an immediately-fulfilled promise', () => { specify('from resolved', (done) => { adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); return adapter.resolved(4); }) .then( function onFulfilled(x) { assert.strictEqual(x, 3); done(); }, function onRejected() { done(new Error('should not be called')); }); }); specify('from rejected', (done) => { adapter.rejected(someRejectionReason) .catch((e) => { assert.strictEqual(e, someRejectionReason); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); return adapter.resolved(4); }) .then( function onFulfilled() { done(new Error('should not be called')); }, function onRejected(e) { assert.strictEqual(e, someRejectionReason); done(); }); }); }); describe('returns an immediately-rejected promise', () => { specify('from resolved ', (done) => { adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); return adapter.rejected(4); }) .then( function onFulfilled(x) { done(new Error('should not be called')); }, function onRejected(e) { assert.strictEqual(e, 4); done(); }); }); specify('from rejected', (done) => { const newReason = {}; adapter.rejected(someRejectionReason) .catch((e) => { assert.strictEqual(e, someRejectionReason); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); return adapter.rejected(newReason); }) .then( function onFulfilled(x) { done(new Error('should not be called')); }, function onRejected(e) { assert.strictEqual(e, newReason); done(); }); }); }); describe('returns a fulfilled-after-a-second promise', () => { specify('from resolved', (done) => { var timeout; adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 1.5e3); return new P((resolve) => { setTimeout(() => resolve(4), 1e3); }); }) .then( function onFulfilled(x) { clearTimeout(timeout); assert.strictEqual(x, 3); done(); }, function onRejected() { clearTimeout(timeout); done(new Error('should not be called')); }); }); specify('from rejected', (done) => { var timeout; adapter.rejected(3) .catch((e) => { assert.strictEqual(e, 3); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 1.5e3); return new P((resolve) => { setTimeout(() => resolve(4), 1e3); }); }) .then( function onFulfilled() { clearTimeout(timeout); done(new Error('should not be called')); }, function onRejected(e) { clearTimeout(timeout); assert.strictEqual(e, 3); done(); }); }); }); describe('returns a rejected-after-a-second promise', () => { specify('from resolved', (done) => { var timeout; adapter.resolved(3) .then((x) => { assert.strictEqual(x, 3); return x; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 1.5e3); return new P((resolve, reject) => { setTimeout(() => reject(4), 1e3); }); }) .then( function onFulfilled() { clearTimeout(timeout); done(new Error('should not be called')); }, function onRejected(e) { clearTimeout(timeout); assert.strictEqual(e, 4); done(); }); }); specify('from rejected', (done) => { var timeout; adapter.rejected(someRejectionReason) .catch((e) => { assert.strictEqual(e, someRejectionReason); throw e; }) .finally(function onFinally() { assert(arguments.length === 0); timeout = setTimeout(done, 1.5e3); return new P((resolve, reject) => { setTimeout(() => reject(anotherReason), 1e3); }); }) .then( function onFulfilled() { clearTimeout(timeout); done(new Error('should not be called')); }, function onRejected(e) { clearTimeout(timeout); assert.strictEqual(e, anotherReason); done(); }); }); }); specify('has the correct property descriptor', () => { var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, 'finally'); assert.strictEqual(descriptor.writable, true); assert.strictEqual(descriptor.configurable, true); }); });