From 389762ca48f8850a42825a38ca871934fd65fd46 Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Tue, 3 Apr 2018 03:29:16 +0900 Subject: [PATCH] fix(test): add flag to patch jasmine.clock, move fakeAsync/async into original bundle (#1067) --- .travis.yml | 2 + dist/zone-async-testing.js | 107 ------------ dist/zone-fake-async.js | 161 ----------------- dist/zone-mix.js | 64 +++++-- dist/zone-node.js | 64 +++++-- dist/zone-patch-resize-observer.js | 38 +++- dist/zone-patch-resize-observer.min.js | 2 +- dist/zone-testing-bundle.js | 64 +++++-- dist/zone-testing-node-bundle.js | 64 +++++-- dist/zone.js | 64 +++++-- dist/zone.min.js | 4 +- gulpfile.js | 22 ++- karma-base.conf.js | 2 +- karma-dist.conf.js | 6 +- lib/jasmine/jasmine.ts | 102 +++++------ lib/testing/async-testing.ts | 4 + lib/testing/fake-async.ts | 1 + lib/testing/zone-testing.ts | 4 +- lib/zone-spec/async-test.ts | 20 ++- test/browser-zone-setup.ts | 7 +- test/node_entry_point.ts | 14 +- test/test-env-setup-jasmine-no-patch-clock.ts | 8 + test/zone-spec/async-test.spec.ts | 12 +- test/zone-spec/fake-async-test.spec.ts | 165 +++++++++++------- 24 files changed, 483 insertions(+), 518 deletions(-) delete mode 100644 dist/zone-async-testing.js delete mode 100644 dist/zone-fake-async.js create mode 100644 test/test-env-setup-jasmine-no-patch-clock.ts diff --git a/.travis.yml b/.travis.yml index 93c1c1f27..3ec8c6596 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ script: - node_modules/.bin/karma start karma-dist-sauce-selenium3-jasmine.conf.js --single-run - node_modules/.bin/karma start karma-build-sauce-selenium3-mocha.conf.js --single-run - node_modules/.bin/gulp test/node + - node_modules/.bin/gulp test/node -no-patch-clock - node_modules/.bin/gulp test/bluebird - node simple-server.js 2>&1> server.log& - node ./test/webdriver/test.sauce.js @@ -48,3 +49,4 @@ script: - node_modules/.bin/karma start karma-dist-sauce-jasmine3.conf.js --single-run - node_modules/.bin/karma start karma-build-sauce-selenium3-mocha.conf.js --single-run - node_modules/.bin/gulp test/node + - node_modules/.bin/gulp test/node -no-patch-clock diff --git a/dist/zone-async-testing.js b/dist/zone-async-testing.js deleted file mode 100644 index 9d6f52df8..000000000 --- a/dist/zone-async-testing.js +++ /dev/null @@ -1,107 +0,0 @@ -/** -* @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 - */ -Zone.__load_patch('asynctest', function (global, Zone, api) { - /** - * Wraps a test function in an asynchronous test zone. The test will automatically - * complete when all asynchronous calls within this zone are done. - */ - Zone[api.symbol('asyncTest')] = function asyncTest(fn) { - // If we're running using the Jasmine test framework, adapt to call the 'done' - // function when asynchronous activity is finished. - if (global.jasmine) { - // Not using an arrow function to preserve context passed from call site - return function (done) { - if (!done) { - // if we run beforeEach in @angular/core/testing/testing_internal then we get no done - // fake it here and assume sync. - done = function () { }; - done.fail = function (e) { - throw e; - }; - } - runInTestZone(fn, this, done, function (err) { - if (typeof err === 'string') { - return done.fail(new Error(err)); - } - else { - done.fail(err); - } - }); - }; - } - // Otherwise, return a promise which will resolve when asynchronous activity - // is finished. This will be correctly consumed by the Mocha framework with - // it('...', async(myFn)); or can be used in a custom framework. - // Not using an arrow function to preserve context passed from call site - return function () { - var _this = this; - return new Promise(function (finishCallback, failCallback) { - runInTestZone(fn, _this, finishCallback, failCallback); - }); - }; - }; - function runInTestZone(fn, context, finishCallback, failCallback) { - var currentZone = Zone.current; - var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; - if (AsyncTestZoneSpec === undefined) { - throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + - 'Please make sure that your environment includes zone.js/dist/async-test.js'); - } - var ProxyZoneSpec = Zone['ProxyZoneSpec']; - if (ProxyZoneSpec === undefined) { - throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + - 'Please make sure that your environment includes zone.js/dist/proxy.js'); - } - var proxyZoneSpec = ProxyZoneSpec.get(); - ProxyZoneSpec.assertPresent(); - // We need to create the AsyncTestZoneSpec outside the ProxyZone. - // If we do it in ProxyZone then we will get to infinite recursion. - var proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); - var previousDelegate = proxyZoneSpec.getDelegate(); - proxyZone.parent.run(function () { - var testZoneSpec = new AsyncTestZoneSpec(function () { - // Need to restore the original zone. - if (proxyZoneSpec.getDelegate() == testZoneSpec) { - // Only reset the zone spec if it's - // sill this one. Otherwise, assume - // it's OK. - proxyZoneSpec.setDelegate(previousDelegate); - } - currentZone.run(function () { - finishCallback(); - }); - }, function (error) { - // Need to restore the original zone. - if (proxyZoneSpec.getDelegate() == testZoneSpec) { - // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. - proxyZoneSpec.setDelegate(previousDelegate); - } - currentZone.run(function () { - failCallback(error); - }); - }, 'test'); - proxyZoneSpec.setDelegate(testZoneSpec); - }); - return Zone.current.runGuarded(fn, context); - } -}); - -}))); diff --git a/dist/zone-fake-async.js b/dist/zone-fake-async.js deleted file mode 100644 index 8ae013811..000000000 --- a/dist/zone-fake-async.js +++ /dev/null @@ -1,161 +0,0 @@ -/** -* @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 - */ -Zone.__load_patch('fakeasync', function (global, Zone, api) { - var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; - var ProxyZoneSpec = Zone && Zone['ProxyZoneSpec']; - var _fakeAsyncTestZoneSpec = null; - /** - * Clears out the shared fake async zone for a test. - * To be called in a global `beforeEach`. - * - * @experimental - */ - function resetFakeAsyncZone() { - if (_fakeAsyncTestZoneSpec) { - _fakeAsyncTestZoneSpec.unlockDatePatch(); - } - _fakeAsyncTestZoneSpec = null; - // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. - ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate(); - } - /** - * Wraps a function to be executed in the fakeAsync zone: - * - microtasks are manually executed by calling `flushMicrotasks()`, - * - timers are synchronous, `tick()` simulates the asynchronous passage of time. - * - * If there are any pending timers at the end of the function, an exception will be thrown. - * - * Can be used to wrap inject() calls. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @param fn - * @returns The function wrapped to be executed in the fakeAsync zone - * - * @experimental - */ - function fakeAsync(fn) { - // Not using an arrow function to preserve context passed from call site - return function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var proxyZoneSpec = ProxyZoneSpec.assertPresent(); - if (Zone.current.get('FakeAsyncTestZoneSpec')) { - throw new Error('fakeAsync() calls can not be nested'); - } - try { - // in case jasmine.clock init a fakeAsyncTestZoneSpec - if (!_fakeAsyncTestZoneSpec) { - if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { - throw new Error('fakeAsync() calls can not be nested'); - } - _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); - } - var res = void 0; - var lastProxyZoneSpec = proxyZoneSpec.getDelegate(); - proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); - _fakeAsyncTestZoneSpec.lockDatePatch(); - try { - res = fn.apply(this, args); - flushMicrotasks(); - } - finally { - proxyZoneSpec.setDelegate(lastProxyZoneSpec); - } - if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { - throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + - "periodic timer(s) still in the queue."); - } - if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { - throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); - } - return res; - } - finally { - resetFakeAsyncZone(); - } - }; - } - function _getFakeAsyncZoneSpec() { - if (_fakeAsyncTestZoneSpec == null) { - _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); - if (_fakeAsyncTestZoneSpec == null) { - throw new Error('The code should be running in the fakeAsync zone to call this function'); - } - } - return _fakeAsyncTestZoneSpec; - } - /** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. - * - * The microtasks queue is drained at the very start of this function and after any timer callback - * has been executed. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @experimental - */ - function tick(millis) { - if (millis === void 0) { millis = 0; } - _getFakeAsyncZoneSpec().tick(millis); - } - /** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by - * draining the macrotask queue until it is empty. The returned value is the milliseconds - * of time that would have been elapsed. - * - * @param maxTurns - * @returns The simulated time elapsed, in millis. - * - * @experimental - */ - function flush(maxTurns) { - return _getFakeAsyncZoneSpec().flush(maxTurns); - } - /** - * Discard all remaining periodic tasks. - * - * @experimental - */ - function discardPeriodicTasks() { - var zoneSpec = _getFakeAsyncZoneSpec(); - var pendingTimers = zoneSpec.pendingPeriodicTimers; - zoneSpec.pendingPeriodicTimers.length = 0; - } - /** - * Flush any pending microtasks. - * - * @experimental - */ - function flushMicrotasks() { - _getFakeAsyncZoneSpec().flushMicrotasks(); - } - Zone[api.symbol('fakeAsyncTest')] = - { resetFakeAsyncZone: resetFakeAsyncZone, flushMicrotasks: flushMicrotasks, discardPeriodicTasks: discardPeriodicTasks, tick: tick, flush: flush, fakeAsync: fakeAsync }; -}); - -}))); diff --git a/dist/zone-mix.js b/dist/zone-mix.js index 23a6e068f..4b59965e3 100644 --- a/dist/zone-mix.js +++ b/dist/zone-mix.js @@ -643,6 +643,16 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); +var __values = (undefined && undefined.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -916,14 +926,24 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var value = values_1[_i]; - if (!isThenable(value)) { - value = this.resolve(value); + try { + for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { + var value = values_1_1.value; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then(onResolve, onReject); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); } - value.then(onResolve, onReject); + finally { if (e_1) throw e_1.error; } } return promise; + var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -934,23 +954,33 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { - var value = values_2[_i]; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); + try { + for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { + var value = values_2_1.value; + if (!isThenable(value)) { + value = this.resolve(value); } - }; })(count), reject); - count++; + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + } + finally { if (e_2) throw e_2.error; } } if (!count) resolve(resolvedValues); return promise; + var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone-node.js b/dist/zone-node.js index c857c893c..dc55a8875 100644 --- a/dist/zone-node.js +++ b/dist/zone-node.js @@ -643,6 +643,16 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); +var __values = (undefined && undefined.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -916,14 +926,24 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var value = values_1[_i]; - if (!isThenable(value)) { - value = this.resolve(value); + try { + for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { + var value = values_1_1.value; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then(onResolve, onReject); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); } - value.then(onResolve, onReject); + finally { if (e_1) throw e_1.error; } } return promise; + var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -934,23 +954,33 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { - var value = values_2[_i]; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); + try { + for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { + var value = values_2_1.value; + if (!isThenable(value)) { + value = this.resolve(value); } - }; })(count), reject); - count++; + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + } + finally { if (e_2) throw e_2.error; } } if (!count) resolve(resolvedValues); return promise; + var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone-patch-resize-observer.js b/dist/zone-patch-resize-observer.js index b0cabc088..e80c32588 100644 --- a/dist/zone-patch-resize-observer.js +++ b/dist/zone-patch-resize-observer.js @@ -11,6 +11,16 @@ (factory()); }(this, (function () { 'use strict'; +var __values = (undefined && undefined.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; /** * @license * Copyright Google Inc. All Rights Reserved. @@ -31,17 +41,26 @@ Zone.__load_patch('ResizeObserver', function (global, Zone, api) { var _this = this; var zones = {}; var currZone = Zone.current; - for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) { - var entry = entries_1[_i]; - var zone = entry.target[resizeObserverSymbol]; - if (!zone) { - zone = currZone; + try { + for (var entries_1 = __values(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) { + var entry = entries_1_1.value; + var zone = entry.target[resizeObserverSymbol]; + if (!zone) { + zone = currZone; + } + var zoneEntriesInfo = zones[zone.name]; + if (!zoneEntriesInfo) { + zones[zone.name] = zoneEntriesInfo = { entries: [], zone: zone }; + } + zoneEntriesInfo.entries.push(entry); } - var zoneEntriesInfo = zones[zone.name]; - if (!zoneEntriesInfo) { - zones[zone.name] = zoneEntriesInfo = { entries: [], zone: zone }; + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1); } - zoneEntriesInfo.entries.push(entry); + finally { if (e_1) throw e_1.error; } } Object.keys(zones).forEach(function (zoneName) { var zoneEntriesInfo = zones[zoneName]; @@ -52,6 +71,7 @@ Zone.__load_patch('ResizeObserver', function (global, Zone, api) { callback.call(_this, zoneEntriesInfo.entries, observer); } }); + var e_1, _a; }; } return args.length > 0 ? new ResizeObserver(args[0]) : new ResizeObserver(); diff --git a/dist/zone-patch-resize-observer.min.js b/dist/zone-patch-resize-observer.min.js index bffe2a10a..4e3ef0583 100644 --- a/dist/zone-patch-resize-observer.min.js +++ b/dist/zone-patch-resize-observer.min.js @@ -1 +1 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(this,function(){"use strict";Zone.__load_patch("ResizeObserver",function(e,n,r){var t=e.ResizeObserver;if(t){var o=r.symbol("ResizeObserver");r.patchMethod(e,"ResizeObserver",function(e){return function(e,r){var i=r.length>0?r[0]:null;return i&&(r[0]=function(e,r){for(var t=this,u={},a=n.current,c=0,f=e;c0?new t(r[0]):new t}}),r.patchMethod(t.prototype,"observe",function(e){return function(r,t){var i=t.length>0?t[0]:null;if(!i)return e.apply(r,t);var u=r[o];return u||(u=r[o]=[]),u.push(i),i[o]=n.current,e.apply(r,t)}}),r.patchMethod(t.prototype,"unobserve",function(e){return function(n,r){var t=r.length>0?r[0]:null;if(!t)return e.apply(n,r);var i=n[o];if(i)for(var u=0;u=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}};Zone.__load_patch("ResizeObserver",function(n,r,t){var o=n.ResizeObserver;if(o){var i=t.symbol("ResizeObserver");t.patchMethod(n,"ResizeObserver",function(n){return function(n,t){var u=t.length>0?t[0]:null;return u&&(t[0]=function(n,t){var o=this,a={},c=r.current;try{for(var f=e(n),l=f.next();!l.done;l=f.next()){var v=l.value,p=v.target[i];p||(p=c);var s=a[p.name];s||(a[p.name]=s={entries:[],zone:p}),s.entries.push(v)}}catch(h){d={error:h}}finally{try{l&&!l.done&&(y=f["return"])&&y.call(f)}finally{if(d)throw d.error}}Object.keys(a).forEach(function(e){var n=a[e];n.zone!==r.current?n.zone.run(u,o,[n.entries,t],"ResizeObserver"):u.call(o,n.entries,t)});var d,y}),t.length>0?new o(t[0]):new o}}),t.patchMethod(o.prototype,"observe",function(e){return function(n,t){var o=t.length>0?t[0]:null;if(!o)return e.apply(n,t);var u=n[i];return u||(u=n[i]=[]),u.push(o),o[i]=r.current,e.apply(n,t)}}),t.patchMethod(o.prototype,"unobserve",function(e){return function(n,r){var t=r.length>0?r[0]:null;if(!t)return e.apply(n,r);var o=n[i];if(o)for(var u=0;u= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -916,14 +926,24 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var value = values_1[_i]; - if (!isThenable(value)) { - value = this.resolve(value); + try { + for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { + var value = values_1_1.value; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then(onResolve, onReject); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); } - value.then(onResolve, onReject); + finally { if (e_1) throw e_1.error; } } return promise; + var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -934,23 +954,33 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { - var value = values_2[_i]; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); + try { + for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { + var value = values_2_1.value; + if (!isThenable(value)) { + value = this.resolve(value); } - }; })(count), reject); - count++; + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + } + finally { if (e_2) throw e_2.error; } } if (!count) resolve(resolvedValues); return promise; + var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone-testing-node-bundle.js b/dist/zone-testing-node-bundle.js index 85de0f422..71a8528ed 100644 --- a/dist/zone-testing-node-bundle.js +++ b/dist/zone-testing-node-bundle.js @@ -643,6 +643,16 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); +var __values = (undefined && undefined.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -916,14 +926,24 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var value = values_1[_i]; - if (!isThenable(value)) { - value = this.resolve(value); + try { + for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { + var value = values_1_1.value; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then(onResolve, onReject); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); } - value.then(onResolve, onReject); + finally { if (e_1) throw e_1.error; } } return promise; + var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -934,23 +954,33 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { - var value = values_2[_i]; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); + try { + for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { + var value = values_2_1.value; + if (!isThenable(value)) { + value = this.resolve(value); } - }; })(count), reject); - count++; + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + } + finally { if (e_2) throw e_2.error; } } if (!count) resolve(resolvedValues); return promise; + var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone.js b/dist/zone.js index e15c127cf..2cd0134c8 100644 --- a/dist/zone.js +++ b/dist/zone.js @@ -643,6 +643,16 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); +var __values = (undefined && undefined.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -916,14 +926,24 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var value = values_1[_i]; - if (!isThenable(value)) { - value = this.resolve(value); + try { + for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { + var value = values_1_1.value; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then(onResolve, onReject); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); } - value.then(onResolve, onReject); + finally { if (e_1) throw e_1.error; } } return promise; + var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -934,23 +954,33 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { - var value = values_2[_i]; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); + try { + for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { + var value = values_2_1.value; + if (!isThenable(value)) { + value = this.resolve(value); } - }; })(count), reject); - count++; + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + } + finally { if (e_2) throw e_2.error; } } if (!count) resolve(resolvedValues); return promise; + var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone.min.js b/dist/zone.min.js index b95e78412..7d809e8d1 100644 --- a/dist/zone.min.js +++ b/dist/zone.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(this,function(){"use strict";function e(e,t){return Zone.current.wrap(e,t)}function t(e,t,n,r,o){return Zone.current.scheduleMacroTask(e,t,n,r,o)}function n(t,n){for(var r=t.length-1;r>=0;r--)"function"==typeof t[r]&&(t[r]=e(t[r],n+"_"+r));return t}function r(e,t){for(var r=e.constructor.name,a=function(a){var i=t[a],s=e[i];if(s){var c=P(e,i);if(!o(c))return"continue";e[i]=function(e){var t=function(){return e.apply(this,n(arguments,r+"."+i))};return l(t,e),t}(s)}},i=0;i=0&&"function"==typeof a[i.cbIdx]?t(i.name,a[i.cbIdx],i,o,null):e.apply(n,a)}})}function l(e,t){e[B("OriginalDelegate")]=t}function f(){if(te)return ne;te=!0;try{var e=W.navigator.userAgent;return e.indexOf("MSIE ")===-1&&e.indexOf("Trident/")===-1&&e.indexOf("Edge/")===-1||(ne=!0),ne}catch(t){}}function p(e,t,n){function r(t,n){if(!t)return!1;var r=!0;n&&void 0!==n.useG&&(r=n.useG);var d=n&&n.vh,y=!0;n&&void 0!==n.chkDup&&(y=n.chkDup);var m=!1;n&&void 0!==n.rt&&(m=n.rt);for(var k=t;k&&!k.hasOwnProperty(o);)k=C(k);if(!k&&t[o]&&(k=t),!k)return!1;if(k[c])return!1;var _,b={},T=k[c]=k[o],w=k[B(a)]=k[a],E=k[B(i)]=k[i],S=k[B(s)]=k[s];n&&n.prepend&&(_=k[B(n.prepend)]=k[n.prepend]);var D=function(){if(!b.isExisting)return T.call(b.target,b.eventName,b.capture?g:v,b.options)},Z=function(e){if(!e.isRemoved){var t=oe[e.eventName],n=void 0;t&&(n=t[e.capture?F:q]);var r=n&&e.target[n];if(r)for(var o=0;o1?new n(e,t):new n(e),s=P(a,"onmessage");return s&&s.configurable===!1?(r=I(a),o=a,[M,R,"send","close"].forEach(function(e){r[e]=function(){var t=L.call(arguments);if(e===M||e===R){var n=t.length>0?t[0]:void 0;if(n){var o=Zone.__symbol__("ON_PROPERTY"+n);a[o]=r[o]}}return a[e].apply(a,t)}})):r=a,i(r,["close","error","message","open"],o),r};var r=t.WebSocket;for(var o in n)r[o]=n[o]}function T(e,t,n){if(!n)return t;var r=n.filter(function(t){return t.target===e});if(!r||0===r.length)return t;var o=r[0].ignoreProperties;return t.filter(function(e){return o.indexOf(e)===-1})}function w(e,t,n,r){if(e){var o=T(e,t,n);i(e,o,r)}}function E(e,t){if(!K||Y){var n="undefined"!=typeof WebSocket;if(S()){var r=t.__Zone_ignore_on_properties;if(J){var o=window;w(o,Oe.concat(["messageerror"]),r,C(o)),w(Document.prototype,Oe,r),"undefined"!=typeof o.SVGElement&&w(o.SVGElement.prototype,Oe,r),w(Element.prototype,Oe,r),w(HTMLElement.prototype,Oe,r),w(HTMLMediaElement.prototype,ye,r),w(HTMLFrameSetElement.prototype,ve.concat(we),r),w(HTMLBodyElement.prototype,ve.concat(we),r),w(HTMLFrameElement.prototype,Te,r),w(HTMLIFrameElement.prototype,Te,r);var a=o.HTMLMarqueeElement;a&&w(a.prototype,Ee,r);var i=o.Worker;i&&w(i.prototype,ze,r)}w(XMLHttpRequest.prototype,Se,r);var c=t.XMLHttpRequestEventTarget;c&&w(c&&c.prototype,Se,r),"undefined"!=typeof IDBIndex&&(w(IDBIndex.prototype,De,r),w(IDBRequest.prototype,De,r),w(IDBOpenDBRequest.prototype,De,r),w(IDBDatabase.prototype,De,r),w(IDBTransaction.prototype,De,r),w(IDBCursor.prototype,De,r)),n&&w(WebSocket.prototype,Ze,r)}else D(),s("XMLHttpRequest"),n&&b(e,t)}}function S(){if((J||Y)&&!P(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var e=P(Element.prototype,"onclick");if(e&&!e.configurable)return!1}var t="onreadystatechange",n=XMLHttpRequest.prototype,r=P(n,t);if(r){j(n,t,{enumerable:!0,configurable:!0,get:function(){return!0}});var o=new XMLHttpRequest,a=!!o.onreadystatechange;return j(n,t,r||{}),a}var i=B("fake");j(n,t,{enumerable:!0,configurable:!0,get:function(){return this[i]},set:function(e){this[i]=e}});var o=new XMLHttpRequest,s=function(){};o.onreadystatechange=s;var a=o[i]===s;return o.onreadystatechange=null,a}function D(){for(var t=function(t){var n=Oe[t],r="on"+n;self.addEventListener(n,function(t){var n,o,a=t.target;for(o=a?a.constructor.name+"."+r:"unknown."+r;a;)a[r]&&!a[r][Pe]&&(n=e(a[r],o),n[Pe]=a[r],a[r]=n),a=a.parentElement},!0)},n=0;n",this._properties=t&&t.properties||{},this._zoneDelegate=new p(this,this._parent&&this._parent._zoneDelegate,t)}return r.assertZonePatched=function(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(r,"root",{get:function(){for(var e=r.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(r,"current",{get:function(){return j.zone},enumerable:!0,configurable:!0}),Object.defineProperty(r,"currentTask",{get:function(){return C},enumerable:!0,configurable:!0}),r.__load_patch=function(o,a){if(O.hasOwnProperty(o))throw Error("Already loaded patch: "+o);if(!e["__Zone_disable_"+o]){var i="Zone:"+o;t(i),O[o]=a(e,r,P),n(i,i)}},Object.defineProperty(r.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),r.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},r.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},r.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},r.prototype.wrap=function(e,t){if(typeof e!==s)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},r.prototype.run=function(e,t,n,r){void 0===t&&(t=void 0),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{j=j.parent}},r.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{j=j.parent}},r.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");var r=e.state===_;if(!r||e.type!==z){var o=e.state!=w;o&&e._transitionTo(w,T),e.runCount++;var a=C;C=e,j={parent:j,zone:this};try{e.type==Z&&e.data&&!e.data.isPeriodic&&(e.cancelFn=null);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{e.state!==_&&e.state!==S&&(e.type==z||e.data&&e.data.isPeriodic?o&&e._transitionTo(T,w):(e.runCount=0,this._updateTaskCount(e,-1),o&&e._transitionTo(_,w,_))),j=j.parent,C=a}}},r.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(b,_);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,b,_),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==b&&e._transitionTo(T,b),e},r.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new h(D,e,t,n,r,null))},r.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new h(Z,e,t,n,r,o))},r.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new h(z,e,t,n,r,o))},r.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");e._transitionTo(E,T,w);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,E),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(_,E),e.runCount=0,e},r.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;t==-1&&(e._zoneDelegates=null);for(var r=0;r0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e};this.hasTask(this.zone,a)}},e}(),h=function(){function t(n,r,o,a,i,s){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=a,this.scheduleFn=i,this.cancelFn=s,this.callback=o;var c=this;n===z&&a&&a.useG?this.invoke=t.invokeTask:this.invoke=function(){return t.invokeTask.call(e,c,this,arguments)}}return t.invokeTask=function(e,t,n){e||(e=this),I++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==I&&o(),I--}},Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),t.prototype.cancelScheduleRequest=function(){this._transitionTo(_,b)},t.prototype._transitionTo=function(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+e+"', expecting state '"+t+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=e,e==_&&(this._zoneDelegates=null)},t.prototype.toString=function(){return this.data&&"undefined"!=typeof this.data.handleId?this.data.handleId:Object.prototype.toString.call(this)},t.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},t}(),d=i("setTimeout"),v=i("Promise"),g=i("then"),y=[],m=!1,k={name:"NO ZONE"},_="notScheduled",b="scheduling",T="scheduled",w="running",E="canceling",S="unknown",D="microTask",Z="macroTask",z="eventTask",O={},P={symbol:i,currentZoneFrame:function(){return j},onUnhandledError:a,microtaskDrainDone:a,scheduleMicroTask:r,showUncaughtError:function(){return!l[i("ignoreConsoleErrorUncaughtError")]},patchEventTarget:function(){return[]},patchOnProperties:a,patchMethod:function(){return a},bindArguments:function(){return null},setNativePromise:function(e){e&&typeof e.resolve===s&&(u=e.resolve(0))}},j={parent:null,zone:new l(null,null)},C=null,I=0;return n("Zone","Zone"),e.Zone=l})("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global);Zone.__load_patch("ZoneAwarePromise",function(e,t,n){function r(e){if(e&&e.toString===Object.prototype.toString){var t=e.constructor&&e.constructor.name;return(t?t:"")+": "+JSON.stringify(e)}return e?e.toString():Object.prototype.toString.call(e)}function o(e){n.onUnhandledError(e);try{var r=t[b];r&&"function"==typeof r&&r.call(this,e)}catch(o){}}function a(e){return e&&e.then}function i(e){return e}function s(e){return H.reject(e)}function c(e,t){return function(n){try{u(e,t,n)}catch(r){u(e,!1,r)}}}function u(e,o,a){var i=C();if(e===a)throw new TypeError(I);if(e[T]===z){var s=null;try{"object"!=typeof a&&"function"!=typeof a||(s=a&&a.then)}catch(p){return i(function(){u(e,!1,p)})(),e}if(o!==P&&a instanceof H&&a.hasOwnProperty(T)&&a.hasOwnProperty(w)&&a[T]!==z)l(a),u(e,a[T],a[w]);else if(o!==P&&"function"==typeof s)try{s.call(a,i(c(e,o)),i(c(e,!1)))}catch(p){i(function(){u(e,!1,p)})()}else{e[T]=o;var h=e[w];if(e[w]=a,e[E]===E&&o===O&&(e[T]=e[D],e[w]=e[S]),o===P&&a instanceof Error){var d=t.currentTask&&t.currentTask.data&&t.currentTask.data[_];d&&v(a,L,{configurable:!0,enumerable:!1,writable:!0,value:d})}for(var g=0;g=0;r--)"function"==typeof t[r]&&(t[r]=e(t[r],n+"_"+r));return t}function r(e,t){for(var r=e.constructor.name,a=function(a){var i=t[a],s=e[i];if(s){var c=j(e,i);if(!o(c))return"continue";e[i]=function(e){var t=function(){return e.apply(this,n(arguments,r+"."+i))};return l(t,e),t}(s)}},i=0;i=0&&"function"==typeof a[i.cbIdx]?t(i.name,a[i.cbIdx],i,o,null):e.apply(n,a)}})}function l(e,t){e[N("OriginalDelegate")]=t}function f(){if(ne)return re;ne=!0;try{var e=X.navigator.userAgent;return e.indexOf("MSIE ")===-1&&e.indexOf("Trident/")===-1&&e.indexOf("Edge/")===-1||(re=!0),re}catch(t){}}function p(e,t,n){function r(t,n){if(!t)return!1;var r=!0;n&&void 0!==n.useG&&(r=n.useG);var d=n&&n.vh,y=!0;n&&void 0!==n.chkDup&&(y=n.chkDup);var m=!1;n&&void 0!==n.rt&&(m=n.rt);for(var k=t;k&&!k.hasOwnProperty(o);)k=I(k);if(!k&&t[o]&&(k=t),!k)return!1;if(k[c])return!1;var _,b={},T=k[c]=k[o],w=k[N(a)]=k[a],E=k[N(i)]=k[i],S=k[N(s)]=k[s];n&&n.prepend&&(_=k[N(n.prepend)]=k[n.prepend]);var D=function(){if(!b.isExisting)return T.call(b.target,b.eventName,b.capture?g:v,b.options)},Z=function(e){if(!e.isRemoved){var t=ae[e.eventName],n=void 0;t&&(n=t[e.capture?q:A]);var r=n&&e.target[n];if(r)for(var o=0;o1?new n(e,t):new n(e),s=j(a,"onmessage");return s&&s.configurable===!1?(r=L(a),o=a,[R,x,"send","close"].forEach(function(e){r[e]=function(){var t=M.call(arguments);if(e===R||e===x){var n=t.length>0?t[0]:void 0;if(n){var o=Zone.__symbol__("ON_PROPERTY"+n);a[o]=r[o]}}return a[e].apply(a,t)}})):r=a,i(r,["close","error","message","open"],o),r};var r=t.WebSocket;for(var o in n)r[o]=n[o]}function T(e,t,n){if(!n)return t;var r=n.filter(function(t){return t.target===e});if(!r||0===r.length)return t;var o=r[0].ignoreProperties;return t.filter(function(e){return o.indexOf(e)===-1})}function w(e,t,n,r){if(e){var o=T(e,t,n);i(e,o,r)}}function E(e,t){if(!J||Q){var n="undefined"!=typeof WebSocket;if(S()){var r=t.__Zone_ignore_on_properties;if(Y){var o=window;w(o,Pe.concat(["messageerror"]),r,I(o)),w(Document.prototype,Pe,r),"undefined"!=typeof o.SVGElement&&w(o.SVGElement.prototype,Pe,r),w(Element.prototype,Pe,r),w(HTMLElement.prototype,Pe,r),w(HTMLMediaElement.prototype,me,r),w(HTMLFrameSetElement.prototype,ge.concat(Ee),r),w(HTMLBodyElement.prototype,ge.concat(Ee),r),w(HTMLFrameElement.prototype,we,r),w(HTMLIFrameElement.prototype,we,r);var a=o.HTMLMarqueeElement;a&&w(a.prototype,Se,r);var i=o.Worker;i&&w(i.prototype,Oe,r)}w(XMLHttpRequest.prototype,De,r);var c=t.XMLHttpRequestEventTarget;c&&w(c&&c.prototype,De,r),"undefined"!=typeof IDBIndex&&(w(IDBIndex.prototype,Ze,r),w(IDBRequest.prototype,Ze,r),w(IDBOpenDBRequest.prototype,Ze,r),w(IDBDatabase.prototype,Ze,r),w(IDBTransaction.prototype,Ze,r),w(IDBCursor.prototype,Ze,r)),n&&w(WebSocket.prototype,ze,r)}else D(),s("XMLHttpRequest"),n&&b(e,t)}}function S(){if((Y||Q)&&!j(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var e=j(Element.prototype,"onclick");if(e&&!e.configurable)return!1}var t="onreadystatechange",n=XMLHttpRequest.prototype,r=j(n,t);if(r){C(n,t,{enumerable:!0,configurable:!0,get:function(){return!0}});var o=new XMLHttpRequest,a=!!o.onreadystatechange;return C(n,t,r||{}),a}var i=N("fake");C(n,t,{enumerable:!0,configurable:!0,get:function(){return this[i]},set:function(e){this[i]=e}});var o=new XMLHttpRequest,s=function(){};o.onreadystatechange=s;var a=o[i]===s;return o.onreadystatechange=null,a}function D(){for(var t=function(t){var n=Pe[t],r="on"+n;self.addEventListener(n,function(t){var n,o,a=t.target;for(o=a?a.constructor.name+"."+r:"unknown."+r;a;)a[r]&&!a[r][je]&&(n=e(a[r],o),n[je]=a[r],a[r]=n),a=a.parentElement},!0)},n=0;n",this._properties=t&&t.properties||{},this._zoneDelegate=new p(this,this._parent&&this._parent._zoneDelegate,t)}return r.assertZonePatched=function(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(r,"root",{get:function(){for(var e=r.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(r,"current",{get:function(){return j.zone},enumerable:!0,configurable:!0}),Object.defineProperty(r,"currentTask",{get:function(){return C},enumerable:!0,configurable:!0}),r.__load_patch=function(o,a){if(O.hasOwnProperty(o))throw Error("Already loaded patch: "+o);if(!e["__Zone_disable_"+o]){var i="Zone:"+o;t(i),O[o]=a(e,r,P),n(i,i)}},Object.defineProperty(r.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),r.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},r.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},r.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},r.prototype.wrap=function(e,t){if(typeof e!==s)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},r.prototype.run=function(e,t,n,r){void 0===t&&(t=void 0),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{j=j.parent}},r.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{j=j.parent}},r.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");var r=e.state===_;if(!r||e.type!==z){var o=e.state!=w;o&&e._transitionTo(w,T),e.runCount++;var a=C;C=e,j={parent:j,zone:this};try{e.type==Z&&e.data&&!e.data.isPeriodic&&(e.cancelFn=null);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{e.state!==_&&e.state!==S&&(e.type==z||e.data&&e.data.isPeriodic?o&&e._transitionTo(T,w):(e.runCount=0,this._updateTaskCount(e,-1),o&&e._transitionTo(_,w,_))),j=j.parent,C=a}}},r.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(b,_);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,b,_),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==b&&e._transitionTo(T,b),e},r.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new h(D,e,t,n,r,null))},r.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new h(Z,e,t,n,r,o))},r.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new h(z,e,t,n,r,o))},r.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");e._transitionTo(E,T,w);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,E),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(_,E),e.runCount=0,e},r.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;t==-1&&(e._zoneDelegates=null);for(var r=0;r0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e};this.hasTask(this.zone,a)}},e}(),h=function(){function t(n,r,o,a,i,s){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=a,this.scheduleFn=i,this.cancelFn=s,this.callback=o;var c=this;n===z&&a&&a.useG?this.invoke=t.invokeTask:this.invoke=function(){return t.invokeTask.call(e,c,this,arguments)}}return t.invokeTask=function(e,t,n){e||(e=this),I++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==I&&o(),I--}},Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),t.prototype.cancelScheduleRequest=function(){this._transitionTo(_,b)},t.prototype._transitionTo=function(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+e+"', expecting state '"+t+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=e,e==_&&(this._zoneDelegates=null)},t.prototype.toString=function(){return this.data&&"undefined"!=typeof this.data.handleId?this.data.handleId:Object.prototype.toString.call(this)},t.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},t}(),d=i("setTimeout"),v=i("Promise"),g=i("then"),y=[],m=!1,k={name:"NO ZONE"},_="notScheduled",b="scheduling",T="scheduled",w="running",E="canceling",S="unknown",D="microTask",Z="macroTask",z="eventTask",O={},P={symbol:i,currentZoneFrame:function(){return j},onUnhandledError:a,microtaskDrainDone:a,scheduleMicroTask:r,showUncaughtError:function(){return!l[i("ignoreConsoleErrorUncaughtError")]},patchEventTarget:function(){return[]},patchOnProperties:a,patchMethod:function(){return a},bindArguments:function(){return null},setNativePromise:function(e){e&&typeof e.resolve===s&&(u=e.resolve(0))}},j={parent:null,zone:new l(null,null)},C=null,I=0;return n("Zone","Zone"),e.Zone=l}("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global),function(e){var t="function"==typeof Symbol&&e[Symbol.iterator],n=0;return t?t.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}});Zone.__load_patch("ZoneAwarePromise",function(e,t,n){function r(e){if(e&&e.toString===Object.prototype.toString){var t=e.constructor&&e.constructor.name;return(t?t:"")+": "+JSON.stringify(e)}return e?e.toString():Object.prototype.toString.call(e)}function o(e){n.onUnhandledError(e);try{var r=t[b];r&&"function"==typeof r&&r.call(this,e)}catch(o){}}function a(e){return e&&e.then}function i(e){return e}function s(e){return H.reject(e)}function c(e,t){return function(n){try{u(e,t,n)}catch(r){u(e,!1,r)}}}function u(e,o,a){var i=I();if(e===a)throw new TypeError(L);if(e[T]===z){var s=null;try{"object"!=typeof a&&"function"!=typeof a||(s=a&&a.then)}catch(p){return i(function(){u(e,!1,p)})(),e}if(o!==j&&a instanceof H&&a.hasOwnProperty(T)&&a.hasOwnProperty(w)&&a[T]!==z)l(a),u(e,a[T],a[w]);else if(o!==j&&"function"==typeof s)try{s.call(a,i(c(e,o)),i(c(e,!1)))}catch(p){i(function(){u(e,!1,p)})()}else{e[T]=o;var h=e[w];if(e[w]=a,e[E]===E&&o===O&&(e[T]=e[D],e[w]=e[S]),o===j&&a instanceof Error){var d=t.currentTask&&t.currentTask.data&&t.currentTask.data[_];d&&v(a,M,{configurable:!0,enumerable:!1,writable:!0,value:d})}for(var g=0;g 3) { + require('./build/test/test-env-setup-jasmine' + args[3]); + } + var JasmineRunner = require('jasmine'); var JasmineRunner = require('jasmine'); var jrunner = new JasmineRunner(); diff --git a/karma-base.conf.js b/karma-base.conf.js index 26ffa771a..0778ebe2e 100644 --- a/karma-base.conf.js +++ b/karma-base.conf.js @@ -29,7 +29,7 @@ module.exports = function (config) { require('karma-sourcemap-loader') ], - preprocessors: { + preprocessors: { '**/*.js': ['sourcemap'] }, diff --git a/karma-dist.conf.js b/karma-dist.conf.js index 73ee8a788..204225c4d 100644 --- a/karma-dist.conf.js +++ b/karma-dist.conf.js @@ -14,14 +14,12 @@ module.exports = function(config) { config.files.push('dist/zone.js'); config.files.push('dist/zone-patch-user-media.js'); config.files.push('dist/zone-patch-resize-observer.js'); - config.files.push('dist/async-test.js'); - config.files.push('dist/fake-async-test.js'); config.files.push('dist/long-stack-trace-zone.js'); config.files.push('dist/proxy.js'); config.files.push('dist/sync-test.js'); + config.files.push('dist/async-test.js'); + config.files.push('dist/fake-async-test.js'); config.files.push('dist/task-tracking.js'); - config.files.push('dist/zone-async-testing.js'); - config.files.push('dist/zone-fake-async.js'); config.files.push('dist/zone-patch-promise-test.js'); config.files.push('dist/wtf.js'); config.files.push('build/test/main.js'); diff --git a/lib/jasmine/jasmine.ts b/lib/jasmine/jasmine.ts index 1d4912460..4ff7762f7 100644 --- a/lib/jasmine/jasmine.ts +++ b/lib/jasmine/jasmine.ts @@ -39,6 +39,9 @@ const symbol = Zone.__symbol__; + // whether patch jasmine clock when in fakeAsync + const enableClockPatch = _global[symbol('fakeAsyncPatchLock')] === true; + // Monkey patch all of the jasmine DSL so that each function runs in appropriate zone. const jasmineEnv: any = jasmine.getEnv(); ['describe', 'xdescribe', 'fdescribe'].forEach(methodName => { @@ -64,41 +67,44 @@ return originalJasmineFn.apply(this, arguments); }; }); - const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']); - (jasmine as any)['clock'] = function() { - const clock = originalClockFn.apply(this, arguments); - const originalTick = (clock[symbol('tick')] = clock.tick); - clock.tick = function() { - const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); - if (fakeAsyncZoneSpec) { - return fakeAsyncZoneSpec.tick.apply(fakeAsyncZoneSpec, arguments); - } - return originalTick.apply(this, arguments); - }; - const originalMockDate = (clock[symbol('mockDate')] = clock.mockDate); - clock.mockDate = function() { - const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); - if (fakeAsyncZoneSpec) { - const dateTime = arguments[0]; - return fakeAsyncZoneSpec.setCurrentRealTime.apply( - fakeAsyncZoneSpec, - dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : arguments); - } - return originalMockDate.apply(this, arguments); - }; - ['install', 'uninstall'].forEach(methodName => { - const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]); - clock[methodName] = function() { - const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; - if (FakeAsyncTestZoneSpec) { - (jasmine as any)[symbol('clockInstalled')] = 'install' === methodName; - return; + if (enableClockPatch) { + const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']); + (jasmine as any)['clock'] = function() { + const clock = originalClockFn.apply(this, arguments); + const originalTick = (clock[symbol('tick')] = clock.tick); + clock.tick = function() { + const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (fakeAsyncZoneSpec) { + return fakeAsyncZoneSpec.tick.apply(fakeAsyncZoneSpec, arguments); } - return originalClockFn.apply(this, arguments); + return originalTick.apply(this, arguments); }; - }); - return clock; - }; + const originalMockDate = (clock[symbol('mockDate')] = clock.mockDate); + clock.mockDate = function() { + const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (fakeAsyncZoneSpec) { + const dateTime = arguments[0]; + return fakeAsyncZoneSpec.setCurrentRealTime.apply( + fakeAsyncZoneSpec, + dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : + arguments); + } + return originalMockDate.apply(this, arguments); + }; + ['install', 'uninstall'].forEach(methodName => { + const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]); + clock[methodName] = function() { + const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; + if (FakeAsyncTestZoneSpec) { + (jasmine as any)[symbol('clockInstalled')] = 'install' === methodName; + return; + } + return originalClockFn.apply(this, arguments); + }; + }); + return clock; + }; + } /** * Gets a function wrapping the body of a Jasmine `describe` block to execute in a @@ -115,29 +121,17 @@ const testProxyZoneSpec = queueRunner.testProxyZoneSpec; const testProxyZone = queueRunner.testProxyZone; let lastDelegate; - if (isClockInstalled) { - const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; - if (FakeAsyncTestZoneSpec) { - const _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); - lastDelegate = (testProxyZoneSpec as any).getDelegate(); - (testProxyZoneSpec as any).setDelegate(_fakeAsyncTestZoneSpec); - _fakeAsyncTestZoneSpec.lockDatePatch(); + if (isClockInstalled && enableClockPatch) { + // auto run a fakeAsync + const fakeAsyncModule = (Zone as any)[Zone.__symbol__('fakeAsyncTest')]; + if (fakeAsyncModule && typeof fakeAsyncModule.fakeAsync === 'function') { + testBody = fakeAsyncModule.fakeAsync(testBody); } } - try { - if (done) { - return testProxyZone.run(testBody, applyThis, [done]); - } else { - return testProxyZone.run(testBody, applyThis); - } - } finally { - if (isClockInstalled) { - const _fakeAsyncTestZoneSpec = testProxyZoneSpec.getDelegate(); - if (_fakeAsyncTestZoneSpec) { - _fakeAsyncTestZoneSpec.unlockDatePatch(); - } - (testProxyZoneSpec as any).setDelegate(lastDelegate); - } + if (done) { + return testProxyZone.run(testBody, applyThis, [done]); + } else { + return testProxyZone.run(testBody, applyThis); } } diff --git a/lib/testing/async-testing.ts b/lib/testing/async-testing.ts index e51ca365b..1e3c3ab4a 100644 --- a/lib/testing/async-testing.ts +++ b/lib/testing/async-testing.ts @@ -5,6 +5,7 @@ * 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 */ +import '../zone-spec/async-test'; Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate) => { /** @@ -79,6 +80,7 @@ Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate) // it's OK. proxyZoneSpec.setDelegate(previousDelegate); } + (testZoneSpec as any).unPatchPromiseForTest(); currentZone.run(() => { finishCallback(); }); @@ -89,12 +91,14 @@ Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate) // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. proxyZoneSpec.setDelegate(previousDelegate); } + (testZoneSpec as any).unPatchPromiseForTest(); currentZone.run(() => { failCallback(error); }); }, 'test'); proxyZoneSpec.setDelegate(testZoneSpec); + (testZoneSpec as any).patchPromiseForTest(); }); return Zone.current.runGuarded(fn, context); } diff --git a/lib/testing/fake-async.ts b/lib/testing/fake-async.ts index 948f80f88..72e934f02 100644 --- a/lib/testing/fake-async.ts +++ b/lib/testing/fake-async.ts @@ -5,6 +5,7 @@ * 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 */ +import '../zone-spec/fake-async-test'; Zone.__load_patch('fakeasync', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const FakeAsyncTestZoneSpec = Zone && (Zone as any)['FakeAsyncTestZoneSpec']; diff --git a/lib/testing/zone-testing.ts b/lib/testing/zone-testing.ts index ea88b7596..51218110e 100644 --- a/lib/testing/zone-testing.ts +++ b/lib/testing/zone-testing.ts @@ -13,6 +13,4 @@ import '../zone-spec/sync-test'; import '../jasmine/jasmine'; import '../zone-spec/async-test'; import '../zone-spec/fake-async-test'; -import './promise-testing'; -import './async-testing'; -import './fake-async'; \ No newline at end of file +import './promise-testing'; \ No newline at end of file diff --git a/lib/zone-spec/async-test.ts b/lib/zone-spec/async-test.ts index 31e178cb0..328585123 100644 --- a/lib/zone-spec/async-test.ts +++ b/lib/zone-spec/async-test.ts @@ -5,7 +5,8 @@ * 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 */ - +const _global: any = + typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; class AsyncTestZoneSpec implements ZoneSpec { static symbolParentUnresolved = Zone.__symbol__('parentUnresolved'); @@ -16,14 +17,23 @@ class AsyncTestZoneSpec implements ZoneSpec { runZone = Zone.current; unresolvedChainedPromiseCount = 0; + supportWaitUnresolvedChainedPromise = false; + constructor( private finishCallback: Function, private failCallback: Function, namePrefix: string) { this.name = 'asyncTestZone for ' + namePrefix; this.properties = {'AsyncTestZoneSpec': this}; + this.supportWaitUnresolvedChainedPromise = + _global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] === true; + } + + isUnresolvedChainedPromisePending() { + return this.unresolvedChainedPromiseCount > 0; } _finishCallbackIfDone() { - if (!(this._pendingMicroTasks || this._pendingMacroTasks)) { + if (!(this._pendingMicroTasks || this._pendingMacroTasks || + (this.supportWaitUnresolvedChainedPromise && this.isUnresolvedChainedPromisePending()))) { // We do this because we would like to catch unhandled rejected promises. this.runZone.run(() => { setTimeout(() => { @@ -36,6 +46,9 @@ class AsyncTestZoneSpec implements ZoneSpec { } patchPromiseForTest() { + if (!this.supportWaitUnresolvedChainedPromise) { + return; + } const patchPromiseForTest = (Promise as any)[Zone.__symbol__('patchPromiseForTest')]; if (patchPromiseForTest) { patchPromiseForTest(); @@ -43,6 +56,9 @@ class AsyncTestZoneSpec implements ZoneSpec { } unPatchPromiseForTest() { + if (!this.supportWaitUnresolvedChainedPromise) { + return; + } const unPatchPromiseForTest = (Promise as any)[Zone.__symbol__('unPatchPromiseForTest')]; if (unPatchPromiseForTest) { unPatchPromiseForTest(); diff --git a/test/browser-zone-setup.ts b/test/browser-zone-setup.ts index 334834acc..8b812dc1c 100644 --- a/test/browser-zone-setup.ts +++ b/test/browser-zone-setup.ts @@ -7,15 +7,12 @@ */ if (typeof window !== 'undefined') { (window as any)['__Zone_enable_cross_context_check'] = true; + (window as any)['__zone_symbol__fakeAsyncPatchLock'] = true; } import '../lib/common/to-string'; import '../lib/browser/browser'; import '../lib/browser/webapis-user-media'; -import '../lib/zone-spec/async-test'; -import '../lib/zone-spec/fake-async-test'; -import '../lib/zone-spec/long-stack-trace'; -import '../lib/zone-spec/proxy'; -import '../lib/zone-spec/sync-test'; +import '../lib/testing/zone-testing'; import '../lib/zone-spec/task-tracking'; import '../lib/zone-spec/wtf'; import '../lib/extra/cordova'; diff --git a/test/node_entry_point.ts b/test/node_entry_point.ts index b58ffc8c1..fd521eb92 100644 --- a/test/node_entry_point.ts +++ b/test/node_entry_point.ts @@ -7,19 +7,15 @@ */ // Must be loaded before zone loads, so that zone can detect WTF. +if (typeof global !== 'undefined' && + (global as any)['__zone_symbol__fakeAsyncPatchLock'] !== false) { + (global as any)['__zone_symbol__fakeAsyncPatchLock'] = true; +} import './wtf_mock'; import './test_fake_polyfill'; // Setup tests for Zone without microtask support -import '../lib/zone'; -import '../lib/common/promise'; -import '../lib/common/to-string'; -import '../lib/node/node'; -import '../lib/zone-spec/async-test'; -import '../lib/zone-spec/fake-async-test'; -import '../lib/zone-spec/long-stack-trace'; -import '../lib/zone-spec/proxy'; -import '../lib/zone-spec/sync-test'; +import '../lib/testing/zone-testing'; import '../lib/zone-spec/task-tracking'; import '../lib/zone-spec/wtf'; import '../lib/rxjs/rxjs'; diff --git a/test/test-env-setup-jasmine-no-patch-clock.ts b/test/test-env-setup-jasmine-no-patch-clock.ts new file mode 100644 index 000000000..8c06e92c1 --- /dev/null +++ b/test/test-env-setup-jasmine-no-patch-clock.ts @@ -0,0 +1,8 @@ +/** + * @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 as any)['__zone_symbol__fakeAsyncPatchLock'] = false; diff --git a/test/zone-spec/async-test.spec.ts b/test/zone-spec/async-test.spec.ts index b5aeb491e..71cc26fcc 100644 --- a/test/zone-spec/async-test.spec.ts +++ b/test/zone-spec/async-test.spec.ts @@ -332,10 +332,16 @@ describe('AsyncTestZoneSpec', function() { } describe('async', () => { - // TODO: @JiaLiPassion, get this feature back when all tests pass - // in angular - xdescribe('non zone aware async task in promise should be detected', () => { + describe('non zone aware async task in promise should be detected', () => { let finished = false; + const _global: any = + typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; + beforeEach(() => { + _global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] = true; + }); + afterEach(() => { + _global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] = false; + }); it('should be able to detect non zone aware async task in promise', wrapAsyncTest( () => { diff --git a/test/zone-spec/fake-async-test.spec.ts b/test/zone-spec/fake-async-test.spec.ts index 340245760..b64bda8fa 100644 --- a/test/zone-spec/fake-async-test.spec.ts +++ b/test/zone-spec/fake-async-test.spec.ts @@ -20,6 +20,13 @@ function supportNode() { (supportNode as any).message = 'support node'; +function supportClock() { + const _global: any = typeof window === 'undefined' ? global : window; + return typeof jasmine.clock === 'function' && _global['__zone_symbol__fakeAsyncPatchLock']; +} + +(supportClock as any).message = 'support patch clock'; + describe('FakeAsyncTestZoneSpec', () => { let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; let testZoneSpec: any; @@ -137,18 +144,18 @@ describe('FakeAsyncTestZoneSpec', () => { }); it('should run queued immediate timer on zero tick', ifEnvSupports('setImmediate', () => { - fakeAsyncTestZone.run(() => { - let ran = false; - setImmediate(() => { - ran = true; - }); + fakeAsyncTestZone.run(() => { + let ran = false; + setImmediate(() => { + ran = true; + }); - expect(ran).toEqual(false); + expect(ran).toEqual(false); - testZoneSpec.tick(); - expect(ran).toEqual(true); - }); - })); + testZoneSpec.tick(); + expect(ran).toEqual(true); + }); + })); it('should run queued timer after sufficient clock ticks', () => { fakeAsyncTestZone.run(() => { @@ -233,16 +240,16 @@ describe('FakeAsyncTestZoneSpec', () => { }); it('should pass arguments to setImmediate', ifEnvSupports('setImmediate', () => { - fakeAsyncTestZone.run(() => { - let value = 'genuine value'; - let id = setImmediate((arg1, arg2) => { - value = arg1 + arg2; - }, 'expected', ' value'); + fakeAsyncTestZone.run(() => { + let value = 'genuine value'; + let id = setImmediate((arg1, arg2) => { + value = arg1 + arg2; + }, 'expected', ' value'); - testZoneSpec.tick(); - expect(value).toEqual('expected value'); - }); - })); + testZoneSpec.tick(); + expect(value).toEqual('expected value'); + }); + })); it('should run periodic timers', () => { fakeAsyncTestZone.run(() => { @@ -909,12 +916,13 @@ describe('FakeAsyncTestZoneSpec', () => { }); describe( - 'fakeAsyncTest should patch jasmine.clock', + 'fakeAsyncTest should work without jasmine.clock', ifEnvSupports( () => { - return typeof jasmine.clock === 'function'; + return !supportClock() && supportNode(); }, () => { + const fakeAsync = (Zone as any)[Zone.__symbol__('fakeAsyncTest')].fakeAsync; beforeEach(() => { jasmine.clock().install(); }); @@ -923,19 +931,12 @@ describe('FakeAsyncTestZoneSpec', () => { jasmine.clock().uninstall(); }); - it('should check date type correctly', () => { + it('should check date type correctly', fakeAsync(() => { const d: any = new Date(); expect(d instanceof Date).toBe(true); - }); + })); - it('should get date diff correctly', () => { - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - }); - - it('should mock date correctly', () => { + it('should mock date correctly', fakeAsync(() => { const baseTime = new Date(2013, 9, 23); jasmine.clock().mockDate(baseTime); const start = Date.now(); @@ -944,9 +945,9 @@ describe('FakeAsyncTestZoneSpec', () => { const end = Date.now(); expect(end - start).toBe(100); expect(end).toBe(baseTime.getTime() + 100); - }); + })); - it('should handle new Date correctly', () => { + it('should handle new Date correctly', fakeAsync(() => { const baseTime = new Date(2013, 9, 23); jasmine.clock().mockDate(baseTime); const start = new Date(); @@ -955,36 +956,80 @@ describe('FakeAsyncTestZoneSpec', () => { const end = new Date(); expect(end.getTime() - start.getTime()).toBe(100); expect(end.getTime()).toBe(baseTime.getTime() + 100); - }); + })); })); - describe('fakeAsyncTest should patch rxjs scheduler', () => { - let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; - let testZoneSpec: any; - let fakeAsyncTestZone: Zone; + describe('fakeAsyncTest should patch jasmine.clock', ifEnvSupports(supportClock, () => { + beforeEach(() => { + jasmine.clock().install(); + }); - beforeEach(() => { - testZoneSpec = new FakeAsyncTestZoneSpec('name', false); - fakeAsyncTestZone = Zone.current.fork(testZoneSpec); - }); + afterEach(() => { + jasmine.clock().uninstall(); + }); - it('should get date diff correctly', (done) => { - fakeAsyncTestZone.run(() => { - let result = null; - const observable = new Observable((subscribe: any) => { - subscribe.next('hello'); - subscribe.complete(); - }); - observable.delay(1000).subscribe(v => { - result = v; - }); - expect(result).toBe(null); - testZoneSpec.tick(1000); - expect(result).toBe('hello'); - done(); - }); - }); - }); + it('should check date type correctly', () => { + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + }); + + it('should get date diff correctly', () => { + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + }); + + it('should mock date correctly', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = Date.now(); + expect(start).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + expect(end).toBe(baseTime.getTime() + 100); + }); + + it('should handle new Date correctly', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = new Date(); + expect(start.getTime()).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = new Date(); + expect(end.getTime() - start.getTime()).toBe(100); + expect(end.getTime()).toBe(baseTime.getTime() + 100); + }); + })); + + describe('fakeAsyncTest should patch rxjs scheduler', ifEnvSupports(supportClock, () => { + let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; + let testZoneSpec: any; + let fakeAsyncTestZone: Zone; + + beforeEach(() => { + testZoneSpec = new FakeAsyncTestZoneSpec('name', false); + fakeAsyncTestZone = Zone.current.fork(testZoneSpec); + }); + + it('should get date diff correctly', (done) => { + fakeAsyncTestZone.run(() => { + let result = null; + const observable = new Observable((subscribe: any) => { + subscribe.next('hello'); + subscribe.complete(); + }); + observable.delay(1000).subscribe(v => { + result = v; + }); + expect(result).toBe(null); + testZoneSpec.tick(1000); + expect(result).toBe('hello'); + done(); + }); + }); + })); }); class Log { @@ -1408,4 +1453,4 @@ const {fakeAsync, tick, discardPeriodicTasks, flush, flushMicrotasks} = fakeAsyn expect(state).toEqual('works'); }); }); -} \ No newline at end of file +}