feat(fakeAsync): allow simulating the passage of time
This commit is contained in:
parent
b066b8d15a
commit
0f002a5b18
|
@ -17,8 +17,9 @@ dependencies:
|
||||||
logging: '>=0.9.0 <0.11.0'
|
logging: '>=0.9.0 <0.11.0'
|
||||||
source_span: '^1.0.0'
|
source_span: '^1.0.0'
|
||||||
stack_trace: '^1.1.1'
|
stack_trace: '^1.1.1'
|
||||||
|
quiver: '^0.21.3+1'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
guinness: "^0.1.17"
|
guinness: '^0.1.17'
|
||||||
transformers:
|
transformers:
|
||||||
- angular2
|
- angular2
|
||||||
- $dart2js:
|
- $dart2js:
|
||||||
|
|
|
@ -25,8 +25,19 @@ class PromiseWrapper {
|
||||||
|
|
||||||
static _Completer completer() => new _Completer(new Completer());
|
static _Completer completer() => new _Completer(new Completer());
|
||||||
|
|
||||||
static void setTimeout(fn(), int millis) {
|
// TODO(vic): create a TimerWrapper
|
||||||
new Timer(new Duration(milliseconds: millis), fn);
|
static Timer setTimeout(fn(), int millis)
|
||||||
|
=> new Timer(new Duration(milliseconds: millis), fn);
|
||||||
|
static void clearTimeout(Timer timer) {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Timer setInterval(fn(), int millis) {
|
||||||
|
var interval = new Duration(milliseconds: millis);
|
||||||
|
return new Timer.periodic(interval, (Timer timer) { fn(); });
|
||||||
|
}
|
||||||
|
static void clearInterval(Timer timer) {
|
||||||
|
timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isPromise(maybePromise) {
|
static bool isPromise(maybePromise) {
|
||||||
|
|
|
@ -45,7 +45,12 @@ export class PromiseWrapper {
|
||||||
return {promise: p, resolve: resolve, reject: reject};
|
return {promise: p, resolve: resolve, reject: reject};
|
||||||
}
|
}
|
||||||
|
|
||||||
static setTimeout(fn: Function, millis: int) { global.setTimeout(fn, millis); }
|
// TODO(vicb): create a TimerWrapper
|
||||||
|
static setTimeout(fn: Function, millis: int): int { return global.setTimeout(fn, millis); }
|
||||||
|
static clearTimeout(id: int): void { global.clearTimeout(id); }
|
||||||
|
|
||||||
|
static setInterval(fn: Function, millis: int): int { return global.setInterval(fn, millis); }
|
||||||
|
static clearInterval(id: int): void { global.clearInterval(id); }
|
||||||
|
|
||||||
static isPromise(maybePromise): boolean { return maybePromise instanceof Promise; }
|
static isPromise(maybePromise): boolean { return maybePromise instanceof Promise; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
library test_lib.fake_async;
|
||||||
|
|
||||||
|
import 'dart:async' show runZoned, ZoneSpecification;
|
||||||
|
import 'package:quiver/testing/async.dart' as quiver;
|
||||||
|
import 'package:angular2/src/facade/lang.dart' show BaseException;
|
||||||
|
|
||||||
|
const _u = const Object();
|
||||||
|
|
||||||
|
quiver.FakeAsync _fakeAsync = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the [fn] 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.
|
||||||
|
*
|
||||||
|
* Returns a `Function` that wraps [fn].
|
||||||
|
*/
|
||||||
|
Function fakeAsync(Function fn) {
|
||||||
|
if (_fakeAsync != null) {
|
||||||
|
throw 'fakeAsync() calls can not be nested';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ([a0 = _u, a1 = _u, a2 = _u, a3 = _u, a4 = _u, a5 = _u, a6 = _u,
|
||||||
|
a7 = _u, a8 = _u, a9 = _u]) {
|
||||||
|
// runZoned() to install a custom exception handler that re-throws
|
||||||
|
return runZoned(() {
|
||||||
|
new quiver.FakeAsync().run((quiver.FakeAsync async) {
|
||||||
|
try {
|
||||||
|
_fakeAsync = async;
|
||||||
|
List args = [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9]
|
||||||
|
.takeWhile((a) => a != _u).toList();
|
||||||
|
return Function.apply(fn , args);
|
||||||
|
} finally {
|
||||||
|
_fakeAsync = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
zoneSpecification: new ZoneSpecification(
|
||||||
|
handleUncaughtError: (self, parent, zone, error, stackTrace)
|
||||||
|
=> throw error
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates the asynchronous passage of [millis] milliseconds 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.
|
||||||
|
*/
|
||||||
|
void tick([int millis = 0]) {
|
||||||
|
_assertInFakeAsyncZone();
|
||||||
|
var duration = new Duration(milliseconds: millis);
|
||||||
|
_fakeAsync.elapse(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush any pending microtasks.
|
||||||
|
*/
|
||||||
|
void flushMicrotasks() {
|
||||||
|
_assertInFakeAsyncZone();
|
||||||
|
_fakeAsync.flushMicrotasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _assertInFakeAsyncZone() {
|
||||||
|
if (_fakeAsync == null) {
|
||||||
|
throw new BaseException('The code should be running in the fakeAsync zone '
|
||||||
|
'to call this function');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
import {BaseException, global} from 'angular2/src/facade/lang';
|
||||||
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
var _scheduler;
|
||||||
|
var _microtasks:List<Function> = [];
|
||||||
|
var _pendingPeriodicTimers: List<number> = [];
|
||||||
|
var _pendingTimers: List<number> = [];
|
||||||
|
var _error = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param fn
|
||||||
|
* @returns {Function} The function wrapped to be executed in the fakeAsync zone
|
||||||
|
*/
|
||||||
|
export function fakeAsync(fn: Function): Function {
|
||||||
|
// TODO(vicb) re-enable once the jasmine patch from zone.js is applied
|
||||||
|
//if (global.zone._inFakeAsyncZone) {
|
||||||
|
// throw new Error('fakeAsync() calls can not be nested');
|
||||||
|
//}
|
||||||
|
|
||||||
|
var fakeAsyncZone = global.zone.fork({
|
||||||
|
setTimeout: _setTimeout,
|
||||||
|
clearTimeout: _clearTimeout,
|
||||||
|
setInterval: _setInterval,
|
||||||
|
clearInterval: _clearInterval,
|
||||||
|
scheduleMicrotask: _scheduleMicrotask,
|
||||||
|
_inFakeAsyncZone: true
|
||||||
|
});
|
||||||
|
|
||||||
|
return function(...args) {
|
||||||
|
_scheduler = global.jasmine.DelayedFunctionScheduler();
|
||||||
|
ListWrapper.clear(_microtasks);
|
||||||
|
ListWrapper.clear(_pendingPeriodicTimers);
|
||||||
|
ListWrapper.clear(_pendingTimers);
|
||||||
|
|
||||||
|
var res = fakeAsyncZone.run(() => {
|
||||||
|
var res = fn(...args);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_pendingPeriodicTimers.length > 0) {
|
||||||
|
throw new BaseException(`${_pendingPeriodicTimers.length} periodic timer(s) still in the queue.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pendingTimers.length > 0) {
|
||||||
|
throw new BaseException(`${_pendingTimers.length} timer(s) still in the queue.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scheduler = null;
|
||||||
|
ListWrapper.clear(_microtasks);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param {number} millis Number of millisecond, defaults to 0
|
||||||
|
*/
|
||||||
|
export function tick(millis: number = 0): void {
|
||||||
|
_assertInFakeAsyncZone();
|
||||||
|
flushMicrotasks();
|
||||||
|
_scheduler.tick(millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush any pending microtasks.
|
||||||
|
*/
|
||||||
|
export function flushMicrotasks(): void {
|
||||||
|
_assertInFakeAsyncZone();
|
||||||
|
while (_microtasks.length > 0) {
|
||||||
|
var microtask = ListWrapper.removeAt(_microtasks, 0);
|
||||||
|
microtask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setTimeout(fn: Function, delay: number, ...args): number {
|
||||||
|
var cb = _fnAndFlush(fn);
|
||||||
|
var id = _scheduler.scheduleFunction(cb, delay, args);
|
||||||
|
ListWrapper.push(_pendingTimers, id);
|
||||||
|
_scheduler.scheduleFunction(_dequeueTimer(id), delay);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _clearTimeout(id: number) {
|
||||||
|
_dequeueTimer(id);
|
||||||
|
return _scheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setInterval(fn: Function, interval: number, ...args) {
|
||||||
|
var cb = _fnAndFlush(fn);
|
||||||
|
var id = _scheduler.scheduleFunction(cb, interval, args, true);
|
||||||
|
_pendingPeriodicTimers.push(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _clearInterval(id: number) {
|
||||||
|
ListWrapper.remove(_pendingPeriodicTimers, id);
|
||||||
|
return _scheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fnAndFlush(fn: Function): void {
|
||||||
|
return () => {
|
||||||
|
fn.apply(global, arguments);
|
||||||
|
flushMicrotasks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _scheduleMicrotask(microtask: Function): void {
|
||||||
|
ListWrapper.push(_microtasks, microtask);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _dequeueTimer(id: number): Function {
|
||||||
|
return function() {
|
||||||
|
ListWrapper.remove(_pendingTimers, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _assertInFakeAsyncZone(): void {
|
||||||
|
if (!global.zone._inFakeAsyncZone) {
|
||||||
|
throw new Error('The code should be running in the fakeAsync zone to call this function');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
library test_lib.lang_utils;
|
||||||
|
|
||||||
import 'dart:mirrors';
|
import 'dart:mirrors';
|
||||||
|
|
||||||
Type getTypeOf(instance) => instance.runtimeType;
|
Type getTypeOf(instance) => instance.runtimeType;
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
expect,
|
||||||
|
fakeAsync,
|
||||||
|
flushMicrotasks,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
IS_DARTIUM,
|
||||||
|
it,
|
||||||
|
Log,
|
||||||
|
tick,
|
||||||
|
xit
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
import {BaseException, global} from 'angular2/src/facade/lang';
|
||||||
|
import {Parser} from 'angular2/change_detection';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('fake async', () => {
|
||||||
|
it('should run synchronous code', () => {
|
||||||
|
var ran = false;
|
||||||
|
fakeAsync(() => {
|
||||||
|
ran = true;
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(ran).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pass arguments to the wrapped function', () => {
|
||||||
|
fakeAsync((foo, bar) => {
|
||||||
|
expect(foo).toEqual('foo');
|
||||||
|
expect(bar).toEqual('bar');
|
||||||
|
})('foo', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with inject()', inject([Parser], fakeAsync((parser) => {
|
||||||
|
expect(parser).toBeAnInstanceOf(Parser);
|
||||||
|
})));
|
||||||
|
|
||||||
|
if (!IS_DARTIUM) {
|
||||||
|
it('should throw on nested calls', () => {
|
||||||
|
// TODO(vicb): re-enable once the jasmine patch from zone.js is applied
|
||||||
|
if (!IS_DARTIUM) return;
|
||||||
|
expect(() => {
|
||||||
|
fakeAsync(() => {
|
||||||
|
fakeAsync(() => null)();
|
||||||
|
})();
|
||||||
|
}).toThrowError('fakeAsync() calls can not be nested');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Promise', () => {
|
||||||
|
it('should run asynchronous code', fakeAsync(() => {
|
||||||
|
var thenRan = false;
|
||||||
|
PromiseWrapper.resolve(null).then((_) => {
|
||||||
|
thenRan = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(thenRan).toEqual(false);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(thenRan).toEqual(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run chained thens', fakeAsync(() => {
|
||||||
|
var log = new Log();
|
||||||
|
|
||||||
|
PromiseWrapper
|
||||||
|
.resolve(null)
|
||||||
|
.then((_) => log.add(1))
|
||||||
|
.then((_) => log.add(2));
|
||||||
|
|
||||||
|
expect(log.result()).toEqual('');
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(log.result()).toEqual('1; 2');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run Promise created in Promise', fakeAsync(() => {
|
||||||
|
var log = new Log();
|
||||||
|
|
||||||
|
PromiseWrapper
|
||||||
|
.resolve(null)
|
||||||
|
.then((_) => {
|
||||||
|
log.add(1);
|
||||||
|
PromiseWrapper.resolve(null).then((_) => log.add(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(log.result()).toEqual('');
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(log.result()).toEqual('1; 2');
|
||||||
|
}));
|
||||||
|
|
||||||
|
// TODO(vicb): check why this doesn't work in JS - linked to open issues on GH ?
|
||||||
|
xit('should complain if the test throws an exception during async calls', () => {
|
||||||
|
expect(() => {
|
||||||
|
fakeAsync(() => {
|
||||||
|
PromiseWrapper.resolve(null).then((_) => {
|
||||||
|
throw new BaseException('async');
|
||||||
|
});
|
||||||
|
flushMicrotasks();
|
||||||
|
})();
|
||||||
|
}).toThrowError('async');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should complain if a test throws an exception', () => {
|
||||||
|
expect(() => {
|
||||||
|
fakeAsync(() => {
|
||||||
|
throw new BaseException('sync');
|
||||||
|
})();
|
||||||
|
}).toThrowError('sync');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('timers', () => {
|
||||||
|
it('should run queued zero duration timer on zero tick', fakeAsync(() => {
|
||||||
|
var ran = false;
|
||||||
|
PromiseWrapper.setTimeout(() => { ran = true }, 0);
|
||||||
|
|
||||||
|
expect(ran).toEqual(false);
|
||||||
|
|
||||||
|
tick();
|
||||||
|
expect(ran).toEqual(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should run queued timer after sufficient clock ticks', fakeAsync(() => {
|
||||||
|
var ran = false;
|
||||||
|
PromiseWrapper.setTimeout(() => { ran = true; }, 10);
|
||||||
|
|
||||||
|
tick(6);
|
||||||
|
expect(ran).toEqual(false);
|
||||||
|
|
||||||
|
tick(6);
|
||||||
|
expect(ran).toEqual(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run queued timer only once', fakeAsync(() => {
|
||||||
|
var cycles = 0;
|
||||||
|
PromiseWrapper.setTimeout(() => { cycles++; }, 10);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not run cancelled timer', fakeAsync(() => {
|
||||||
|
var ran = false;
|
||||||
|
var id = PromiseWrapper.setTimeout(() => { ran = true; }, 10);
|
||||||
|
PromiseWrapper.clearTimeout(id);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(ran).toEqual(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw an error on dangling timers', () => {
|
||||||
|
// TODO(vicb): https://github.com/google/quiver-dart/issues/248
|
||||||
|
if (IS_DARTIUM) return;
|
||||||
|
expect(() => {
|
||||||
|
fakeAsync(() => {
|
||||||
|
PromiseWrapper.setTimeout(() => { }, 10);
|
||||||
|
})();
|
||||||
|
}).toThrowError('1 timer(s) still in the queue.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error on dangling periodic timers', () => {
|
||||||
|
// TODO(vicb): https://github.com/google/quiver-dart/issues/248
|
||||||
|
if (IS_DARTIUM) return;
|
||||||
|
expect(() => {
|
||||||
|
fakeAsync(() => {
|
||||||
|
PromiseWrapper.setInterval(() => { }, 10);
|
||||||
|
})();
|
||||||
|
}).toThrowError('1 periodic timer(s) still in the queue.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run periodic timers', fakeAsync(() => {
|
||||||
|
var cycles = 0;
|
||||||
|
var id = PromiseWrapper.setInterval(() => { cycles++; }, 10);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(2);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(3);
|
||||||
|
|
||||||
|
PromiseWrapper.clearInterval(id);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not run cancelled periodic timer', fakeAsync(() => {
|
||||||
|
var ran = false;
|
||||||
|
var id = PromiseWrapper.setInterval(() => { ran = true; }, 10);
|
||||||
|
PromiseWrapper.clearInterval(id);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(ran).toEqual(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be able to cancel periodic timers from a callback', fakeAsync(() => {
|
||||||
|
if (global != null && global.jasmine) {
|
||||||
|
// TODO(vicb): remove this when we switch to jasmine 2.3.3+
|
||||||
|
// see https://github.com/jasmine/jasmine/commit/51462f369b376615bc9d761dcaa5d822ea1ff8ee
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cycles = 0;
|
||||||
|
var id;
|
||||||
|
|
||||||
|
id = PromiseWrapper.setInterval(() => {
|
||||||
|
cycles++;
|
||||||
|
PromiseWrapper.clearInterval(id);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(cycles).toEqual(1);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should process microtasks before timers', fakeAsync(() => {
|
||||||
|
var log = new Log();
|
||||||
|
|
||||||
|
PromiseWrapper.resolve(null).then((_) => log.add('microtask'));
|
||||||
|
|
||||||
|
PromiseWrapper.setTimeout(() => log.add('timer'), 9);
|
||||||
|
|
||||||
|
var id = PromiseWrapper.setInterval(() => log.add('periodic timer'), 10);
|
||||||
|
|
||||||
|
expect(log.result()).toEqual('');
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(log.result()).toEqual('microtask; timer; periodic timer');
|
||||||
|
|
||||||
|
PromiseWrapper.clearInterval(id);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should process micro-tasks created in timers before next timers', fakeAsync(() => {
|
||||||
|
var log = new Log();
|
||||||
|
|
||||||
|
PromiseWrapper.resolve(null).then((_) => log.add('microtask'));
|
||||||
|
|
||||||
|
PromiseWrapper.setTimeout(() => {
|
||||||
|
log.add('timer');
|
||||||
|
PromiseWrapper.resolve(null).then((_) => log.add('t microtask'));
|
||||||
|
}, 9);
|
||||||
|
|
||||||
|
var id = PromiseWrapper.setInterval(() => {
|
||||||
|
log.add('periodic timer');
|
||||||
|
PromiseWrapper.resolve(null).then((_) => log.add('pt microtask'));
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(log.result()).toEqual('microtask; timer; t microtask; periodic timer; pt microtask');
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
expect(log.result()).toEqual('microtask; timer; t microtask; periodic timer; pt microtask; periodic timer; pt microtask');
|
||||||
|
|
||||||
|
PromiseWrapper.clearInterval(id);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('outside of the fakeAsync zone', () => {
|
||||||
|
it('calling flushMicrotasks should throw', () => {
|
||||||
|
expect(() => {
|
||||||
|
flushMicrotasks();
|
||||||
|
}).toThrowError('The code should be running in the fakeAsync zone to call this function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calling tick should throw', () => {
|
||||||
|
expect(() => {
|
||||||
|
tick();
|
||||||
|
}).toThrowError('The code should be running in the fakeAsync zone to call this function');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './src/test_lib/test_lib';
|
export * from './src/test_lib/test_lib';
|
||||||
export * from './src/test_lib/utils';
|
export * from './src/test_lib/utils';
|
||||||
|
export * from './src/test_lib/fake_async';
|
||||||
|
|
|
@ -4,3 +4,4 @@ environment:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
guinness: '^0.1.17'
|
guinness: '^0.1.17'
|
||||||
unittest: '^0.11.5+4'
|
unittest: '^0.11.5+4'
|
||||||
|
quiver: '^0.21.3+1'
|
||||||
|
|
|
@ -22,7 +22,8 @@ module.exports = function makeNodeTree(destinationPath) {
|
||||||
exclude: [
|
exclude: [
|
||||||
// the following code and tests are not compatible with CJS/node environment
|
// the following code and tests are not compatible with CJS/node environment
|
||||||
'angular2/src/core/zone/ng_zone.es6',
|
'angular2/src/core/zone/ng_zone.es6',
|
||||||
'angular2/test/core/zone/**'
|
'angular2/test/core/zone/**',
|
||||||
|
'angular2/test/test_lib/fake_async_spec.js'
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue