@ -19,12 +19,24 @@ class BaseError extends Error {
|
||||
this._nativeError = nativeError;
|
||||
}
|
||||
|
||||
get message() { return this._nativeError.message; }
|
||||
set message(message) { this._nativeError.message = message; }
|
||||
get name() { return this._nativeError.name; }
|
||||
get stack() { return (this._nativeError as any).stack; }
|
||||
set stack(value) { (this._nativeError as any).stack = value; }
|
||||
toString() { return this._nativeError.toString(); }
|
||||
get message() {
|
||||
return this._nativeError.message;
|
||||
}
|
||||
set message(message) {
|
||||
this._nativeError.message = message;
|
||||
}
|
||||
get name() {
|
||||
return this._nativeError.name;
|
||||
}
|
||||
get stack() {
|
||||
return (this._nativeError as any).stack;
|
||||
}
|
||||
set stack(value) {
|
||||
(this._nativeError as any).stack = value;
|
||||
}
|
||||
toString() {
|
||||
return this._nativeError.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class WrappedError extends BaseError {
|
||||
@ -46,7 +58,9 @@ class TestError extends WrappedError {
|
||||
super(`${message} caused by: ${error instanceof Error ? error.message : error}`, error);
|
||||
}
|
||||
|
||||
get message() { return 'test ' + this.originalError.message; }
|
||||
get message() {
|
||||
return 'test ' + this.originalError.message;
|
||||
}
|
||||
}
|
||||
|
||||
class TestMessageError extends WrappedError {
|
||||
@ -54,9 +68,13 @@ class TestMessageError extends WrappedError {
|
||||
super(`${message} caused by: ${error instanceof Error ? error.message : error}`, error);
|
||||
}
|
||||
|
||||
get message() { return 'test ' + this.originalError.message; }
|
||||
get message() {
|
||||
return 'test ' + this.originalError.message;
|
||||
}
|
||||
|
||||
set message(value) { this.originalError.message = value; }
|
||||
set message(value) {
|
||||
this.originalError.message = value;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ZoneAwareError', () => {
|
||||
@ -153,9 +171,11 @@ describe('ZoneAwareError', () => {
|
||||
it('should copy customized NativeError properties to ZoneAwareError', () => {
|
||||
const spy = jasmine.createSpy('errorCustomFunction');
|
||||
const NativeError = (global as any)[(Zone as any).__symbol__('Error')];
|
||||
NativeError.customFunction = function(args: any) { spy(args); };
|
||||
NativeError.customFunction = function(args: any) {
|
||||
spy(args);
|
||||
};
|
||||
expect((Error as any)['customProperty']).toBe('customProperty');
|
||||
expect(typeof(Error as any)['customFunction']).toBe('function');
|
||||
expect(typeof (Error as any)['customFunction']).toBe('function');
|
||||
(Error as any)['customFunction']('test');
|
||||
expect(spy).toHaveBeenCalledWith('test');
|
||||
});
|
||||
@ -166,8 +186,8 @@ describe('ZoneAwareError', () => {
|
||||
// there event without throw
|
||||
const error = new Error('test');
|
||||
const errorWithoutNew = Error('test');
|
||||
expect(error.stack !.split('\n').length > 0).toBeTruthy();
|
||||
expect(errorWithoutNew.stack !.split('\n').length > 0).toBeTruthy();
|
||||
expect(error.stack!.split('\n').length > 0).toBeTruthy();
|
||||
expect(errorWithoutNew.stack!.split('\n').length > 0).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show zone names in stack frames and remove extra frames', () => {
|
||||
@ -218,14 +238,14 @@ describe('ZoneAwareError', () => {
|
||||
|
||||
expect(outside.stack).toEqual(outside.zoneAwareStack);
|
||||
expect(outsideWithoutNew.stack).toEqual(outsideWithoutNew.zoneAwareStack);
|
||||
expect(inside !.stack).toEqual(inside !.zoneAwareStack);
|
||||
expect(insideWithoutNew !.stack).toEqual(insideWithoutNew !.zoneAwareStack);
|
||||
expect(typeof inside !.originalStack).toEqual('string');
|
||||
expect(typeof insideWithoutNew !.originalStack).toEqual('string');
|
||||
const outsideFrames = outside.stack !.split(/\n/);
|
||||
const insideFrames = inside !.stack !.split(/\n/);
|
||||
const outsideWithoutNewFrames = outsideWithoutNew !.stack !.split(/\n/);
|
||||
const insideWithoutNewFrames = insideWithoutNew !.stack !.split(/\n/);
|
||||
expect(inside!.stack).toEqual(inside!.zoneAwareStack);
|
||||
expect(insideWithoutNew!.stack).toEqual(insideWithoutNew!.zoneAwareStack);
|
||||
expect(typeof inside!.originalStack).toEqual('string');
|
||||
expect(typeof insideWithoutNew!.originalStack).toEqual('string');
|
||||
const outsideFrames = outside.stack!.split(/\n/);
|
||||
const insideFrames = inside!.stack!.split(/\n/);
|
||||
const outsideWithoutNewFrames = outsideWithoutNew!.stack!.split(/\n/);
|
||||
const insideWithoutNewFrames = insideWithoutNew!.stack!.split(/\n/);
|
||||
|
||||
// throw away first line if it contains the error
|
||||
if (/Outside/.test(outsideFrames[0])) {
|
||||
@ -304,7 +324,9 @@ describe('ZoneAwareError', () => {
|
||||
onHandleError:
|
||||
(parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => {
|
||||
assertStackDoesNotContainZoneFrames(error);
|
||||
setTimeout(() => { errorZoneSpec.done && errorZoneSpec.done(); }, 0);
|
||||
setTimeout(() => {
|
||||
errorZoneSpec.done && errorZoneSpec.done();
|
||||
}, 0);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@ -320,17 +342,26 @@ describe('ZoneAwareError', () => {
|
||||
|
||||
describe('Error stack', () => {
|
||||
it('Error with new which occurs in setTimeout callback should not have zone frames visible',
|
||||
assertStackDoesNotContainZoneFramesTest(
|
||||
() => { setTimeout(() => { throw new Error('timeout test error'); }, 10); }));
|
||||
assertStackDoesNotContainZoneFramesTest(() => {
|
||||
setTimeout(() => {
|
||||
throw new Error('timeout test error');
|
||||
}, 10);
|
||||
}));
|
||||
|
||||
it('Error without new which occurs in setTimeout callback should not have zone frames visible',
|
||||
assertStackDoesNotContainZoneFramesTest(
|
||||
() => { setTimeout(() => { throw Error('test error'); }, 10); }));
|
||||
assertStackDoesNotContainZoneFramesTest(() => {
|
||||
setTimeout(() => {
|
||||
throw Error('test error');
|
||||
}, 10);
|
||||
}));
|
||||
|
||||
it('Error with new which cause by promise rejection should not have zone frames visible',
|
||||
(done) => {
|
||||
const p = new Promise(
|
||||
(resolve, reject) => { setTimeout(() => { reject(new Error('test error')); }); });
|
||||
const p = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error('test error'));
|
||||
});
|
||||
});
|
||||
p.catch(err => {
|
||||
assertStackDoesNotContainZoneFrames(err);
|
||||
done();
|
||||
@ -339,8 +370,11 @@ describe('ZoneAwareError', () => {
|
||||
|
||||
it('Error without new which cause by promise rejection should not have zone frames visible',
|
||||
(done) => {
|
||||
const p = new Promise(
|
||||
(resolve, reject) => { setTimeout(() => { reject(Error('test error')); }); });
|
||||
const p = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(Error('test error'));
|
||||
});
|
||||
});
|
||||
p.catch(err => {
|
||||
assertStackDoesNotContainZoneFrames(err);
|
||||
done();
|
||||
@ -357,8 +391,9 @@ describe('ZoneAwareError', () => {
|
||||
|
||||
it('Error without new which occurs in eventTask callback should not have zone frames visible',
|
||||
assertStackDoesNotContainZoneFramesTest(() => {
|
||||
const task = Zone.current.scheduleEventTask(
|
||||
'errorEvent', () => { throw Error('test error'); }, undefined, () => null, undefined);
|
||||
const task = Zone.current.scheduleEventTask('errorEvent', () => {
|
||||
throw Error('test error');
|
||||
}, undefined, () => null, undefined);
|
||||
task.invoke();
|
||||
}));
|
||||
|
||||
|
@ -19,7 +19,7 @@ class MicroTaskQueueZoneSpec implements ZoneSpec {
|
||||
flush() {
|
||||
while (this.queue.length) {
|
||||
const task = this.queue.shift();
|
||||
task !.invoke();
|
||||
task!.invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,11 +50,12 @@ describe(
|
||||
|
||||
pZone = Zone.current.fork({
|
||||
name: 'promise-zone',
|
||||
onScheduleTask: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
task: Task): any => {
|
||||
log.push('scheduleTask');
|
||||
parentZoneDelegate.scheduleTask(targetZone, task);
|
||||
}
|
||||
onScheduleTask:
|
||||
(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task):
|
||||
any => {
|
||||
log.push('scheduleTask');
|
||||
parentZoneDelegate.scheduleTask(targetZone, task);
|
||||
}
|
||||
});
|
||||
|
||||
queueZone = Zone.current.fork(new MicroTaskQueueZoneSpec());
|
||||
@ -77,7 +78,9 @@ describe(
|
||||
expect(value).toBe(0);
|
||||
done();
|
||||
})
|
||||
.catch(error => { fail(error); });
|
||||
.catch(error => {
|
||||
fail(error);
|
||||
});
|
||||
} finally {
|
||||
global['Promise'] = NativePromise;
|
||||
Zone.assertZonePatched();
|
||||
@ -85,8 +88,9 @@ describe(
|
||||
}
|
||||
});
|
||||
|
||||
it('should pretend to be a native code',
|
||||
() => { expect(String(Promise).indexOf('[native code]') >= 0).toBe(true); });
|
||||
it('should pretend to be a native code', () => {
|
||||
expect(String(Promise).indexOf('[native code]') >= 0).toBe(true);
|
||||
});
|
||||
|
||||
it('should use native toString for promise instance', () => {
|
||||
expect(Object.prototype.toString.call(Promise.resolve())).toEqual('[object Promise]');
|
||||
@ -105,16 +109,22 @@ describe(
|
||||
|
||||
it('should allow subclassing without Symbol.species', () => {
|
||||
class MyPromise extends Promise<any> {
|
||||
constructor(fn: any) { super(fn); }
|
||||
constructor(fn: any) {
|
||||
super(fn);
|
||||
}
|
||||
}
|
||||
expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true);
|
||||
});
|
||||
|
||||
it('should allow subclassing with Symbol.species', () => {
|
||||
class MyPromise extends Promise<any> {
|
||||
constructor(fn: any) { super(fn); }
|
||||
constructor(fn: any) {
|
||||
super(fn);
|
||||
}
|
||||
|
||||
static get[Symbol.species]() { return MyPromise; }
|
||||
static get[Symbol.species]() {
|
||||
return MyPromise;
|
||||
}
|
||||
}
|
||||
expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true);
|
||||
});
|
||||
@ -122,15 +132,18 @@ describe(
|
||||
it('Symbol.species should return ZoneAwarePromise', () => {
|
||||
const empty = function() {};
|
||||
const promise = Promise.resolve(1);
|
||||
const FakePromise = ((promise.constructor = {} as any) as any)[Symbol.species] = function(
|
||||
exec: any) { exec(empty, empty); };
|
||||
const FakePromise =
|
||||
((promise.constructor = {} as any) as any)[Symbol.species] = function(exec: any) {
|
||||
exec(empty, empty);
|
||||
};
|
||||
expect(promise.then(empty) instanceof FakePromise).toBe(true);
|
||||
});
|
||||
|
||||
it('should intercept scheduling of resolution and then', (done) => {
|
||||
pZone.run(() => {
|
||||
let p: Promise<any> =
|
||||
new Promise(function(resolve, reject) { expect(resolve('RValue')).toBe(undefined); });
|
||||
let p: Promise<any> = new Promise(function(resolve, reject) {
|
||||
expect(resolve('RValue')).toBe(undefined);
|
||||
});
|
||||
expect(log).toEqual([]);
|
||||
expect(p instanceof Promise).toBe(true);
|
||||
p = p.then((v) => {
|
||||
@ -155,12 +168,16 @@ describe(
|
||||
queueZone.run(() => {
|
||||
const flush = Zone.current.get('flush');
|
||||
const queue = Zone.current.get('queue');
|
||||
const p = new Promise<string>(function(resolve, reject) { resolve('RValue'); })
|
||||
const p = new Promise<string>(function(resolve, reject) {
|
||||
resolve('RValue');
|
||||
})
|
||||
.then((v: string) => {
|
||||
log.push(v);
|
||||
return 'second value';
|
||||
})
|
||||
.then((v: string) => { log.push(v); });
|
||||
.then((v: string) => {
|
||||
log.push(v);
|
||||
});
|
||||
expect(queue.length).toEqual(1);
|
||||
expect(log).toEqual([]);
|
||||
flush();
|
||||
@ -172,13 +189,16 @@ describe(
|
||||
queueZone.run(() => {
|
||||
const flush = Zone.current.get('flush');
|
||||
const queue = Zone.current.get('queue');
|
||||
const p =
|
||||
new Promise<string>(function(resolve, reject) { resolve(Promise.resolve('RValue')); })
|
||||
.then((v: string) => {
|
||||
log.push(v);
|
||||
return Promise.resolve('second value');
|
||||
})
|
||||
.then((v: string) => { log.push(v); });
|
||||
const p = new Promise<string>(function(resolve, reject) {
|
||||
resolve(Promise.resolve('RValue'));
|
||||
})
|
||||
.then((v: string) => {
|
||||
log.push(v);
|
||||
return Promise.resolve('second value');
|
||||
})
|
||||
.then((v: string) => {
|
||||
log.push(v);
|
||||
});
|
||||
expect(queue.length).toEqual(1);
|
||||
expect(log).toEqual([]);
|
||||
flush();
|
||||
@ -191,55 +211,65 @@ describe(
|
||||
let resolve: Function|null = null;
|
||||
|
||||
testZone.run(function() {
|
||||
new Promise(function(resolveFn) { resolve = resolveFn; }).then(function() {
|
||||
new Promise(function(resolveFn) {
|
||||
resolve = resolveFn;
|
||||
}).then(function() {
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
resolve !();
|
||||
resolve!();
|
||||
});
|
||||
|
||||
it('should work with .catch', function(done) {
|
||||
let reject: (() => void)|null = null;
|
||||
|
||||
testZone.run(function() {
|
||||
new Promise(function(resolveFn, rejectFn) { reject = rejectFn; })['catch'](function() {
|
||||
new Promise(function(resolveFn, rejectFn) {
|
||||
reject = rejectFn;
|
||||
})['catch'](function() {
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
expect(reject !()).toBe(undefined);
|
||||
expect(reject!()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should work with .finally with resolved promise', function(done) {
|
||||
let resolve: Function|null = null;
|
||||
|
||||
testZone.run(function() {
|
||||
(new Promise(function(resolveFn) { resolve = resolveFn; }) as any).finally(function() {
|
||||
expect(arguments.length).toBe(0);
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
(new Promise(function(resolveFn) {
|
||||
resolve = resolveFn;
|
||||
}) as any)
|
||||
.finally(function() {
|
||||
expect(arguments.length).toBe(0);
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
resolve !('value');
|
||||
resolve!('value');
|
||||
});
|
||||
|
||||
it('should work with .finally with rejected promise', function(done) {
|
||||
let reject: Function|null = null;
|
||||
|
||||
testZone.run(function() {
|
||||
(new Promise(function(_, rejectFn) { reject = rejectFn; }) as any).finally(function() {
|
||||
expect(arguments.length).toBe(0);
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
(new Promise(function(_, rejectFn) {
|
||||
reject = rejectFn;
|
||||
}) as any)
|
||||
.finally(function() {
|
||||
expect(arguments.length).toBe(0);
|
||||
expect(Zone.current).toBe(testZone);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
reject !('error');
|
||||
reject!('error');
|
||||
});
|
||||
|
||||
it('should work with Promise.resolve', () => {
|
||||
@ -275,8 +305,9 @@ describe(
|
||||
it('should re-reject promise', () => {
|
||||
queueZone.run(() => {
|
||||
let value: any = null;
|
||||
Promise.reject('rejectReason')['catch']((v) => { throw v; })['catch'](
|
||||
(v) => value = v);
|
||||
Promise.reject('rejectReason')['catch']((v) => {
|
||||
throw v;
|
||||
})['catch']((v) => value = v);
|
||||
flushMicrotasks();
|
||||
expect(value).toEqual('rejectReason');
|
||||
});
|
||||
@ -308,7 +339,9 @@ describe(
|
||||
(Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = false;
|
||||
const originalConsoleError = console.error;
|
||||
console.error = jasmine.createSpy('consoleErr');
|
||||
const p = new Promise((resolve, reject) => { throw new Error('promise error'); });
|
||||
const p = new Promise((resolve, reject) => {
|
||||
throw new Error('promise error');
|
||||
});
|
||||
setTimeout(() => {
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
console.error = originalConsoleError;
|
||||
@ -323,7 +356,9 @@ describe(
|
||||
(Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = true;
|
||||
const originalConsoleError = console.error;
|
||||
console.error = jasmine.createSpy('consoleErr');
|
||||
const p = new Promise((resolve, reject) => { throw new Error('promise error'); });
|
||||
const p = new Promise((resolve, reject) => {
|
||||
throw new Error('promise error');
|
||||
});
|
||||
setTimeout(() => {
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
console.error = originalConsoleError;
|
||||
@ -342,11 +377,11 @@ describe(
|
||||
.fork({
|
||||
name: 'promise-error',
|
||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.run(() => {
|
||||
zone = Zone.current;
|
||||
@ -362,10 +397,10 @@ describe(
|
||||
});
|
||||
setTimeout((): any => null);
|
||||
setTimeout(() => {
|
||||
expect(promiseError !.message)
|
||||
expect(promiseError!.message)
|
||||
.toBe(
|
||||
'Uncaught (in promise): ' + error +
|
||||
(error !.stack ? '\n' + error !.stack : ''));
|
||||
(error!.stack ? '\n' + error!.stack : ''));
|
||||
expect((promiseError as any)['rejection']).toBe(error);
|
||||
expect((promiseError as any)['zone']).toBe(zone);
|
||||
expect((promiseError as any)['task']).toBe(task);
|
||||
@ -382,11 +417,11 @@ describe(
|
||||
.fork({
|
||||
name: 'promise-error',
|
||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.run(() => {
|
||||
zone = Zone.current;
|
||||
@ -399,7 +434,7 @@ describe(
|
||||
});
|
||||
setTimeout((): any => null);
|
||||
setTimeout(() => {
|
||||
expect(promiseError !.message)
|
||||
expect(promiseError!.message)
|
||||
.toMatch(/Uncaught \(in promise\):.*: {"prop1":"value1","prop2":"value2"}/);
|
||||
done();
|
||||
});
|
||||
@ -456,8 +491,16 @@ describe(
|
||||
it('should resolve with the sync then operation', () => {
|
||||
queueZone.run(() => {
|
||||
let value: any = null;
|
||||
const p1 = {then: function(thenCallback: Function) { return thenCallback('p1'); }};
|
||||
const p2 = {then: function(thenCallback: Function) { return thenCallback('p2'); }};
|
||||
const p1 = {
|
||||
then: function(thenCallback: Function) {
|
||||
return thenCallback('p1');
|
||||
}
|
||||
};
|
||||
const p2 = {
|
||||
then: function(thenCallback: Function) {
|
||||
return thenCallback('p2');
|
||||
}
|
||||
};
|
||||
Promise.all([p1, 'v1', p2]).then((v: any) => value = v);
|
||||
// expect(Zone.current.get('queue').length).toEqual(2);
|
||||
flushMicrotasks();
|
||||
@ -467,16 +510,20 @@ describe(
|
||||
|
||||
it('should resolve generators',
|
||||
ifEnvSupports(
|
||||
() => { return isNode; },
|
||||
() => {
|
||||
const generators: any = function* () {
|
||||
return isNode;
|
||||
},
|
||||
() => {
|
||||
const generators: any = function*() {
|
||||
yield Promise.resolve(1);
|
||||
yield Promise.resolve(2);
|
||||
return;
|
||||
};
|
||||
queueZone.run(() => {
|
||||
let value: any = null;
|
||||
Promise.all(generators()).then(val => { value = val; });
|
||||
Promise.all(generators()).then(val => {
|
||||
value = val;
|
||||
});
|
||||
// expect(Zone.current.get('queue').length).toEqual(2);
|
||||
flushMicrotasks();
|
||||
expect(value).toEqual([1, 2]);
|
||||
@ -488,7 +535,9 @@ describe(
|
||||
describe('Promise subclasses', function() {
|
||||
class MyPromise<T> {
|
||||
private _promise: Promise<any>;
|
||||
constructor(init: any) { this._promise = new Promise(init); }
|
||||
constructor(init: any) {
|
||||
this._promise = new Promise(init);
|
||||
}
|
||||
|
||||
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>)|
|
||||
undefined|null): Promise<T|TResult> {
|
||||
@ -511,29 +560,43 @@ describe(
|
||||
setPrototypeOf(MyPromise.prototype, Promise.prototype);
|
||||
|
||||
it('should reject if the Promise subclass rejects', function() {
|
||||
const myPromise =
|
||||
new MyPromise(function(resolve: any, reject: any): void { reject('foo'); });
|
||||
const myPromise = new MyPromise(function(resolve: any, reject: any): void {
|
||||
reject('foo');
|
||||
});
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function() { return myPromise; })
|
||||
.then(function() {
|
||||
return myPromise;
|
||||
})
|
||||
.then(
|
||||
function() { throw new Error('Unexpected resolution'); },
|
||||
function(result) { expect(result).toBe('foo'); });
|
||||
function() {
|
||||
throw new Error('Unexpected resolution');
|
||||
},
|
||||
function(result) {
|
||||
expect(result).toBe('foo');
|
||||
});
|
||||
});
|
||||
|
||||
function testPromiseSubClass(done?: Function) {
|
||||
const myPromise =
|
||||
new MyPromise(function(resolve: any, reject: Function) { resolve('foo'); });
|
||||
|
||||
return Promise.resolve().then(function() { return myPromise; }).then(function(result) {
|
||||
expect(result).toBe('foo');
|
||||
done && done();
|
||||
const myPromise = new MyPromise(function(resolve: any, reject: Function) {
|
||||
resolve('foo');
|
||||
});
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function() {
|
||||
return myPromise;
|
||||
})
|
||||
.then(function(result) {
|
||||
expect(result).toBe('foo');
|
||||
done && done();
|
||||
});
|
||||
}
|
||||
|
||||
it('should resolve if the Promise subclass resolves', jasmine ? function(done) {
|
||||
testPromiseSubClass(done);
|
||||
} : function() { testPromiseSubClass(); });
|
||||
} : function() {
|
||||
testPromiseSubClass();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Promise.allSettled', () => {
|
||||
@ -589,9 +652,13 @@ describe(
|
||||
});
|
||||
it('poisoned .then', (done: DoneFn) => {
|
||||
const promise = new Promise(function() {});
|
||||
promise.then = function() { throw new EvalError(); };
|
||||
promise.then = function() {
|
||||
throw new EvalError();
|
||||
};
|
||||
allSettled([promise]).then(
|
||||
() => { fail('should not reach here'); },
|
||||
() => {
|
||||
fail('should not reach here');
|
||||
},
|
||||
(reason: any) => {
|
||||
expect(reason instanceof EvalError).toBe(true);
|
||||
done();
|
||||
|
@ -12,7 +12,9 @@ declare const global: any;
|
||||
describe(
|
||||
'fetch', ifEnvSupports('fetch', function() {
|
||||
let testZone: Zone;
|
||||
beforeEach(() => { testZone = Zone.current.fork({name: 'TestZone'}); });
|
||||
beforeEach(() => {
|
||||
testZone = Zone.current.fork({name: 'TestZone'});
|
||||
});
|
||||
it('should work for text response', function(done) {
|
||||
testZone.run(function() {
|
||||
global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json')
|
||||
@ -92,7 +94,9 @@ describe(
|
||||
testZone.run(function() {
|
||||
global['fetch']('http://user:password@example.com')
|
||||
.then(
|
||||
function(response: any) { fail('should not success'); },
|
||||
function(response: any) {
|
||||
fail('should not success');
|
||||
},
|
||||
(error: any) => {
|
||||
expect(Zone.current.name).toEqual(testZone.name);
|
||||
expect(error.constructor.name).toEqual('TypeError');
|
||||
@ -118,13 +122,14 @@ describe(
|
||||
}
|
||||
return delegate.scheduleTask(target, task);
|
||||
},
|
||||
onInvokeTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task,
|
||||
applyThis: any, applyArgs: any) => {
|
||||
if (task.type !== 'eventTask') {
|
||||
logs.push(`invokeTask:${task.source}:${task.type}`);
|
||||
}
|
||||
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
||||
},
|
||||
onInvokeTask:
|
||||
(delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task, applyThis: any,
|
||||
applyArgs: any) => {
|
||||
if (task.type !== 'eventTask') {
|
||||
logs.push(`invokeTask:${task.source}:${task.type}`);
|
||||
}
|
||||
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
||||
},
|
||||
onCancelTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => {
|
||||
if (task.type !== 'eventTask') {
|
||||
logs.push(`cancelTask:${task.source}:${task.type}`);
|
||||
@ -160,7 +165,9 @@ describe(
|
||||
const abort = new AbortController();
|
||||
const signal = abort.signal;
|
||||
global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal})
|
||||
.then(function(response: any) { fail('should not get response'); })
|
||||
.then(function(response: any) {
|
||||
fail('should not get response');
|
||||
})
|
||||
.catch(function(error: any) {
|
||||
expect(error.name).toEqual('AbortError');
|
||||
expect(logs).toEqual([
|
||||
@ -187,7 +194,9 @@ describe(
|
||||
const abort = new AbortController();
|
||||
const signal = abort.signal;
|
||||
global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal})
|
||||
.then(function(response: any) { fail('should not get response'); })
|
||||
.then(function(response: any) {
|
||||
fail('should not get response');
|
||||
})
|
||||
.catch(function(error: any) {
|
||||
expect(error.name).toEqual('AbortError');
|
||||
expect(logs).toEqual([
|
||||
|
@ -9,7 +9,9 @@
|
||||
describe('Microtasks', function() {
|
||||
if (!global.Promise) return;
|
||||
|
||||
function scheduleFn(task: Task) { Promise.resolve().then(<any>task.invoke); }
|
||||
function scheduleFn(task: Task) {
|
||||
Promise.resolve().then(<any>task.invoke);
|
||||
}
|
||||
|
||||
it('should execute microtasks enqueued in the root zone', function(done) {
|
||||
const log: number[] = [];
|
||||
@ -35,7 +37,9 @@ describe('Microtasks', function() {
|
||||
log.push('-mat1');
|
||||
}, 10);
|
||||
|
||||
setTimeout(function() { log.push('mat2'); }, 30);
|
||||
setTimeout(function() {
|
||||
log.push('mat2');
|
||||
}, 30);
|
||||
|
||||
setTimeout(function() {
|
||||
expect(log).toEqual(['+root', '-root', 'root.mit', '+mat1', '-mat1', 'mat1.mit', 'mat2']);
|
||||
@ -62,7 +66,9 @@ describe('Microtasks', function() {
|
||||
'in different zone.',
|
||||
function(done) {
|
||||
let resolve: Function;
|
||||
const promise = new Promise(function(rs) { resolve = rs; });
|
||||
const promise = new Promise(function(rs) {
|
||||
resolve = rs;
|
||||
});
|
||||
|
||||
const testZone = Zone.current.fork({name: 'test'});
|
||||
|
||||
@ -73,7 +79,9 @@ describe('Microtasks', function() {
|
||||
});
|
||||
});
|
||||
|
||||
Zone.current.fork({name: 'test'}).run(function() { resolve(null); });
|
||||
Zone.current.fork({name: 'test'}).run(function() {
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Promise', function() {
|
||||
|
@ -21,11 +21,11 @@ describe('disable wrap uncaught promise rejection', () => {
|
||||
.fork({
|
||||
name: 'promise-error',
|
||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.run(() => {
|
||||
zone = Zone.current;
|
||||
@ -56,11 +56,11 @@ describe('disable wrap uncaught promise rejection', () => {
|
||||
.fork({
|
||||
name: 'promise-error',
|
||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.run(() => {
|
||||
rejectObj = new TestRejection();
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
const noop = function() {};
|
||||
let log: {zone: string, taskZone: undefined | string, toState: TaskState, fromState: TaskState}[] =
|
||||
let log: {zone: string, taskZone: undefined|string, toState: TaskState, fromState: TaskState}[] =
|
||||
[];
|
||||
const detectTask = Zone.current.scheduleMacroTask('detectTask', noop, undefined, noop, noop);
|
||||
const originalTransitionTo = detectTask.constructor.prototype._transitionTo;
|
||||
@ -34,14 +34,18 @@ function testFnWithLoggedTransitionTo(testFn: Function) {
|
||||
|
||||
describe('task lifecycle', () => {
|
||||
describe('event task lifecycle', () => {
|
||||
beforeEach(() => { log = []; });
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
});
|
||||
|
||||
it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testEventTaskZone'}).run(() => {
|
||||
Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -63,7 +67,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'unknown', fromState: 'scheduling'}
|
||||
@ -77,7 +83,9 @@ describe('task lifecycle', () => {
|
||||
Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -93,7 +101,9 @@ describe('task lifecycle', () => {
|
||||
Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop);
|
||||
Zone.current.cancelTask(task);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -105,11 +115,14 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testEventTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleEventTask(
|
||||
'testEventTask', () => { Zone.current.cancelTask(task); }, undefined, noop, noop);
|
||||
const task = Zone.current.scheduleEventTask('testEventTask', () => {
|
||||
Zone.current.cancelTask(task);
|
||||
}, undefined, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -122,14 +135,17 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from running to scheduled when task.callback throw error',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testEventTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleEventTask(
|
||||
'testEventTask', () => { throw Error('invoke error'); }, undefined, noop, noop);
|
||||
const task = Zone.current.scheduleEventTask('testEventTask', () => {
|
||||
throw Error('invoke error');
|
||||
}, undefined, noop, noop);
|
||||
try {
|
||||
task.invoke();
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -141,14 +157,18 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testEventTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleEventTask(
|
||||
'testEventTask', noop, undefined, noop, () => { throw Error('cancel task'); });
|
||||
const task =
|
||||
Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -160,14 +180,18 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testEventTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleEventTask(
|
||||
'testEventTask', noop, undefined, noop, () => { throw Error('cancel task'); });
|
||||
const task =
|
||||
Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -191,7 +215,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -218,7 +244,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -229,14 +257,18 @@ describe('task lifecycle', () => {
|
||||
});
|
||||
|
||||
describe('non periodical macroTask lifecycle', () => {
|
||||
beforeEach(() => { log = []; });
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
});
|
||||
|
||||
it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMacroTaskZone'}).run(() => {
|
||||
Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -258,7 +290,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'unknown', fromState: 'scheduling'}
|
||||
@ -272,7 +306,9 @@ describe('task lifecycle', () => {
|
||||
Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -288,7 +324,9 @@ describe('task lifecycle', () => {
|
||||
Zone.current.scheduleMacroTask('testMacrotask', noop, undefined, noop, noop);
|
||||
Zone.current.cancelTask(task);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -300,11 +338,14 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMacroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMacroTask(
|
||||
'testMacroTask', () => { Zone.current.cancelTask(task); }, undefined, noop, noop);
|
||||
const task = Zone.current.scheduleMacroTask('testMacroTask', () => {
|
||||
Zone.current.cancelTask(task);
|
||||
}, undefined, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -317,14 +358,17 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from running to noScheduled when task.callback throw error',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMacroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMacroTask(
|
||||
'testMacroTask', () => { throw Error('invoke error'); }, undefined, noop, noop);
|
||||
const task = Zone.current.scheduleMacroTask('testMacroTask', () => {
|
||||
throw Error('invoke error');
|
||||
}, undefined, noop, noop);
|
||||
try {
|
||||
task.invoke();
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -336,14 +380,18 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMacroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMacroTask(
|
||||
'testMacroTask', noop, undefined, noop, () => { throw Error('cancel task'); });
|
||||
const task =
|
||||
Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -355,14 +403,18 @@ describe('task lifecycle', () => {
|
||||
it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMacroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMacroTask(
|
||||
'testMacroTask', noop, undefined, noop, () => { throw Error('cancel task'); });
|
||||
const task =
|
||||
Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -386,7 +438,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -413,7 +467,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -442,7 +498,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -469,7 +527,9 @@ describe('task lifecycle', () => {
|
||||
task = Zone.current.scheduleMacroTask(
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -492,7 +552,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'unknown', fromState: 'scheduling'}
|
||||
@ -506,7 +568,9 @@ describe('task lifecycle', () => {
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -522,7 +586,9 @@ describe('task lifecycle', () => {
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop);
|
||||
Zone.current.cancelTask(task);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -535,11 +601,13 @@ describe('task lifecycle', () => {
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => {
|
||||
task = Zone.current.scheduleMacroTask('testPeriodicalTask', () => {
|
||||
Zone.current.cancelTask(task !);
|
||||
Zone.current.cancelTask(task!);
|
||||
}, {isPeriodic: true}, noop, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -560,7 +628,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -573,14 +643,17 @@ describe('task lifecycle', () => {
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => {
|
||||
task = Zone.current.scheduleMacroTask(
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop,
|
||||
() => { throw Error('cancel task'); });
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -593,14 +666,17 @@ describe('task lifecycle', () => {
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => {
|
||||
task = Zone.current.scheduleMacroTask(
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop,
|
||||
() => { throw Error('cancel task'); });
|
||||
'testPeriodicalTask', noop, {isPeriodic: true}, noop, () => {
|
||||
throw Error('cancel task');
|
||||
});
|
||||
try {
|
||||
Zone.current.cancelTask(task);
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -625,7 +701,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -651,7 +729,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -662,14 +742,18 @@ describe('task lifecycle', () => {
|
||||
});
|
||||
|
||||
describe('microTask lifecycle', () => {
|
||||
beforeEach(() => { log = []; });
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
});
|
||||
|
||||
it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMicroTaskZone'}).run(() => {
|
||||
Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop);
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -691,7 +775,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'unknown', fromState: 'scheduling'}
|
||||
@ -704,7 +790,9 @@ describe('task lifecycle', () => {
|
||||
const task = Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -716,21 +804,26 @@ describe('task lifecycle', () => {
|
||||
it('should throw error when try to cancel a microTask', testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMicroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMicroTask('testMicroTask', () => {}, undefined, noop);
|
||||
expect(() => { Zone.current.cancelTask(task); }).toThrowError('Task is not cancelable');
|
||||
expect(() => {
|
||||
Zone.current.cancelTask(task);
|
||||
}).toThrowError('Task is not cancelable');
|
||||
});
|
||||
}));
|
||||
|
||||
it('task should transit from running to notScheduled when task.callback throw error',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
Zone.current.fork({name: 'testMicroTaskZone'}).run(() => {
|
||||
const task = Zone.current.scheduleMicroTask(
|
||||
'testMicroTask', () => { throw Error('invoke error'); }, undefined, noop);
|
||||
const task = Zone.current.scheduleMicroTask('testMicroTask', () => {
|
||||
throw Error('invoke error');
|
||||
}, undefined, noop);
|
||||
try {
|
||||
task.invoke();
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -754,7 +847,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'}
|
||||
@ -780,7 +875,9 @@ describe('task lifecycle', () => {
|
||||
} catch (err) {
|
||||
}
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -798,7 +895,9 @@ describe('task lifecycle', () => {
|
||||
Zone.current.cancelTask(task);
|
||||
task.invoke();
|
||||
});
|
||||
expect(log.map(item => { return {toState: item.toState, fromState: item.fromState}; }))
|
||||
expect(log.map(item => {
|
||||
return {toState: item.toState, fromState: item.fromState};
|
||||
}))
|
||||
.toEqual([
|
||||
{toState: 'scheduling', fromState: 'notScheduled'},
|
||||
{toState: 'scheduled', fromState: 'scheduling'},
|
||||
@ -809,7 +908,7 @@ describe('task lifecycle', () => {
|
||||
});
|
||||
|
||||
describe('reschedule zone', () => {
|
||||
let callbackLogs: ({pos: string, method: string, zone: string, task: string} | HasTaskState)[];
|
||||
let callbackLogs: ({pos: string, method: string, zone: string, task: string}|HasTaskState)[];
|
||||
const newZone = Zone.root.fork({
|
||||
name: 'new',
|
||||
onScheduleTask: (delegate, currZone, targetZone, task) => {
|
||||
@ -861,7 +960,9 @@ describe('task lifecycle', () => {
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => { callbackLogs = []; });
|
||||
beforeEach(() => {
|
||||
callbackLogs = [];
|
||||
});
|
||||
|
||||
it('should be able to reschedule zone when in scheduling state, after that, task will completely go to new zone, has nothing to do with original one',
|
||||
testFnWithLoggedTransitionTo(() => {
|
||||
@ -876,13 +977,8 @@ describe('task lifecycle', () => {
|
||||
{pos: 'before', method: 'onScheduleTask', zone: 'new', task: 'new'},
|
||||
{microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'new'},
|
||||
{pos: 'after', method: 'onScheduleTask', zone: 'original', task: 'new'},
|
||||
{pos: 'before', method: 'onInvokeTask', zone: 'new', task: 'new'}, {
|
||||
microTask: false,
|
||||
macroTask: false,
|
||||
eventTask: false,
|
||||
change: 'macroTask',
|
||||
zone: 'new'
|
||||
}
|
||||
{pos: 'before', method: 'onInvokeTask', zone: 'new', task: 'new'},
|
||||
{microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'new'}
|
||||
]);
|
||||
}));
|
||||
|
||||
@ -892,7 +988,9 @@ describe('task lifecycle', () => {
|
||||
const t = Zone.current.scheduleMacroTask(
|
||||
'testRescheduleZoneTask', noop, undefined, noop, noop);
|
||||
Zone.current.cancelTask(t);
|
||||
expect(() => { t.cancelScheduleRequest(); })
|
||||
expect(() => {
|
||||
t.cancelScheduleRequest();
|
||||
})
|
||||
.toThrow(Error(
|
||||
`macroTask 'testRescheduleZoneTask': can not transition to ` +
|
||||
`'notScheduled', expecting state 'scheduling', was 'notScheduled'.`));
|
||||
@ -902,7 +1000,9 @@ describe('task lifecycle', () => {
|
||||
.fork({
|
||||
name: 'rescheduleRunning',
|
||||
onInvokeTask: (delegate, currZone, targetZone, task, applyThis, applyArgs) => {
|
||||
expect(() => { task.cancelScheduleRequest(); })
|
||||
expect(() => {
|
||||
task.cancelScheduleRequest();
|
||||
})
|
||||
.toThrow(Error(
|
||||
`macroTask 'testRescheduleZoneTask': can not transition to ` +
|
||||
`'notScheduled', expecting state 'scheduling', was 'running'.`));
|
||||
@ -918,7 +1018,9 @@ describe('task lifecycle', () => {
|
||||
.fork({
|
||||
name: 'rescheduleCanceling',
|
||||
onCancelTask: (delegate, currZone, targetZone, task) => {
|
||||
expect(() => { task.cancelScheduleRequest(); })
|
||||
expect(() => {
|
||||
task.cancelScheduleRequest();
|
||||
})
|
||||
.toThrow(Error(
|
||||
`macroTask 'testRescheduleZoneTask': can not transition to ` +
|
||||
`'notScheduled', expecting state 'scheduling', was 'canceling'.`));
|
||||
|
@ -32,8 +32,9 @@ describe('global function patch', () => {
|
||||
});
|
||||
|
||||
describe('isNative', () => {
|
||||
it('ZoneAwareError toString should look like native',
|
||||
() => { expect(Function.prototype.toString.call(Error)).toContain('[native code]'); });
|
||||
it('ZoneAwareError toString should look like native', () => {
|
||||
expect(Function.prototype.toString.call(Error)).toContain('[native code]');
|
||||
});
|
||||
|
||||
it('Function toString should look like native', () => {
|
||||
expect(Function.prototype.toString.call(Function.prototype.toString))
|
||||
|
@ -29,27 +29,33 @@ describe('utils', function() {
|
||||
expect(name).toEqual('method');
|
||||
delegateMethod = delegate;
|
||||
delegateSymbol = symbol;
|
||||
return function(self, args) { return delegate.apply(self, ['patch', args[0]]); };
|
||||
})).toBe(delegateMethod !);
|
||||
return function(self, args) {
|
||||
return delegate.apply(self, ['patch', args[0]]);
|
||||
};
|
||||
})).toBe(delegateMethod!);
|
||||
|
||||
expect(instance.method('a0')).toEqual('OK');
|
||||
expect(args).toEqual(['patch', 'a0']);
|
||||
expect(self).toBe(instance);
|
||||
expect(delegateMethod !).toBe(method);
|
||||
expect(delegateSymbol !).toEqual(zoneSymbol('method'));
|
||||
expect((Type.prototype as any)[delegateSymbol !]).toBe(method);
|
||||
expect(delegateMethod!).toBe(method);
|
||||
expect(delegateSymbol!).toEqual(zoneSymbol('method'));
|
||||
expect((Type.prototype as any)[delegateSymbol!]).toBe(method);
|
||||
});
|
||||
|
||||
it('should not double patch', () => {
|
||||
const Type = function() {};
|
||||
const method = Type.prototype.method = function() {};
|
||||
patchMethod(Type.prototype, 'method', (delegate) => {
|
||||
return function(self, args: any[]) { return delegate.apply(self, ['patch', ...args]); };
|
||||
return function(self, args: any[]) {
|
||||
return delegate.apply(self, ['patch', ...args]);
|
||||
};
|
||||
});
|
||||
const pMethod = Type.prototype.method;
|
||||
expect(pMethod).not.toBe(method);
|
||||
patchMethod(Type.prototype, 'method', (delegate) => {
|
||||
return function(self, args) { return delegate.apply(self, ['patch', ...args]); };
|
||||
return function(self, args) {
|
||||
return delegate.apply(self, ['patch', ...args]);
|
||||
};
|
||||
});
|
||||
expect(pMethod).toBe(Type.prototype.method);
|
||||
});
|
||||
@ -68,8 +74,8 @@ describe('utils', function() {
|
||||
}
|
||||
patchProperty(TestType.prototype, 'nonConfigurableProperty');
|
||||
const desc = Object.getOwnPropertyDescriptor(TestType.prototype, 'nonConfigurableProperty');
|
||||
expect(desc !.writable).toBeTruthy();
|
||||
expect(!desc !.get).toBeTruthy();
|
||||
expect(desc!.writable).toBeTruthy();
|
||||
expect(!desc!.get).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -80,13 +86,17 @@ describe('utils', function() {
|
||||
const log: string[] = [];
|
||||
Object.defineProperties(TestFunction.prototype, {
|
||||
'property1': {
|
||||
value: function Property1(callback: Function) { Zone.root.run(callback); },
|
||||
value: function Property1(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
},
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
},
|
||||
'property2': {
|
||||
value: function Property2(callback: Function) { Zone.root.run(callback); },
|
||||
value: function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
},
|
||||
writable: true,
|
||||
configurable: false,
|
||||
enumerable: true
|
||||
@ -97,8 +107,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1<root>', 'property2<root>']);
|
||||
log.length = 0;
|
||||
@ -107,8 +121,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1patch', 'property2patch']);
|
||||
});
|
||||
@ -119,13 +137,17 @@ describe('utils', function() {
|
||||
const log: string[] = [];
|
||||
Object.defineProperties(TestFunction.prototype, {
|
||||
'property1': {
|
||||
value: function Property1(callback: Function) { Zone.root.run(callback); },
|
||||
value: function Property1(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
},
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
},
|
||||
'property2': {
|
||||
value: function Property2(callback: Function) { Zone.root.run(callback); },
|
||||
value: function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
@ -136,8 +158,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1<root>', 'property2<root>']);
|
||||
log.length = 0;
|
||||
@ -146,8 +172,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1patch', 'property2<root>']);
|
||||
});
|
||||
@ -160,17 +190,23 @@ describe('utils', function() {
|
||||
'property1': {
|
||||
get: function() {
|
||||
if (!this._property1) {
|
||||
this._property1 = function Property2(callback: Function) { Zone.root.run(callback); };
|
||||
this._property1 = function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
};
|
||||
}
|
||||
return this._property1;
|
||||
},
|
||||
set: function(func: Function) { this._property1 = func; },
|
||||
set: function(func: Function) {
|
||||
this._property1 = func;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
},
|
||||
'property2': {
|
||||
get: function() {
|
||||
return function Property2(callback: Function) { Zone.root.run(callback); };
|
||||
return function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
};
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
@ -181,8 +217,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1<root>', 'property2<root>']);
|
||||
log.length = 0;
|
||||
@ -191,8 +231,12 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property1(() => { log.push('property1' + Zone.current.name); });
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property1(() => {
|
||||
log.push('property1' + Zone.current.name);
|
||||
});
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property1patch', 'property2<root>']);
|
||||
});
|
||||
@ -203,7 +247,9 @@ describe('utils', function() {
|
||||
const log: string[] = [];
|
||||
Object.defineProperties(TestFunction.prototype, {
|
||||
'property2': {
|
||||
value: function Property2(callback: Function) { Zone.root.run(callback); },
|
||||
value: function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
@ -214,7 +260,9 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property2<root>']);
|
||||
log.length = 0;
|
||||
@ -222,12 +270,16 @@ describe('utils', function() {
|
||||
patchMethod(
|
||||
TestFunction.prototype, 'property2',
|
||||
function(delegate: Function, delegateName: string, name: string) {
|
||||
return function(self: any, args: any) { log.push('patched property2'); };
|
||||
return function(self: any, args: any) {
|
||||
log.push('patched property2');
|
||||
};
|
||||
});
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property2<root>']);
|
||||
});
|
||||
@ -239,7 +291,9 @@ describe('utils', function() {
|
||||
Object.defineProperties(TestFunction.prototype, {
|
||||
'property2': {
|
||||
get: function() {
|
||||
return function Property2(callback: Function) { Zone.root.run(callback); };
|
||||
return function Property2(callback: Function) {
|
||||
Zone.root.run(callback);
|
||||
};
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
@ -250,7 +304,9 @@ describe('utils', function() {
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property2<root>']);
|
||||
log.length = 0;
|
||||
@ -258,12 +314,16 @@ describe('utils', function() {
|
||||
patchMethod(
|
||||
TestFunction.prototype, 'property2',
|
||||
function(delegate: Function, delegateName: string, name: string) {
|
||||
return function(self: any, args: any) { log.push('patched property2'); };
|
||||
return function(self: any, args: any) {
|
||||
log.push('patched property2');
|
||||
};
|
||||
});
|
||||
|
||||
zone.run(() => {
|
||||
const instance = new TestFunction();
|
||||
instance.property2(() => { log.push('property2' + Zone.current.name); });
|
||||
instance.property2(() => {
|
||||
log.push('property2' + Zone.current.name);
|
||||
});
|
||||
});
|
||||
expect(log).toEqual(['property2<root>']);
|
||||
});
|
||||
|
@ -10,11 +10,16 @@ import {zoneSymbol} from '../../lib/common/utils';
|
||||
describe('Zone', function() {
|
||||
const rootZone = Zone.current;
|
||||
|
||||
it('should have a name', function() { expect(Zone.current.name).toBeDefined(); });
|
||||
it('should have a name', function() {
|
||||
expect(Zone.current.name).toBeDefined();
|
||||
});
|
||||
|
||||
describe('hooks', function() {
|
||||
it('should throw if onError is not defined',
|
||||
function() { expect(function() { Zone.current.run(throwError); }).toThrow(); });
|
||||
it('should throw if onError is not defined', function() {
|
||||
expect(function() {
|
||||
Zone.current.run(throwError);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
|
||||
it('should fire onError if a function run by a zone throws', function() {
|
||||
@ -23,7 +28,9 @@ describe('Zone', function() {
|
||||
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
|
||||
expect(function() { myZone.runGuarded(throwError); }).not.toThrow();
|
||||
expect(function() {
|
||||
myZone.runGuarded(throwError);
|
||||
}).not.toThrow();
|
||||
|
||||
expect(errorSpy).toHaveBeenCalled();
|
||||
});
|
||||
@ -73,7 +80,9 @@ describe('Zone', function() {
|
||||
const zoneB = zone.fork({name: 'B'});
|
||||
|
||||
zoneA.run(function() {
|
||||
zoneB.run(function() { expect(Zone.current).toBe(zoneB); });
|
||||
zoneB.run(function() {
|
||||
expect(Zone.current).toBe(zoneB);
|
||||
});
|
||||
expect(Zone.current).toBe(zoneA);
|
||||
});
|
||||
expect(Zone.current).toBe(zone);
|
||||
@ -97,7 +106,9 @@ describe('Zone', function() {
|
||||
|
||||
it('should be able to get run under rootZone', function() {
|
||||
Zone.current.fork({name: 'testZone'}).run(function() {
|
||||
Zone.root.run(() => { expect(Zone.current.name).toEqual('<root>'); });
|
||||
Zone.root.run(() => {
|
||||
expect(Zone.current.name).toEqual('<root>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -105,7 +116,7 @@ describe('Zone', function() {
|
||||
Zone.current.fork({name: 'testZone'}).run(function() {
|
||||
Zone.root.fork({name: 'newTestZone'}).run(() => {
|
||||
expect(Zone.current.name).toEqual('newTestZone');
|
||||
expect(Zone.current.parent !.name).toEqual('<root>');
|
||||
expect(Zone.current.parent!.name).toEqual('<root>');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -130,10 +141,10 @@ describe('Zone', function() {
|
||||
const zone: Zone = Zone.current.fork({
|
||||
name: 'parent',
|
||||
onHasTask: (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState):
|
||||
void => {
|
||||
(hasTaskState as any)['zone'] = target.name;
|
||||
log.push(hasTaskState);
|
||||
},
|
||||
void => {
|
||||
(hasTaskState as any)['zone'] = target.name;
|
||||
log.push(hasTaskState);
|
||||
},
|
||||
onScheduleTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task) => {
|
||||
// Do nothing to prevent tasks from being run on VM turn;
|
||||
// Tests run task explicitly.
|
||||
@ -141,12 +152,16 @@ describe('Zone', function() {
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => { log = []; });
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
});
|
||||
|
||||
it('task can only run in the zone of creation', () => {
|
||||
const task =
|
||||
zone.fork({name: 'createZone'}).scheduleMacroTask('test', noop, undefined, noop, noop);
|
||||
expect(() => { Zone.current.fork({name: 'anotherZone'}).runTask(task); })
|
||||
expect(() => {
|
||||
Zone.current.fork({name: 'anotherZone'}).runTask(task);
|
||||
})
|
||||
.toThrowError(
|
||||
'A task can only be run in the zone of creation! (Creation: createZone; Execution: anotherZone)');
|
||||
task.zone.cancelTask(task);
|
||||
@ -155,7 +170,9 @@ describe('Zone', function() {
|
||||
it('task can only cancel in the zone of creation', () => {
|
||||
const task =
|
||||
zone.fork({name: 'createZone'}).scheduleMacroTask('test', noop, undefined, noop, noop);
|
||||
expect(() => { Zone.current.fork({name: 'anotherZone'}).cancelTask(task); })
|
||||
expect(() => {
|
||||
Zone.current.fork({name: 'anotherZone'}).cancelTask(task);
|
||||
})
|
||||
.toThrowError(
|
||||
'A task can only be cancelled in the zone of creation! (Creation: createZone; Execution: anotherZone)');
|
||||
task.zone.cancelTask(task);
|
||||
@ -183,13 +200,8 @@ describe('Zone', function() {
|
||||
});
|
||||
expect(log).toEqual([
|
||||
{microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'parent'},
|
||||
'macroTask', 'macroTask', {
|
||||
microTask: false,
|
||||
macroTask: false,
|
||||
eventTask: false,
|
||||
change: 'macroTask',
|
||||
zone: 'parent'
|
||||
}
|
||||
'macroTask', 'macroTask',
|
||||
{microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'parent'}
|
||||
]);
|
||||
});
|
||||
|
||||
@ -209,13 +221,7 @@ describe('Zone', function() {
|
||||
{microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'parent'},
|
||||
{microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'parent'},
|
||||
{microTask: false, macroTask: false, eventTask: true, change: 'eventTask', zone: 'parent'},
|
||||
{
|
||||
microTask: false,
|
||||
macroTask: false,
|
||||
eventTask: false,
|
||||
change: 'eventTask',
|
||||
zone: 'parent'
|
||||
}
|
||||
{microTask: false, macroTask: false, eventTask: false, change: 'eventTask', zone: 'parent'}
|
||||
]);
|
||||
});
|
||||
|
||||
@ -315,15 +321,18 @@ describe('Zone', function() {
|
||||
() => {
|
||||
const zone = Zone.current.fork({name: 'testZone'});
|
||||
|
||||
const task = zone.scheduleEventTask(
|
||||
'testEventTask', () => { zone.cancelTask(task); }, undefined, () => {}, () => {});
|
||||
const task = zone.scheduleEventTask('testEventTask', () => {
|
||||
zone.cancelTask(task);
|
||||
}, undefined, () => {}, () => {});
|
||||
|
||||
task.invoke();
|
||||
expect(task.state).toBe('notScheduled');
|
||||
});
|
||||
|
||||
describe('assert ZoneAwarePromise', () => {
|
||||
it('should not throw when all is OK', () => { Zone.assertZonePatched(); });
|
||||
it('should not throw when all is OK', () => {
|
||||
Zone.assertZonePatched();
|
||||
});
|
||||
|
||||
it('should keep ZoneAwarePromise has been patched', () => {
|
||||
class WrongPromise {
|
||||
@ -353,7 +362,9 @@ describe('Zone', function() {
|
||||
function noop() {}
|
||||
|
||||
|
||||
beforeEach(() => { log = []; });
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
});
|
||||
|
||||
it('should not drain the microtask queue too early', () => {
|
||||
const z = Zone.current;
|
||||
@ -375,17 +386,26 @@ describe('Zone', function() {
|
||||
const event = z.scheduleEventTask('test', () => {}, undefined, noop, noop);
|
||||
const micro = z.scheduleMicroTask('test', () => {});
|
||||
const macro = z.scheduleMacroTask('test', () => {}, undefined, noop, noop);
|
||||
expect(function() { JSON.stringify(event); }).not.toThrow();
|
||||
expect(function() { JSON.stringify(micro); }).not.toThrow();
|
||||
expect(function() { JSON.stringify(macro); }).not.toThrow();
|
||||
expect(function() {
|
||||
JSON.stringify(event);
|
||||
}).not.toThrow();
|
||||
expect(function() {
|
||||
JSON.stringify(micro);
|
||||
}).not.toThrow();
|
||||
expect(function() {
|
||||
JSON.stringify(macro);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should call onHandleError callback when zoneSpec onHasTask throw error', () => {
|
||||
const spy = jasmine.createSpy('error');
|
||||
const hasTaskZone = Zone.current.fork({
|
||||
name: 'hasTask',
|
||||
onHasTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
hasTasState: HasTaskState) => { throw new Error('onHasTask Error'); },
|
||||
onHasTask:
|
||||
(delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
hasTasState: HasTaskState) => {
|
||||
throw new Error('onHasTask Error');
|
||||
},
|
||||
onHandleError:
|
||||
(delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => {
|
||||
spy(error.message);
|
||||
|
Reference in New Issue
Block a user