2015-05-12 10:28:57 -04:00
|
|
|
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,
|
2015-05-29 13:42:47 -04:00
|
|
|
a7 = _u, a8 = _u, a9 = _u]) {
|
2015-05-12 10:28:57 -04:00
|
|
|
// runZoned() to install a custom exception handler that re-throws
|
|
|
|
return runZoned(() {
|
2015-06-02 13:55:03 -04:00
|
|
|
return new quiver.FakeAsync().run((quiver.FakeAsync async) {
|
2015-05-12 10:28:57 -04:00
|
|
|
try {
|
|
|
|
_fakeAsync = async;
|
2015-06-05 13:35:42 -04:00
|
|
|
List args = [
|
|
|
|
a0,
|
|
|
|
a1,
|
|
|
|
a2,
|
|
|
|
a3,
|
|
|
|
a4,
|
|
|
|
a5,
|
|
|
|
a6,
|
|
|
|
a7,
|
|
|
|
a8,
|
|
|
|
a9
|
|
|
|
].takeWhile((a) => a != _u).toList();
|
2015-06-02 13:55:03 -04:00
|
|
|
var res = Function.apply(fn, args);
|
|
|
|
_fakeAsync.flushMicrotasks();
|
2015-05-29 02:20:48 -04:00
|
|
|
|
|
|
|
if (async.periodicTimerCount > 0) {
|
|
|
|
throw new BaseException('${async.periodicTimerCount} periodic '
|
|
|
|
'timer(s) still in the queue.');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (async.nonPeriodicTimerCount > 0) {
|
|
|
|
throw new BaseException('${async.nonPeriodicTimerCount} timer(s) '
|
|
|
|
'still in the queue.');
|
|
|
|
}
|
|
|
|
|
2015-06-02 13:55:03 -04:00
|
|
|
return res;
|
2015-05-12 10:28:57 -04:00
|
|
|
} finally {
|
|
|
|
_fakeAsync = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2015-05-29 13:42:47 -04:00
|
|
|
zoneSpecification: new ZoneSpecification(
|
|
|
|
handleUncaughtError: (self, parent, zone, error, stackTrace) =>
|
|
|
|
throw error));
|
2015-05-12 10:28:57 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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');
|
|
|
|
}
|
|
|
|
}
|