diff --git a/NON-STANDARD-APIS.md b/NON-STANDARD-APIS.md index 9fa15172a..0257f94f2 100644 --- a/NON-STANDARD-APIS.md +++ b/NON-STANDARD-APIS.md @@ -13,6 +13,48 @@ But there are still a lot of non standard APIs are not patched by default, such ## Currently supported non standard node APIs +## Currently supported non standard common APIs + +* bluebird promise + +Browser Usage: + +``` + + + + +``` + +After those steps, window.Promise will become a ZoneAware Bluebird Promise. + +Node Usage: + +``` +require('zone-node.js'); +const Bluebird = require('bluebird'); +require('zone-bluebird.js'); +Zone[Zone['__symbol__']('bluebird')](Bluebird); +``` + +In NodeJS environment, you can choose to use Bluebird Promise as global.Promise +or use ZoneAwarePromise as global.Promise. + +To run the jasmine test cases of bluebird + +``` + npm install bluebird +``` + +then modify test/node_tests.ts +remove the comment of the following line + +``` +//import './extra/bluebird.spec'; +``` + ## Usage By default, those APIs' support will not be loaded in zone.js or zone-node.js, diff --git a/dist/zone-bluebird.js b/dist/zone-bluebird.js new file mode 100644 index 000000000..d9b240f7c --- /dev/null +++ b/dist/zone-bluebird.js @@ -0,0 +1,35 @@ +/** +* @license +* Copyright Google Inc. All Rights Reserved. +* +* Use of this source code is governed by an MIT-style license that can be +* found in the LICENSE file at https://angular.io/license +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +(function (_global) { + var __symbol__ = Zone['__symbol__']; + // TODO: @JiaLiPassion, we can automatically patch bluebird + // if global.Promise = Bluebird, but sometimes in nodejs, + // global.Promise is not Bluebird, and Bluebird is just be + // used by other libraries such as sequelize, so I think it is + // safe to just expose a method to patch Bluebird explicitly + Zone[__symbol__('bluebird')] = function patchBluebird(Bluebird) { + Bluebird.setScheduler(function (fn) { + Zone.current.scheduleMicroTask('bluebird', fn); + }); + }; +})(typeof window === 'object' && window || typeof self === 'object' && self || global); + +}))); diff --git a/dist/zone-bluebird.min.js b/dist/zone-bluebird.min.js new file mode 100644 index 000000000..faf89a974 --- /dev/null +++ b/dist/zone-bluebird.min.js @@ -0,0 +1 @@ +!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o():"function"==typeof define&&define.amd?define(o):o()}(this,function(){"use strict";!function(e){var o=Zone.__symbol__;Zone[o("bluebird")]=function(e){e.setScheduler(function(e){Zone.current.scheduleMicroTask("bluebird",e)})}}("object"==typeof window&&window||"object"==typeof self&&self||global)}); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index b86ed0ee8..0c65fdd54 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -99,6 +99,14 @@ gulp.task('build/webapis-notification.js', ['compile-esm'], function(cb) { return generateScript('./lib/browser/webapis-notification.ts', 'webapis-notification.js', true, cb); }); +gulp.task('build/bluebird.js', ['compile-esm'], function(cb) { + return generateScript('./lib/extra/bluebird.ts', 'zone-bluebird.js', false, cb); +}); + +gulp.task('build/bluebird.min.js', ['compile-esm'], function(cb) { + return generateScript('./lib/extra/bluebird.ts', 'zone-bluebird.min.js', true, cb); +}); + gulp.task('build/jasmine-patch.js', ['compile-esm'], function(cb) { return generateScript('./lib/jasmine/jasmine.ts', 'jasmine-patch.js', false, cb); }); @@ -167,6 +175,8 @@ gulp.task('build', [ 'build/webapis-media-query.js', 'build/webapis-notification.js', 'build/zone-mix.js', + 'build/bluebird.js', + 'build/bluebird.min.js', 'build/jasmine-patch.js', 'build/jasmine-patch.min.js', 'build/mocha-patch.js', diff --git a/lib/extra/bluebird.ts b/lib/extra/bluebird.ts new file mode 100644 index 000000000..b32c6cd91 --- /dev/null +++ b/lib/extra/bluebird.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +((_global: any) => { + const __symbol__ = Zone['__symbol__']; + // TODO: @JiaLiPassion, we can automatically patch bluebird + // if global.Promise = Bluebird, but sometimes in nodejs, + // global.Promise is not Bluebird, and Bluebird is just be + // used by other libraries such as sequelize, so I think it is + // safe to just expose a method to patch Bluebird explicitly + Zone[__symbol__('bluebird')] = function patchBluebird(Bluebird) { + Bluebird.setScheduler((fn) => { + Zone.current.scheduleMicroTask('bluebird', fn); + }); + }; +})(typeof window === 'object' && window || typeof self === 'object' && self || global); diff --git a/test/extra/bluebird.spec.ts b/test/extra/bluebird.spec.ts new file mode 100644 index 000000000..a039455fb --- /dev/null +++ b/test/extra/bluebird.spec.ts @@ -0,0 +1,588 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +// test bluebird promise patch +// this spec will not be integrated with Travis CI, because I don't +// want to add bluebird into devDependencies, you can run this spec +// on your local environment + +describe('bluebird promise', () => { + let BluebirdPromise; + beforeAll(() => { + BluebirdPromise = require('bluebird'); + // import bluebird patch + require('../../lib/extra/bluebird'); + const patchBluebird = Zone[Zone['__symbol__']('bluebird')]; + patchBluebird(BluebirdPromise); + }); + + let log; + + const zone = Zone.root.fork({ + name: 'bluebird', + onScheduleTask: (delegate, curr, targetZone, task) => { + log.push('schedule bluebird task ' + task.source); + return delegate.scheduleTask(targetZone, task); + }, + onInvokeTask: (delegate, curr, target, task, applyThis, applyArgs) => { + log.push('invoke bluebird task ' + task.source); + return delegate.invokeTask(target, task, applyThis, applyArgs); + } + }); + + beforeEach(() => { + log = []; + }); + + it('bluebird promise then method should be in zone and treated as microTask', (done) => { + zone.run(() => { + const p = new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + resolve('test'); + }, 0); + }); + p.then(() => { + expect(Zone.current.name).toEqual('bluebird'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise catch method should be in zone and treated as microTask', (done) => { + zone.run(() => { + const p = new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + reject('test'); + }, 0); + }); + p.catch(() => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise spread method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.all([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) + .spread((r1, r2) => { + expect(r1).toEqual('test1'); + expect(r2).toEqual('test2'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise finally method should be in zone', (done) => { + zone.run(() => { + const p = new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + resolve('test'); + }, 0); + }); + p.finally(() => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise join method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .join( + BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2'), + (r1, r2) => { + expect(r1).toEqual('test1'); + expect(r2).toEqual('test2'); + expect(Zone.current.name).toEqual('bluebird'); + }) + .then(() => { + expect(Zone.current.name).toEqual('bluebird'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise try method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .try(() => { + throw new Error('promise error'); + }) + .catch((err) => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(err.message).toEqual('promise error'); + done(); + }); + }); + }); + + it('bluebird promise method method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .method(() => { + return 'test'; + })() + .then((result) => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(result).toEqual('test'); + done(); + }); + }); + }); + + it('bluebird promise resolve method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve('test').then((result) => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(result).toEqual('test'); + done(); + }); + }); + }); + + it('bluebird promise reject method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.reject('error').catch((error) => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(error).toEqual('error'); + done(); + }); + }); + }); + + it('bluebird promise all method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.all([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) + .then((r) => { + expect(r[0]).toEqual('test1'); + expect(r[1]).toEqual('test2'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise props method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .props({test1: BluebirdPromise.resolve('test1'), test2: BluebirdPromise.resolve('test2')}) + .then((r) => { + expect(r.test1).toEqual('test1'); + expect(r.test2).toEqual('test2'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise any method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.any([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) + .then((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise some method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.some([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')], 1) + .then((r) => { + expect(r.length).toBe(1); + expect(r[0]).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise map method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .map( + ['test1', 'test2'], + (value) => { + return BluebirdPromise.resolve(value); + }) + .then((r) => { + expect(r.length).toBe(2); + expect(r[0]).toEqual('test1'); + expect(r[1]).toEqual('test2'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise reduce method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .reduce( + [1, 2], + (total, value) => { + return BluebirdPromise.resolve(total + value); + }) + .then((r) => { + expect(r).toBe(3); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length) + .toBeTruthy(); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length) + .toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise filter method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .filter( + [1, 2, 3], + (value) => { + return value % 2 === 0 ? BluebirdPromise.resolve(true) : + BluebirdPromise.resolve(false); + }) + .then((r) => { + expect(r[0]).toBe(2); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise each method should be in zone', (done) => { + zone.run(() => { + const arr = [1, 2, 3]; + BluebirdPromise.each( + BluebirdPromise.map(arr, (item) => BluebirdPromise.resolve(item)), (r, idx) => { + expect(r[idx] === arr[idx]); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length) + .toBeTruthy(); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length) + .toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise mapSeries method should be in zone', (done) => { + zone.run(() => { + const arr = [1, 2, 3]; + BluebirdPromise.mapSeries( + BluebirdPromise.map(arr, (item) => BluebirdPromise.resolve(item)), (r, idx) => { + expect(r[idx] === arr[idx]); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length) + .toBeTruthy(); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length) + .toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise race method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.race([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) + .then((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise using/disposer method should be in zone', (done) => { + zone.run(() => { + const p = new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + resolve('test'); + }, 0); + }); + p.leakObj = []; + const disposer = p.disposer(() => { + p.leakObj = null; + }); + BluebirdPromise + .using( + disposer, + (v) => { + p.leakObj.push(v); + }) + .then(() => { + expect(Zone.current.name).toEqual('bluebird'); + expect(p.leakObj).toBe(null); + // using will generate several promise inside bluebird + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise promisify method should be in zone and treated as microTask', (done) => { + const func = (cb: Function) => { + setTimeout(() => { + cb(null, 'test'); + }, 10); + }; + + const promiseFunc = BluebirdPromise.promisify(func); + zone.run(() => { + promiseFunc().then((r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise promisifyAll method should be in zone', (done) => { + const obj = { + func1: (cb: Function) => { + setTimeout(() => { + cb(null, 'test1'); + }, 10); + }, + func2: (cb: Function) => { + setTimeout(() => { + cb(null, 'test2'); + }, 10); + }, + }; + + const promiseObj = BluebirdPromise.promisifyAll(obj); + zone.run(() => { + BluebirdPromise.all([promiseObj.func1Async(), promiseObj.func2Async()]).then((r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r[0]).toBe('test1'); + expect(r[1]).toBe('test2'); + // using will generate several promise inside + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(2); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(2); + done(); + }); + }); + }); + + it('bluebird promise fromCallback method should be in zone', (done) => { + const resolver = (cb: Function) => { + setTimeout(() => { + cb(null, 'test'); + }, 10); + }; + + zone.run(() => { + BluebirdPromise.fromCallback(resolver).then((r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise asCallback method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve('test').asCallback((err, r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + done(); + }); + }); + }); + + it('bluebird promise delay method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve('test').delay(10).then((r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(2); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(2); + done(); + }); + }); + }); + + it('bluebird promise timeout method should be in zone', (done) => { + zone.run(() => { + new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + resolve('test'); + }, 10); + }) + .timeout(100) + .then((r) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + done(); + }); + }); + }); + + it('bluebird promise tap method should be in zone', (done) => { + zone.run(() => { + const p = new BluebirdPromise((resolve, reject) => { + setTimeout(() => { + resolve('test'); + }, 0); + }); + p.tap(() => { + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise call method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise + .map( + ['test1', 'test2'], + (value) => { + return BluebirdPromise.resolve(value); + }) + .call( + 'shift', + (value) => { + return value; + }) + .then((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise get method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve(['test1', 'test2']).get(-1).then((r) => { + expect(r).toEqual('test2'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise return method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve().return ('test1').then((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise throw method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.resolve().throw('test1').catch((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise catchReturn method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.reject().catchReturn('test1').then((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise catchThrow method should be in zone', (done) => { + zone.run(() => { + BluebirdPromise.reject().catchThrow('test1').catch((r) => { + expect(r).toEqual('test1'); + expect(log.filter(item => item === 'schedule bluebird task bluebird').length).toBe(1); + expect(log.filter(item => item === 'invoke bluebird task bluebird').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); + }); + }); + + it('bluebird promise reflect method should be in zone', (done) => { + zone.run(() => { + const promises = [BluebirdPromise.resolve('test1'), BluebirdPromise.reject('test2')]; + BluebirdPromise + .all(promises.map(promise => { + return promise.reflect(); + })) + .each((r) => { + if (r.isFulfilled()) { + expect(r.value()).toEqual('test1'); + } else { + expect(r.reason()).toEqual('test2'); + done(); + } + expect(Zone.current.name).toEqual('bluebird'); + }); + }); + }); +}); diff --git a/test/node/Error.spec.ts b/test/node/Error.spec.ts index c1049dbd1..52c621bd7 100644 --- a/test/node/Error.spec.ts +++ b/test/node/Error.spec.ts @@ -18,15 +18,18 @@ describe('ZoneAwareError', () => { }); it('should support prepareStackTrace', () => { + const originalPrepareStackTrace = (Error).prepareStackTrace; (Error).prepareStackTrace = function(error, stack) { return stack; }; let obj: any = new Object(); Error.captureStackTrace(obj); expect(obj.stack[0].getFileName()).not.toBeUndefined(); + (Error).prepareStackTrace = originalPrepareStackTrace; }); it('should not add additional stacktrace from Zone when use prepareStackTrace', () => { + const originalPrepareStackTrace = (Error).prepareStackTrace; (Error).prepareStackTrace = function(error, stack) { return stack; }; @@ -36,5 +39,6 @@ describe('ZoneAwareError', () => { obj.stack.forEach(function(st) { expect(st.getFunctionName()).not.toEqual('zoneCaptureStackTrace'); }); + (Error).prepareStackTrace = originalPrepareStackTrace; }); }); diff --git a/test/node_tests.ts b/test/node_tests.ts index 6e6d5424c..258f62eee 100644 --- a/test/node_tests.ts +++ b/test/node_tests.ts @@ -12,3 +12,7 @@ import './node/process.spec'; import './node/Error.spec'; import './node/crypto.spec'; import './node/http.spec'; + +// before test bluebird, must run npm install bluebird first. +// then remove the comment below +// import './extra/bluebird.spec';