source: trip-planner-front/node_modules/zone.js/fesm2015/fake-async-test.js@ b738035

Last change on this file since b738035 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 31.3 KB
RevLine 
[6a3a178]1'use strict';
2/**
3 * @license Angular v12.0.0-next.0
4 * (c) 2010-2020 Google LLC. https://angular.io/
5 * License: MIT
6 */
7/**
8 * @license
9 * Copyright Google LLC All Rights Reserved.
10 *
11 * Use of this source code is governed by an MIT-style license that can be
12 * found in the LICENSE file at https://angular.io/license
13 */
14(function (global) {
15 const OriginalDate = global.Date;
16 // Since when we compile this file to `es2015`, and if we define
17 // this `FakeDate` as `class FakeDate`, and then set `FakeDate.prototype`
18 // there will be an error which is `Cannot assign to read only property 'prototype'`
19 // so we need to use function implementation here.
20 function FakeDate() {
21 if (arguments.length === 0) {
22 const d = new OriginalDate();
23 d.setTime(FakeDate.now());
24 return d;
25 }
26 else {
27 const args = Array.prototype.slice.call(arguments);
28 return new OriginalDate(...args);
29 }
30 }
31 FakeDate.now = function () {
32 const fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
33 if (fakeAsyncTestZoneSpec) {
34 return fakeAsyncTestZoneSpec.getFakeSystemTime();
35 }
36 return OriginalDate.now.apply(this, arguments);
37 };
38 FakeDate.UTC = OriginalDate.UTC;
39 FakeDate.parse = OriginalDate.parse;
40 // keep a reference for zone patched timer function
41 const timers = {
42 setTimeout: global.setTimeout,
43 setInterval: global.setInterval,
44 clearTimeout: global.clearTimeout,
45 clearInterval: global.clearInterval
46 };
47 class Scheduler {
48 constructor() {
49 // Scheduler queue with the tuple of end time and callback function - sorted by end time.
50 this._schedulerQueue = [];
51 // Current simulated time in millis.
52 this._currentTickTime = 0;
53 // Current fake system base time in millis.
54 this._currentFakeBaseSystemTime = OriginalDate.now();
55 // track requeuePeriodicTimer
56 this._currentTickRequeuePeriodicEntries = [];
57 }
58 getCurrentTickTime() {
59 return this._currentTickTime;
60 }
61 getFakeSystemTime() {
62 return this._currentFakeBaseSystemTime + this._currentTickTime;
63 }
64 setFakeBaseSystemTime(fakeBaseSystemTime) {
65 this._currentFakeBaseSystemTime = fakeBaseSystemTime;
66 }
67 getRealSystemTime() {
68 return OriginalDate.now();
69 }
70 scheduleFunction(cb, delay, options) {
71 options = Object.assign({
72 args: [],
73 isPeriodic: false,
74 isRequestAnimationFrame: false,
75 id: -1,
76 isRequeuePeriodic: false
77 }, options);
78 let currentId = options.id < 0 ? Scheduler.nextId++ : options.id;
79 let endTime = this._currentTickTime + delay;
80 // Insert so that scheduler queue remains sorted by end time.
81 let newEntry = {
82 endTime: endTime,
83 id: currentId,
84 func: cb,
85 args: options.args,
86 delay: delay,
87 isPeriodic: options.isPeriodic,
88 isRequestAnimationFrame: options.isRequestAnimationFrame
89 };
90 if (options.isRequeuePeriodic) {
91 this._currentTickRequeuePeriodicEntries.push(newEntry);
92 }
93 let i = 0;
94 for (; i < this._schedulerQueue.length; i++) {
95 let currentEntry = this._schedulerQueue[i];
96 if (newEntry.endTime < currentEntry.endTime) {
97 break;
98 }
99 }
100 this._schedulerQueue.splice(i, 0, newEntry);
101 return currentId;
102 }
103 removeScheduledFunctionWithId(id) {
104 for (let i = 0; i < this._schedulerQueue.length; i++) {
105 if (this._schedulerQueue[i].id == id) {
106 this._schedulerQueue.splice(i, 1);
107 break;
108 }
109 }
110 }
111 removeAll() {
112 this._schedulerQueue = [];
113 }
114 getTimerCount() {
115 return this._schedulerQueue.length;
116 }
117 tickToNext(step = 1, doTick, tickOptions) {
118 if (this._schedulerQueue.length < step) {
119 return;
120 }
121 // Find the last task currently queued in the scheduler queue and tick
122 // till that time.
123 const startTime = this._currentTickTime;
124 const targetTask = this._schedulerQueue[step - 1];
125 this.tick(targetTask.endTime - startTime, doTick, tickOptions);
126 }
127 tick(millis = 0, doTick, tickOptions) {
128 let finalTime = this._currentTickTime + millis;
129 let lastCurrentTime = 0;
130 tickOptions = Object.assign({ processNewMacroTasksSynchronously: true }, tickOptions);
131 // we need to copy the schedulerQueue so nested timeout
132 // will not be wrongly called in the current tick
133 // https://github.com/angular/angular/issues/33799
134 const schedulerQueue = tickOptions.processNewMacroTasksSynchronously ?
135 this._schedulerQueue :
136 this._schedulerQueue.slice();
137 if (schedulerQueue.length === 0 && doTick) {
138 doTick(millis);
139 return;
140 }
141 while (schedulerQueue.length > 0) {
142 // clear requeueEntries before each loop
143 this._currentTickRequeuePeriodicEntries = [];
144 let current = schedulerQueue[0];
145 if (finalTime < current.endTime) {
146 // Done processing the queue since it's sorted by endTime.
147 break;
148 }
149 else {
150 // Time to run scheduled function. Remove it from the head of queue.
151 let current = schedulerQueue.shift();
152 if (!tickOptions.processNewMacroTasksSynchronously) {
153 const idx = this._schedulerQueue.indexOf(current);
154 if (idx >= 0) {
155 this._schedulerQueue.splice(idx, 1);
156 }
157 }
158 lastCurrentTime = this._currentTickTime;
159 this._currentTickTime = current.endTime;
160 if (doTick) {
161 doTick(this._currentTickTime - lastCurrentTime);
162 }
163 let retval = current.func.apply(global, current.isRequestAnimationFrame ? [this._currentTickTime] : current.args);
164 if (!retval) {
165 // Uncaught exception in the current scheduled function. Stop processing the queue.
166 break;
167 }
168 // check is there any requeue periodic entry is added in
169 // current loop, if there is, we need to add to current loop
170 if (!tickOptions.processNewMacroTasksSynchronously) {
171 this._currentTickRequeuePeriodicEntries.forEach(newEntry => {
172 let i = 0;
173 for (; i < schedulerQueue.length; i++) {
174 const currentEntry = schedulerQueue[i];
175 if (newEntry.endTime < currentEntry.endTime) {
176 break;
177 }
178 }
179 schedulerQueue.splice(i, 0, newEntry);
180 });
181 }
182 }
183 }
184 lastCurrentTime = this._currentTickTime;
185 this._currentTickTime = finalTime;
186 if (doTick) {
187 doTick(this._currentTickTime - lastCurrentTime);
188 }
189 }
190 flushOnlyPendingTimers(doTick) {
191 if (this._schedulerQueue.length === 0) {
192 return 0;
193 }
194 // Find the last task currently queued in the scheduler queue and tick
195 // till that time.
196 const startTime = this._currentTickTime;
197 const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1];
198 this.tick(lastTask.endTime - startTime, doTick, { processNewMacroTasksSynchronously: false });
199 return this._currentTickTime - startTime;
200 }
201 flush(limit = 20, flushPeriodic = false, doTick) {
202 if (flushPeriodic) {
203 return this.flushPeriodic(doTick);
204 }
205 else {
206 return this.flushNonPeriodic(limit, doTick);
207 }
208 }
209 flushPeriodic(doTick) {
210 if (this._schedulerQueue.length === 0) {
211 return 0;
212 }
213 // Find the last task currently queued in the scheduler queue and tick
214 // till that time.
215 const startTime = this._currentTickTime;
216 const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1];
217 this.tick(lastTask.endTime - startTime, doTick);
218 return this._currentTickTime - startTime;
219 }
220 flushNonPeriodic(limit, doTick) {
221 const startTime = this._currentTickTime;
222 let lastCurrentTime = 0;
223 let count = 0;
224 while (this._schedulerQueue.length > 0) {
225 count++;
226 if (count > limit) {
227 throw new Error('flush failed after reaching the limit of ' + limit +
228 ' tasks. Does your code use a polling timeout?');
229 }
230 // flush only non-periodic timers.
231 // If the only remaining tasks are periodic(or requestAnimationFrame), finish flushing.
232 if (this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame)
233 .length === 0) {
234 break;
235 }
236 const current = this._schedulerQueue.shift();
237 lastCurrentTime = this._currentTickTime;
238 this._currentTickTime = current.endTime;
239 if (doTick) {
240 // Update any secondary schedulers like Jasmine mock Date.
241 doTick(this._currentTickTime - lastCurrentTime);
242 }
243 const retval = current.func.apply(global, current.args);
244 if (!retval) {
245 // Uncaught exception in the current scheduled function. Stop processing the queue.
246 break;
247 }
248 }
249 return this._currentTickTime - startTime;
250 }
251 }
252 // Next scheduler id.
253 Scheduler.nextId = 1;
254 class FakeAsyncTestZoneSpec {
255 constructor(namePrefix, trackPendingRequestAnimationFrame = false, macroTaskOptions) {
256 this.trackPendingRequestAnimationFrame = trackPendingRequestAnimationFrame;
257 this.macroTaskOptions = macroTaskOptions;
258 this._scheduler = new Scheduler();
259 this._microtasks = [];
260 this._lastError = null;
261 this._uncaughtPromiseErrors = Promise[Zone.__symbol__('uncaughtPromiseErrors')];
262 this.pendingPeriodicTimers = [];
263 this.pendingTimers = [];
264 this.patchDateLocked = false;
265 this.properties = { 'FakeAsyncTestZoneSpec': this };
266 this.name = 'fakeAsyncTestZone for ' + namePrefix;
267 // in case user can't access the construction of FakeAsyncTestSpec
268 // user can also define macroTaskOptions by define a global variable.
269 if (!this.macroTaskOptions) {
270 this.macroTaskOptions = global[Zone.__symbol__('FakeAsyncTestMacroTask')];
271 }
272 }
273 static assertInZone() {
274 if (Zone.current.get('FakeAsyncTestZoneSpec') == null) {
275 throw new Error('The code should be running in the fakeAsync zone to call this function');
276 }
277 }
278 _fnAndFlush(fn, completers) {
279 return (...args) => {
280 fn.apply(global, args);
281 if (this._lastError === null) { // Success
282 if (completers.onSuccess != null) {
283 completers.onSuccess.apply(global);
284 }
285 // Flush microtasks only on success.
286 this.flushMicrotasks();
287 }
288 else { // Failure
289 if (completers.onError != null) {
290 completers.onError.apply(global);
291 }
292 }
293 // Return true if there were no errors, false otherwise.
294 return this._lastError === null;
295 };
296 }
297 static _removeTimer(timers, id) {
298 let index = timers.indexOf(id);
299 if (index > -1) {
300 timers.splice(index, 1);
301 }
302 }
303 _dequeueTimer(id) {
304 return () => {
305 FakeAsyncTestZoneSpec._removeTimer(this.pendingTimers, id);
306 };
307 }
308 _requeuePeriodicTimer(fn, interval, args, id) {
309 return () => {
310 // Requeue the timer callback if it's not been canceled.
311 if (this.pendingPeriodicTimers.indexOf(id) !== -1) {
312 this._scheduler.scheduleFunction(fn, interval, { args, isPeriodic: true, id, isRequeuePeriodic: true });
313 }
314 };
315 }
316 _dequeuePeriodicTimer(id) {
317 return () => {
318 FakeAsyncTestZoneSpec._removeTimer(this.pendingPeriodicTimers, id);
319 };
320 }
321 _setTimeout(fn, delay, args, isTimer = true) {
322 let removeTimerFn = this._dequeueTimer(Scheduler.nextId);
323 // Queue the callback and dequeue the timer on success and error.
324 let cb = this._fnAndFlush(fn, { onSuccess: removeTimerFn, onError: removeTimerFn });
325 let id = this._scheduler.scheduleFunction(cb, delay, { args, isRequestAnimationFrame: !isTimer });
326 if (isTimer) {
327 this.pendingTimers.push(id);
328 }
329 return id;
330 }
331 _clearTimeout(id) {
332 FakeAsyncTestZoneSpec._removeTimer(this.pendingTimers, id);
333 this._scheduler.removeScheduledFunctionWithId(id);
334 }
335 _setInterval(fn, interval, args) {
336 let id = Scheduler.nextId;
337 let completers = { onSuccess: null, onError: this._dequeuePeriodicTimer(id) };
338 let cb = this._fnAndFlush(fn, completers);
339 // Use the callback created above to requeue on success.
340 completers.onSuccess = this._requeuePeriodicTimer(cb, interval, args, id);
341 // Queue the callback and dequeue the periodic timer only on error.
342 this._scheduler.scheduleFunction(cb, interval, { args, isPeriodic: true });
343 this.pendingPeriodicTimers.push(id);
344 return id;
345 }
346 _clearInterval(id) {
347 FakeAsyncTestZoneSpec._removeTimer(this.pendingPeriodicTimers, id);
348 this._scheduler.removeScheduledFunctionWithId(id);
349 }
350 _resetLastErrorAndThrow() {
351 let error = this._lastError || this._uncaughtPromiseErrors[0];
352 this._uncaughtPromiseErrors.length = 0;
353 this._lastError = null;
354 throw error;
355 }
356 getCurrentTickTime() {
357 return this._scheduler.getCurrentTickTime();
358 }
359 getFakeSystemTime() {
360 return this._scheduler.getFakeSystemTime();
361 }
362 setFakeBaseSystemTime(realTime) {
363 this._scheduler.setFakeBaseSystemTime(realTime);
364 }
365 getRealSystemTime() {
366 return this._scheduler.getRealSystemTime();
367 }
368 static patchDate() {
369 if (!!global[Zone.__symbol__('disableDatePatching')]) {
370 // we don't want to patch global Date
371 // because in some case, global Date
372 // is already being patched, we need to provide
373 // an option to let user still use their
374 // own version of Date.
375 return;
376 }
377 if (global['Date'] === FakeDate) {
378 // already patched
379 return;
380 }
381 global['Date'] = FakeDate;
382 FakeDate.prototype = OriginalDate.prototype;
383 // try check and reset timers
384 // because jasmine.clock().install() may
385 // have replaced the global timer
386 FakeAsyncTestZoneSpec.checkTimerPatch();
387 }
388 static resetDate() {
389 if (global['Date'] === FakeDate) {
390 global['Date'] = OriginalDate;
391 }
392 }
393 static checkTimerPatch() {
394 if (global.setTimeout !== timers.setTimeout) {
395 global.setTimeout = timers.setTimeout;
396 global.clearTimeout = timers.clearTimeout;
397 }
398 if (global.setInterval !== timers.setInterval) {
399 global.setInterval = timers.setInterval;
400 global.clearInterval = timers.clearInterval;
401 }
402 }
403 lockDatePatch() {
404 this.patchDateLocked = true;
405 FakeAsyncTestZoneSpec.patchDate();
406 }
407 unlockDatePatch() {
408 this.patchDateLocked = false;
409 FakeAsyncTestZoneSpec.resetDate();
410 }
411 tickToNext(steps = 1, doTick, tickOptions = { processNewMacroTasksSynchronously: true }) {
412 if (steps <= 0) {
413 return;
414 }
415 FakeAsyncTestZoneSpec.assertInZone();
416 this.flushMicrotasks();
417 this._scheduler.tickToNext(steps, doTick, tickOptions);
418 if (this._lastError !== null) {
419 this._resetLastErrorAndThrow();
420 }
421 }
422 tick(millis = 0, doTick, tickOptions = { processNewMacroTasksSynchronously: true }) {
423 FakeAsyncTestZoneSpec.assertInZone();
424 this.flushMicrotasks();
425 this._scheduler.tick(millis, doTick, tickOptions);
426 if (this._lastError !== null) {
427 this._resetLastErrorAndThrow();
428 }
429 }
430 flushMicrotasks() {
431 FakeAsyncTestZoneSpec.assertInZone();
432 const flushErrors = () => {
433 if (this._lastError !== null || this._uncaughtPromiseErrors.length) {
434 // If there is an error stop processing the microtask queue and rethrow the error.
435 this._resetLastErrorAndThrow();
436 }
437 };
438 while (this._microtasks.length > 0) {
439 let microtask = this._microtasks.shift();
440 microtask.func.apply(microtask.target, microtask.args);
441 }
442 flushErrors();
443 }
444 flush(limit, flushPeriodic, doTick) {
445 FakeAsyncTestZoneSpec.assertInZone();
446 this.flushMicrotasks();
447 const elapsed = this._scheduler.flush(limit, flushPeriodic, doTick);
448 if (this._lastError !== null) {
449 this._resetLastErrorAndThrow();
450 }
451 return elapsed;
452 }
453 flushOnlyPendingTimers(doTick) {
454 FakeAsyncTestZoneSpec.assertInZone();
455 this.flushMicrotasks();
456 const elapsed = this._scheduler.flushOnlyPendingTimers(doTick);
457 if (this._lastError !== null) {
458 this._resetLastErrorAndThrow();
459 }
460 return elapsed;
461 }
462 removeAllTimers() {
463 FakeAsyncTestZoneSpec.assertInZone();
464 this._scheduler.removeAll();
465 this.pendingPeriodicTimers = [];
466 this.pendingTimers = [];
467 }
468 getTimerCount() {
469 return this._scheduler.getTimerCount() + this._microtasks.length;
470 }
471 onScheduleTask(delegate, current, target, task) {
472 switch (task.type) {
473 case 'microTask':
474 let args = task.data && task.data.args;
475 // should pass additional arguments to callback if have any
476 // currently we know process.nextTick will have such additional
477 // arguments
478 let additionalArgs;
479 if (args) {
480 let callbackIndex = task.data.cbIdx;
481 if (typeof args.length === 'number' && args.length > callbackIndex + 1) {
482 additionalArgs = Array.prototype.slice.call(args, callbackIndex + 1);
483 }
484 }
485 this._microtasks.push({
486 func: task.invoke,
487 args: additionalArgs,
488 target: task.data && task.data.target
489 });
490 break;
491 case 'macroTask':
492 switch (task.source) {
493 case 'setTimeout':
494 task.data['handleId'] = this._setTimeout(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2));
495 break;
496 case 'setImmediate':
497 task.data['handleId'] = this._setTimeout(task.invoke, 0, Array.prototype.slice.call(task.data['args'], 1));
498 break;
499 case 'setInterval':
500 task.data['handleId'] = this._setInterval(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2));
501 break;
502 case 'XMLHttpRequest.send':
503 throw new Error('Cannot make XHRs from within a fake async test. Request URL: ' +
504 task.data['url']);
505 case 'requestAnimationFrame':
506 case 'webkitRequestAnimationFrame':
507 case 'mozRequestAnimationFrame':
508 // Simulate a requestAnimationFrame by using a setTimeout with 16 ms.
509 // (60 frames per second)
510 task.data['handleId'] = this._setTimeout(task.invoke, 16, task.data['args'], this.trackPendingRequestAnimationFrame);
511 break;
512 default:
513 // user can define which macroTask they want to support by passing
514 // macroTaskOptions
515 const macroTaskOption = this.findMacroTaskOption(task);
516 if (macroTaskOption) {
517 const args = task.data && task.data['args'];
518 const delay = args && args.length > 1 ? args[1] : 0;
519 let callbackArgs = macroTaskOption.callbackArgs ? macroTaskOption.callbackArgs : args;
520 if (!!macroTaskOption.isPeriodic) {
521 // periodic macroTask, use setInterval to simulate
522 task.data['handleId'] = this._setInterval(task.invoke, delay, callbackArgs);
523 task.data.isPeriodic = true;
524 }
525 else {
526 // not periodic, use setTimeout to simulate
527 task.data['handleId'] = this._setTimeout(task.invoke, delay, callbackArgs);
528 }
529 break;
530 }
531 throw new Error('Unknown macroTask scheduled in fake async test: ' + task.source);
532 }
533 break;
534 case 'eventTask':
535 task = delegate.scheduleTask(target, task);
536 break;
537 }
538 return task;
539 }
540 onCancelTask(delegate, current, target, task) {
541 switch (task.source) {
542 case 'setTimeout':
543 case 'requestAnimationFrame':
544 case 'webkitRequestAnimationFrame':
545 case 'mozRequestAnimationFrame':
546 return this._clearTimeout(task.data['handleId']);
547 case 'setInterval':
548 return this._clearInterval(task.data['handleId']);
549 default:
550 // user can define which macroTask they want to support by passing
551 // macroTaskOptions
552 const macroTaskOption = this.findMacroTaskOption(task);
553 if (macroTaskOption) {
554 const handleId = task.data['handleId'];
555 return macroTaskOption.isPeriodic ? this._clearInterval(handleId) :
556 this._clearTimeout(handleId);
557 }
558 return delegate.cancelTask(target, task);
559 }
560 }
561 onInvoke(delegate, current, target, callback, applyThis, applyArgs, source) {
562 try {
563 FakeAsyncTestZoneSpec.patchDate();
564 return delegate.invoke(target, callback, applyThis, applyArgs, source);
565 }
566 finally {
567 if (!this.patchDateLocked) {
568 FakeAsyncTestZoneSpec.resetDate();
569 }
570 }
571 }
572 findMacroTaskOption(task) {
573 if (!this.macroTaskOptions) {
574 return null;
575 }
576 for (let i = 0; i < this.macroTaskOptions.length; i++) {
577 const macroTaskOption = this.macroTaskOptions[i];
578 if (macroTaskOption.source === task.source) {
579 return macroTaskOption;
580 }
581 }
582 return null;
583 }
584 onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
585 this._lastError = error;
586 return false; // Don't propagate error to parent zone.
587 }
588 }
589 // Export the class so that new instances can be created with proper
590 // constructor params.
591 Zone['FakeAsyncTestZoneSpec'] = FakeAsyncTestZoneSpec;
592})(typeof window === 'object' && window || typeof self === 'object' && self || global);
593Zone.__load_patch('fakeasync', (global, Zone, api) => {
594 const FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec'];
595 function getProxyZoneSpec() {
596 return Zone && Zone['ProxyZoneSpec'];
597 }
598 let _fakeAsyncTestZoneSpec = null;
599 /**
600 * Clears out the shared fake async zone for a test.
601 * To be called in a global `beforeEach`.
602 *
603 * @experimental
604 */
605 function resetFakeAsyncZone() {
606 if (_fakeAsyncTestZoneSpec) {
607 _fakeAsyncTestZoneSpec.unlockDatePatch();
608 }
609 _fakeAsyncTestZoneSpec = null;
610 // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset.
611 getProxyZoneSpec() && getProxyZoneSpec().assertPresent().resetDelegate();
612 }
613 /**
614 * Wraps a function to be executed in the fakeAsync zone:
615 * - microtasks are manually executed by calling `flushMicrotasks()`,
616 * - timers are synchronous, `tick()` simulates the asynchronous passage of time.
617 *
618 * If there are any pending timers at the end of the function, an exception will be thrown.
619 *
620 * Can be used to wrap inject() calls.
621 *
622 * ## Example
623 *
624 * {@example core/testing/ts/fake_async.ts region='basic'}
625 *
626 * @param fn
627 * @returns The function wrapped to be executed in the fakeAsync zone
628 *
629 * @experimental
630 */
631 function fakeAsync(fn) {
632 // Not using an arrow function to preserve context passed from call site
633 const fakeAsyncFn = function (...args) {
634 const ProxyZoneSpec = getProxyZoneSpec();
635 if (!ProxyZoneSpec) {
636 throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' +
637 'Please make sure that your environment includes zone.js/dist/proxy.js');
638 }
639 const proxyZoneSpec = ProxyZoneSpec.assertPresent();
640 if (Zone.current.get('FakeAsyncTestZoneSpec')) {
641 throw new Error('fakeAsync() calls can not be nested');
642 }
643 try {
644 // in case jasmine.clock init a fakeAsyncTestZoneSpec
645 if (!_fakeAsyncTestZoneSpec) {
646 if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) {
647 throw new Error('fakeAsync() calls can not be nested');
648 }
649 _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec();
650 }
651 let res;
652 const lastProxyZoneSpec = proxyZoneSpec.getDelegate();
653 proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec);
654 _fakeAsyncTestZoneSpec.lockDatePatch();
655 try {
656 res = fn.apply(this, args);
657 flushMicrotasks();
658 }
659 finally {
660 proxyZoneSpec.setDelegate(lastProxyZoneSpec);
661 }
662 if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) {
663 throw new Error(`${_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length} ` +
664 `periodic timer(s) still in the queue.`);
665 }
666 if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) {
667 throw new Error(`${_fakeAsyncTestZoneSpec.pendingTimers.length} timer(s) still in the queue.`);
668 }
669 return res;
670 }
671 finally {
672 resetFakeAsyncZone();
673 }
674 };
675 fakeAsyncFn.isFakeAsync = true;
676 return fakeAsyncFn;
677 }
678 function _getFakeAsyncZoneSpec() {
679 if (_fakeAsyncTestZoneSpec == null) {
680 _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
681 if (_fakeAsyncTestZoneSpec == null) {
682 throw new Error('The code should be running in the fakeAsync zone to call this function');
683 }
684 }
685 return _fakeAsyncTestZoneSpec;
686 }
687 /**
688 * Simulates the asynchronous passage of time for the timers in the fakeAsync zone.
689 *
690 * The microtasks queue is drained at the very start of this function and after any timer callback
691 * has been executed.
692 *
693 * ## Example
694 *
695 * {@example core/testing/ts/fake_async.ts region='basic'}
696 *
697 * @experimental
698 */
699 function tick(millis = 0, ignoreNestedTimeout = false) {
700 _getFakeAsyncZoneSpec().tick(millis, null, ignoreNestedTimeout);
701 }
702 /**
703 * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by
704 * draining the macrotask queue until it is empty. The returned value is the milliseconds
705 * of time that would have been elapsed.
706 *
707 * @param maxTurns
708 * @returns The simulated time elapsed, in millis.
709 *
710 * @experimental
711 */
712 function flush(maxTurns) {
713 return _getFakeAsyncZoneSpec().flush(maxTurns);
714 }
715 /**
716 * Discard all remaining periodic tasks.
717 *
718 * @experimental
719 */
720 function discardPeriodicTasks() {
721 const zoneSpec = _getFakeAsyncZoneSpec();
722 const pendingTimers = zoneSpec.pendingPeriodicTimers;
723 zoneSpec.pendingPeriodicTimers.length = 0;
724 }
725 /**
726 * Flush any pending microtasks.
727 *
728 * @experimental
729 */
730 function flushMicrotasks() {
731 _getFakeAsyncZoneSpec().flushMicrotasks();
732 }
733 Zone[api.symbol('fakeAsyncTest')] =
734 { resetFakeAsyncZone, flushMicrotasks, discardPeriodicTasks, tick, flush, fakeAsync };
735}, true);
Note: See TracBrowser for help on using the repository browser.