1- import { global } from 'angular2/src/facade/lang' ;
21import { BaseException } from 'angular2/src/facade/exceptions' ;
3- import { ListWrapper } from 'angular2/src/facade/collection ' ;
2+ import { getTestInjector , FunctionWithParamTokens } from './test_injector ' ;
43
5- var _scheduler ;
6- var _microtasks : Function [ ] = [ ] ;
7- var _pendingPeriodicTimers : number [ ] = [ ] ;
8- var _pendingTimers : number [ ] = [ ] ;
9-
10- class FakeAsyncZoneSpec implements ZoneSpec {
11- static assertInZone ( ) : void {
12- if ( ! Zone . current . get ( 'inFakeAsyncZone' ) ) {
13- throw new Error ( 'The code should be running in the fakeAsync zone to call this function' ) ;
14- }
15- }
16-
17- name : string = 'fakeAsync' ;
18-
19- properties : { [ key : string ] : any } = { 'inFakeAsyncZone' : true } ;
20-
21- onScheduleTask ( delegate : ZoneDelegate , current : Zone , target : Zone , task : Task ) : Task {
22- switch ( task . type ) {
23- case 'microTask' :
24- _microtasks . push ( task . invoke ) ;
25- break ;
26- case 'macroTask' :
27- switch ( task . source ) {
28- case 'setTimeout' :
29- task . data [ 'handleId' ] = _setTimeout ( task . invoke , task . data [ 'delay' ] , task . data [ 'args' ] ) ;
30- break ;
31- case 'setInterval' :
32- task . data [ 'handleId' ] =
33- _setInterval ( task . invoke , task . data [ 'delay' ] , task . data [ 'args' ] ) ;
34- break ;
35- default :
36- task = delegate . scheduleTask ( target , task ) ;
37- }
38- break ;
39- case 'eventTask' :
40- task = delegate . scheduleTask ( target , task ) ;
41- break ;
42- }
43- return task ;
44- }
45-
46- onCancelTask ( delegate : ZoneDelegate , current : Zone , target : Zone , task : Task ) : any {
47- switch ( task . source ) {
48- case 'setTimeout' :
49- return _clearTimeout ( task . data [ 'handleId' ] ) ;
50- case 'setInterval' :
51- return _clearInterval ( task . data [ 'handleId' ] ) ;
52- default :
53- return delegate . scheduleTask ( target , task ) ;
54- }
55- }
56- }
4+ let _FakeAsyncTestZoneSpecType = Zone [ 'FakeAsyncTestZoneSpec' ] ;
575
586/**
597 * Wraps a function to be executed in the fakeAsync zone:
@@ -62,64 +10,72 @@ class FakeAsyncZoneSpec implements ZoneSpec {
6210 *
6311 * If there are any pending timers at the end of the function, an exception will be thrown.
6412 *
13+ * Can be used to wrap inject() calls.
14+ *
6515 * ## Example
6616 *
6717 * {@example testing/ts/fake_async.ts region='basic'}
6818 *
6919 * @param fn
7020 * @returns {Function } The function wrapped to be executed in the fakeAsync zone
7121 */
72- export function fakeAsync ( fn : Function ) : Function {
73- if ( Zone . current . get ( 'inFakeAsyncZone' ) ) {
74- throw new Error ( 'fakeAsync() calls can not be nested' ) ;
22+ export function fakeAsync ( fn : Function | FunctionWithParamTokens ) : Function {
23+ if ( Zone . current . get ( 'FakeAsyncTestZoneSpec' ) != null ) {
24+ throw new BaseException ( 'fakeAsync() calls can not be nested' ) ;
7525 }
7626
77- var fakeAsyncZone = Zone . current . fork ( new FakeAsyncZoneSpec ( ) ) ;
27+ let fakeAsyncTestZoneSpec = new _FakeAsyncTestZoneSpecType ( ) ;
28+ let fakeAsyncZone = Zone . current . fork ( fakeAsyncTestZoneSpec ) ;
7829
79- return function ( ...args ) {
80- // TODO(tbosch): This class should already be part of the jasmine typings but it is not...
81- _scheduler = new ( < any > jasmine ) . DelayedFunctionScheduler ( ) ;
82- clearPendingTimers ( ) ;
30+ let innerTestFn : Function = null ;
31+
32+ if ( fn instanceof FunctionWithParamTokens ) {
33+ if ( fn . isAsync ) {
34+ throw new BaseException ( 'Cannot wrap async test with fakeAsync' ) ;
35+ }
36+ innerTestFn = ( ) => { getTestInjector ( ) . execute ( fn as FunctionWithParamTokens ) ; } ;
37+ } else {
38+ innerTestFn = fn ;
39+ }
8340
41+ return function ( ...args ) {
8442 let res = fakeAsyncZone . run ( ( ) => {
85- let res = fn ( ...args ) ;
43+ let res = innerTestFn ( ...args ) ;
8644 flushMicrotasks ( ) ;
8745 return res ;
8846 } ) ;
8947
90- if ( _pendingPeriodicTimers . length > 0 ) {
91- throw new BaseException (
92- ` ${ _pendingPeriodicTimers . length } periodic timer(s) still in the queue.`) ;
48+ if ( fakeAsyncTestZoneSpec . pendingPeriodicTimers . length > 0 ) {
49+ throw new BaseException ( ` ${ fakeAsyncTestZoneSpec . pendingPeriodicTimers . length } ` +
50+ ` periodic timer(s) still in the queue.`) ;
9351 }
9452
95- if ( _pendingTimers . length > 0 ) {
96- throw new BaseException ( `${ _pendingTimers . length } timer(s) still in the queue.` ) ;
53+ if ( fakeAsyncTestZoneSpec . pendingTimers . length > 0 ) {
54+ throw new BaseException (
55+ `${ fakeAsyncTestZoneSpec . pendingTimers . length } timer(s) still in the queue.` ) ;
9756 }
98-
99- _scheduler = null ;
100- ListWrapper . clear ( _microtasks ) ;
101-
10257 return res ;
58+ } ;
59+ }
60+
61+ function _getFakeAsyncZoneSpec ( ) : any {
62+ let zoneSpec = Zone . current . get ( 'FakeAsyncTestZoneSpec' ) ;
63+ if ( zoneSpec == null ) {
64+ throw new Error ( 'The code should be running in the fakeAsync zone to call this function' ) ;
10365 }
66+ return zoneSpec ;
10467}
10568
10669/**
10770 * Clear the queue of pending timers and microtasks.
71+ * Tests no longer need to call this explicitly.
10872 *
109- * Useful for cleaning up after an asynchronous test passes.
110- *
111- * ## Example
112- *
113- * {@example testing/ts/fake_async.ts region='pending'}
73+ * @deprecated
11474 */
11575export function clearPendingTimers ( ) : void {
116- // TODO we should fix tick to dequeue the failed timer instead of relying on clearPendingTimers
117- ListWrapper . clear ( _microtasks ) ;
118- ListWrapper . clear ( _pendingPeriodicTimers ) ;
119- ListWrapper . clear ( _pendingTimers ) ;
76+ // Do nothing.
12077}
12178
122-
12379/**
12480 * Simulates the asynchronous passage of time for the timers in the fakeAsync zone.
12581 *
@@ -133,54 +89,12 @@ export function clearPendingTimers(): void {
13389 * @param {number } millis Number of millisecond, defaults to 0
13490 */
13591export function tick ( millis : number = 0 ) : void {
136- FakeAsyncZoneSpec . assertInZone ( ) ;
137- flushMicrotasks ( ) ;
138- _scheduler . tick ( millis ) ;
92+ _getFakeAsyncZoneSpec ( ) . tick ( millis ) ;
13993}
14094
14195/**
14296 * Flush any pending microtasks.
14397 */
14498export function flushMicrotasks ( ) : void {
145- FakeAsyncZoneSpec . assertInZone ( ) ;
146- while ( _microtasks . length > 0 ) {
147- var microtask = ListWrapper . removeAt ( _microtasks , 0 ) ;
148- microtask ( ) ;
149- }
150- }
151-
152- function _setTimeout ( fn : Function , delay : number , args : any [ ] ) : number {
153- var cb = _fnAndFlush ( fn ) ;
154- var id = _scheduler . scheduleFunction ( cb , delay , args ) ;
155- _pendingTimers . push ( id ) ;
156- _scheduler . scheduleFunction ( _dequeueTimer ( id ) , delay ) ;
157- return id ;
158- }
159-
160- function _clearTimeout ( id : number ) {
161- _dequeueTimer ( id ) ;
162- return _scheduler . removeFunctionWithId ( id ) ;
163- }
164-
165- function _setInterval ( fn : Function , interval : number , ...args ) {
166- var cb = _fnAndFlush ( fn ) ;
167- var id = _scheduler . scheduleFunction ( cb , interval , args , true ) ;
168- _pendingPeriodicTimers . push ( id ) ;
169- return id ;
170- }
171-
172- function _clearInterval ( id : number ) {
173- ListWrapper . remove ( _pendingPeriodicTimers , id ) ;
174- return _scheduler . removeFunctionWithId ( id ) ;
175- }
176-
177- function _fnAndFlush ( fn : Function ) : Function {
178- return ( ...args ) => {
179- fn . apply ( global , args ) ;
180- flushMicrotasks ( ) ;
181- }
182- }
183-
184- function _dequeueTimer ( id : number ) : Function {
185- return function ( ) { ListWrapper . remove ( _pendingTimers , id ) ; }
99+ _getFakeAsyncZoneSpec ( ) . flushMicrotasks ( ) ;
186100}
0 commit comments