Initial OpenECOMP policy/engine commit
[policy/engine.git] / ecomp-sdk-app / src / main / webapp / app / fusion / external / angular-1.5 / angular-mocks.js
1 /**
2  * @license AngularJS v1.5.0
3  * (c) 2010-2016 Google, Inc. http://angularjs.org
4  * License: MIT
5  */
6 (function(window, angular, undefined) {
7
8 'use strict';
9
10 /**
11  * @ngdoc object
12  * @name angular.mock
13  * @description
14  *
15  * Namespace from 'angular-mocks.js' which contains testing related code.
16  */
17 angular.mock = {};
18
19 /**
20  * ! This is a private undocumented service !
21  *
22  * @name $browser
23  *
24  * @description
25  * This service is a mock implementation of {@link ng.$browser}. It provides fake
26  * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
27  * cookies, etc...
28  *
29  * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
30  * that there are several helper methods available which can be used in tests.
31  */
32 angular.mock.$BrowserProvider = function() {
33   this.$get = function() {
34     return new angular.mock.$Browser();
35   };
36 };
37
38 angular.mock.$Browser = function() {
39   var self = this;
40
41   this.isMock = true;
42   self.$$url = "http://server/";
43   self.$$lastUrl = self.$$url; // used by url polling fn
44   self.pollFns = [];
45
46   // TODO(vojta): remove this temporary api
47   self.$$completeOutstandingRequest = angular.noop;
48   self.$$incOutstandingRequestCount = angular.noop;
49
50
51   // register url polling fn
52
53   self.onUrlChange = function(listener) {
54     self.pollFns.push(
55       function() {
56         if (self.$$lastUrl !== self.$$url || self.$$state !== self.$$lastState) {
57           self.$$lastUrl = self.$$url;
58           self.$$lastState = self.$$state;
59           listener(self.$$url, self.$$state);
60         }
61       }
62     );
63
64     return listener;
65   };
66
67   self.$$applicationDestroyed = angular.noop;
68   self.$$checkUrlChange = angular.noop;
69
70   self.deferredFns = [];
71   self.deferredNextId = 0;
72
73   self.defer = function(fn, delay) {
74     delay = delay || 0;
75     self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
76     self.deferredFns.sort(function(a, b) { return a.time - b.time;});
77     return self.deferredNextId++;
78   };
79
80
81   /**
82    * @name $browser#defer.now
83    *
84    * @description
85    * Current milliseconds mock time.
86    */
87   self.defer.now = 0;
88
89
90   self.defer.cancel = function(deferId) {
91     var fnIndex;
92
93     angular.forEach(self.deferredFns, function(fn, index) {
94       if (fn.id === deferId) fnIndex = index;
95     });
96
97     if (angular.isDefined(fnIndex)) {
98       self.deferredFns.splice(fnIndex, 1);
99       return true;
100     }
101
102     return false;
103   };
104
105
106   /**
107    * @name $browser#defer.flush
108    *
109    * @description
110    * Flushes all pending requests and executes the defer callbacks.
111    *
112    * @param {number=} number of milliseconds to flush. See {@link #defer.now}
113    */
114   self.defer.flush = function(delay) {
115     if (angular.isDefined(delay)) {
116       self.defer.now += delay;
117     } else {
118       if (self.deferredFns.length) {
119         self.defer.now = self.deferredFns[self.deferredFns.length - 1].time;
120       } else {
121         throw new Error('No deferred tasks to be flushed');
122       }
123     }
124
125     while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
126       self.deferredFns.shift().fn();
127     }
128   };
129
130   self.$$baseHref = '/';
131   self.baseHref = function() {
132     return this.$$baseHref;
133   };
134 };
135 angular.mock.$Browser.prototype = {
136
137 /**
138   * @name $browser#poll
139   *
140   * @description
141   * run all fns in pollFns
142   */
143   poll: function poll() {
144     angular.forEach(this.pollFns, function(pollFn) {
145       pollFn();
146     });
147   },
148
149   url: function(url, replace, state) {
150     if (angular.isUndefined(state)) {
151       state = null;
152     }
153     if (url) {
154       this.$$url = url;
155       // Native pushState serializes & copies the object; simulate it.
156       this.$$state = angular.copy(state);
157       return this;
158     }
159
160     return this.$$url;
161   },
162
163   state: function() {
164     return this.$$state;
165   },
166
167   notifyWhenNoOutstandingRequests: function(fn) {
168     fn();
169   }
170 };
171
172
173 /**
174  * @ngdoc provider
175  * @name $exceptionHandlerProvider
176  *
177  * @description
178  * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
179  * passed to the `$exceptionHandler`.
180  */
181
182 /**
183  * @ngdoc service
184  * @name $exceptionHandler
185  *
186  * @description
187  * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
188  * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
189  * information.
190  *
191  *
192  * ```js
193  *   describe('$exceptionHandlerProvider', function() {
194  *
195  *     it('should capture log messages and exceptions', function() {
196  *
197  *       module(function($exceptionHandlerProvider) {
198  *         $exceptionHandlerProvider.mode('log');
199  *       });
200  *
201  *       inject(function($log, $exceptionHandler, $timeout) {
202  *         $timeout(function() { $log.log(1); });
203  *         $timeout(function() { $log.log(2); throw 'banana peel'; });
204  *         $timeout(function() { $log.log(3); });
205  *         expect($exceptionHandler.errors).toEqual([]);
206  *         expect($log.assertEmpty());
207  *         $timeout.flush();
208  *         expect($exceptionHandler.errors).toEqual(['banana peel']);
209  *         expect($log.log.logs).toEqual([[1], [2], [3]]);
210  *       });
211  *     });
212  *   });
213  * ```
214  */
215
216 angular.mock.$ExceptionHandlerProvider = function() {
217   var handler;
218
219   /**
220    * @ngdoc method
221    * @name $exceptionHandlerProvider#mode
222    *
223    * @description
224    * Sets the logging mode.
225    *
226    * @param {string} mode Mode of operation, defaults to `rethrow`.
227    *
228    *   - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
229    *            mode stores an array of errors in `$exceptionHandler.errors`, to allow later
230    *            assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
231    *            {@link ngMock.$log#reset reset()}
232    *   - `rethrow`: If any errors are passed to the handler in tests, it typically means that there
233    *                is a bug in the application or test, so this mock will make these tests fail.
234    *                For any implementations that expect exceptions to be thrown, the `rethrow` mode
235    *                will also maintain a log of thrown errors.
236    */
237   this.mode = function(mode) {
238
239     switch (mode) {
240       case 'log':
241       case 'rethrow':
242         var errors = [];
243         handler = function(e) {
244           if (arguments.length == 1) {
245             errors.push(e);
246           } else {
247             errors.push([].slice.call(arguments, 0));
248           }
249           if (mode === "rethrow") {
250             throw e;
251           }
252         };
253         handler.errors = errors;
254         break;
255       default:
256         throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
257     }
258   };
259
260   this.$get = function() {
261     return handler;
262   };
263
264   this.mode('rethrow');
265 };
266
267
268 /**
269  * @ngdoc service
270  * @name $log
271  *
272  * @description
273  * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
274  * (one array per logging level). These arrays are exposed as `logs` property of each of the
275  * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
276  *
277  */
278 angular.mock.$LogProvider = function() {
279   var debug = true;
280
281   function concat(array1, array2, index) {
282     return array1.concat(Array.prototype.slice.call(array2, index));
283   }
284
285   this.debugEnabled = function(flag) {
286     if (angular.isDefined(flag)) {
287       debug = flag;
288       return this;
289     } else {
290       return debug;
291     }
292   };
293
294   this.$get = function() {
295     var $log = {
296       log: function() { $log.log.logs.push(concat([], arguments, 0)); },
297       warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
298       info: function() { $log.info.logs.push(concat([], arguments, 0)); },
299       error: function() { $log.error.logs.push(concat([], arguments, 0)); },
300       debug: function() {
301         if (debug) {
302           $log.debug.logs.push(concat([], arguments, 0));
303         }
304       }
305     };
306
307     /**
308      * @ngdoc method
309      * @name $log#reset
310      *
311      * @description
312      * Reset all of the logging arrays to empty.
313      */
314     $log.reset = function() {
315       /**
316        * @ngdoc property
317        * @name $log#log.logs
318        *
319        * @description
320        * Array of messages logged using {@link ng.$log#log `log()`}.
321        *
322        * @example
323        * ```js
324        * $log.log('Some Log');
325        * var first = $log.log.logs.unshift();
326        * ```
327        */
328       $log.log.logs = [];
329       /**
330        * @ngdoc property
331        * @name $log#info.logs
332        *
333        * @description
334        * Array of messages logged using {@link ng.$log#info `info()`}.
335        *
336        * @example
337        * ```js
338        * $log.info('Some Info');
339        * var first = $log.info.logs.unshift();
340        * ```
341        */
342       $log.info.logs = [];
343       /**
344        * @ngdoc property
345        * @name $log#warn.logs
346        *
347        * @description
348        * Array of messages logged using {@link ng.$log#warn `warn()`}.
349        *
350        * @example
351        * ```js
352        * $log.warn('Some Warning');
353        * var first = $log.warn.logs.unshift();
354        * ```
355        */
356       $log.warn.logs = [];
357       /**
358        * @ngdoc property
359        * @name $log#error.logs
360        *
361        * @description
362        * Array of messages logged using {@link ng.$log#error `error()`}.
363        *
364        * @example
365        * ```js
366        * $log.error('Some Error');
367        * var first = $log.error.logs.unshift();
368        * ```
369        */
370       $log.error.logs = [];
371         /**
372        * @ngdoc property
373        * @name $log#debug.logs
374        *
375        * @description
376        * Array of messages logged using {@link ng.$log#debug `debug()`}.
377        *
378        * @example
379        * ```js
380        * $log.debug('Some Error');
381        * var first = $log.debug.logs.unshift();
382        * ```
383        */
384       $log.debug.logs = [];
385     };
386
387     /**
388      * @ngdoc method
389      * @name $log#assertEmpty
390      *
391      * @description
392      * Assert that all of the logging methods have no logged messages. If any messages are present,
393      * an exception is thrown.
394      */
395     $log.assertEmpty = function() {
396       var errors = [];
397       angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
398         angular.forEach($log[logLevel].logs, function(log) {
399           angular.forEach(log, function(logItem) {
400             errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
401                         (logItem.stack || ''));
402           });
403         });
404       });
405       if (errors.length) {
406         errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or " +
407           "an expected log message was not checked and removed:");
408         errors.push('');
409         throw new Error(errors.join('\n---------\n'));
410       }
411     };
412
413     $log.reset();
414     return $log;
415   };
416 };
417
418
419 /**
420  * @ngdoc service
421  * @name $interval
422  *
423  * @description
424  * Mock implementation of the $interval service.
425  *
426  * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
427  * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
428  * time.
429  *
430  * @param {function()} fn A function that should be called repeatedly.
431  * @param {number} delay Number of milliseconds between each function call.
432  * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
433  *   indefinitely.
434  * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
435  *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
436  * @param {...*=} Pass additional parameters to the executed function.
437  * @returns {promise} A promise which will be notified on each iteration.
438  */
439 angular.mock.$IntervalProvider = function() {
440   this.$get = ['$browser', '$rootScope', '$q', '$$q',
441        function($browser,   $rootScope,   $q,   $$q) {
442     var repeatFns = [],
443         nextRepeatId = 0,
444         now = 0;
445
446     var $interval = function(fn, delay, count, invokeApply) {
447       var hasParams = arguments.length > 4,
448           args = hasParams ? Array.prototype.slice.call(arguments, 4) : [],
449           iteration = 0,
450           skipApply = (angular.isDefined(invokeApply) && !invokeApply),
451           deferred = (skipApply ? $$q : $q).defer(),
452           promise = deferred.promise;
453
454       count = (angular.isDefined(count)) ? count : 0;
455       promise.then(null, null, (!hasParams) ? fn : function() {
456         fn.apply(null, args);
457       });
458
459       promise.$$intervalId = nextRepeatId;
460
461       function tick() {
462         deferred.notify(iteration++);
463
464         if (count > 0 && iteration >= count) {
465           var fnIndex;
466           deferred.resolve(iteration);
467
468           angular.forEach(repeatFns, function(fn, index) {
469             if (fn.id === promise.$$intervalId) fnIndex = index;
470           });
471
472           if (angular.isDefined(fnIndex)) {
473             repeatFns.splice(fnIndex, 1);
474           }
475         }
476
477         if (skipApply) {
478           $browser.defer.flush();
479         } else {
480           $rootScope.$apply();
481         }
482       }
483
484       repeatFns.push({
485         nextTime:(now + delay),
486         delay: delay,
487         fn: tick,
488         id: nextRepeatId,
489         deferred: deferred
490       });
491       repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
492
493       nextRepeatId++;
494       return promise;
495     };
496     /**
497      * @ngdoc method
498      * @name $interval#cancel
499      *
500      * @description
501      * Cancels a task associated with the `promise`.
502      *
503      * @param {promise} promise A promise from calling the `$interval` function.
504      * @returns {boolean} Returns `true` if the task was successfully cancelled.
505      */
506     $interval.cancel = function(promise) {
507       if (!promise) return false;
508       var fnIndex;
509
510       angular.forEach(repeatFns, function(fn, index) {
511         if (fn.id === promise.$$intervalId) fnIndex = index;
512       });
513
514       if (angular.isDefined(fnIndex)) {
515         repeatFns[fnIndex].deferred.reject('canceled');
516         repeatFns.splice(fnIndex, 1);
517         return true;
518       }
519
520       return false;
521     };
522
523     /**
524      * @ngdoc method
525      * @name $interval#flush
526      * @description
527      *
528      * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
529      *
530      * @param {number=} millis maximum timeout amount to flush up until.
531      *
532      * @return {number} The amount of time moved forward.
533      */
534     $interval.flush = function(millis) {
535       now += millis;
536       while (repeatFns.length && repeatFns[0].nextTime <= now) {
537         var task = repeatFns[0];
538         task.fn();
539         task.nextTime += task.delay;
540         repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
541       }
542       return millis;
543     };
544
545     return $interval;
546   }];
547 };
548
549
550 /* jshint -W101 */
551 /* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
552  * This directive should go inside the anonymous function but a bug in JSHint means that it would
553  * not be enacted early enough to prevent the warning.
554  */
555 var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
556
557 function jsonStringToDate(string) {
558   var match;
559   if (match = string.match(R_ISO8061_STR)) {
560     var date = new Date(0),
561         tzHour = 0,
562         tzMin  = 0;
563     if (match[9]) {
564       tzHour = toInt(match[9] + match[10]);
565       tzMin = toInt(match[9] + match[11]);
566     }
567     date.setUTCFullYear(toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
568     date.setUTCHours(toInt(match[4] || 0) - tzHour,
569                      toInt(match[5] || 0) - tzMin,
570                      toInt(match[6] || 0),
571                      toInt(match[7] || 0));
572     return date;
573   }
574   return string;
575 }
576
577 function toInt(str) {
578   return parseInt(str, 10);
579 }
580
581 function padNumber(num, digits, trim) {
582   var neg = '';
583   if (num < 0) {
584     neg =  '-';
585     num = -num;
586   }
587   num = '' + num;
588   while (num.length < digits) num = '0' + num;
589   if (trim) {
590     num = num.substr(num.length - digits);
591   }
592   return neg + num;
593 }
594
595
596 /**
597  * @ngdoc type
598  * @name angular.mock.TzDate
599  * @description
600  *
601  * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
602  *
603  * Mock of the Date type which has its timezone specified via constructor arg.
604  *
605  * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
606  * offset, so that we can test code that depends on local timezone settings without dependency on
607  * the time zone settings of the machine where the code is running.
608  *
609  * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
610  * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
611  *
612  * @example
613  * !!!! WARNING !!!!!
614  * This is not a complete Date object so only methods that were implemented can be called safely.
615  * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
616  *
617  * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
618  * incomplete we might be missing some non-standard methods. This can result in errors like:
619  * "Date.prototype.foo called on incompatible Object".
620  *
621  * ```js
622  * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
623  * newYearInBratislava.getTimezoneOffset() => -60;
624  * newYearInBratislava.getFullYear() => 2010;
625  * newYearInBratislava.getMonth() => 0;
626  * newYearInBratislava.getDate() => 1;
627  * newYearInBratislava.getHours() => 0;
628  * newYearInBratislava.getMinutes() => 0;
629  * newYearInBratislava.getSeconds() => 0;
630  * ```
631  *
632  */
633 angular.mock.TzDate = function(offset, timestamp) {
634   var self = new Date(0);
635   if (angular.isString(timestamp)) {
636     var tsStr = timestamp;
637
638     self.origDate = jsonStringToDate(timestamp);
639
640     timestamp = self.origDate.getTime();
641     if (isNaN(timestamp)) {
642       throw {
643         name: "Illegal Argument",
644         message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
645       };
646     }
647   } else {
648     self.origDate = new Date(timestamp);
649   }
650
651   var localOffset = new Date(timestamp).getTimezoneOffset();
652   self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
653   self.date = new Date(timestamp + self.offsetDiff);
654
655   self.getTime = function() {
656     return self.date.getTime() - self.offsetDiff;
657   };
658
659   self.toLocaleDateString = function() {
660     return self.date.toLocaleDateString();
661   };
662
663   self.getFullYear = function() {
664     return self.date.getFullYear();
665   };
666
667   self.getMonth = function() {
668     return self.date.getMonth();
669   };
670
671   self.getDate = function() {
672     return self.date.getDate();
673   };
674
675   self.getHours = function() {
676     return self.date.getHours();
677   };
678
679   self.getMinutes = function() {
680     return self.date.getMinutes();
681   };
682
683   self.getSeconds = function() {
684     return self.date.getSeconds();
685   };
686
687   self.getMilliseconds = function() {
688     return self.date.getMilliseconds();
689   };
690
691   self.getTimezoneOffset = function() {
692     return offset * 60;
693   };
694
695   self.getUTCFullYear = function() {
696     return self.origDate.getUTCFullYear();
697   };
698
699   self.getUTCMonth = function() {
700     return self.origDate.getUTCMonth();
701   };
702
703   self.getUTCDate = function() {
704     return self.origDate.getUTCDate();
705   };
706
707   self.getUTCHours = function() {
708     return self.origDate.getUTCHours();
709   };
710
711   self.getUTCMinutes = function() {
712     return self.origDate.getUTCMinutes();
713   };
714
715   self.getUTCSeconds = function() {
716     return self.origDate.getUTCSeconds();
717   };
718
719   self.getUTCMilliseconds = function() {
720     return self.origDate.getUTCMilliseconds();
721   };
722
723   self.getDay = function() {
724     return self.date.getDay();
725   };
726
727   // provide this method only on browsers that already have it
728   if (self.toISOString) {
729     self.toISOString = function() {
730       return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
731             padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
732             padNumber(self.origDate.getUTCDate(), 2) + 'T' +
733             padNumber(self.origDate.getUTCHours(), 2) + ':' +
734             padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
735             padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
736             padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
737     };
738   }
739
740   //hide all methods not implemented in this mock that the Date prototype exposes
741   var unimplementedMethods = ['getUTCDay',
742       'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
743       'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
744       'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
745       'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
746       'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
747
748   angular.forEach(unimplementedMethods, function(methodName) {
749     self[methodName] = function() {
750       throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
751     };
752   });
753
754   return self;
755 };
756
757 //make "tzDateInstance instanceof Date" return true
758 angular.mock.TzDate.prototype = Date.prototype;
759 /* jshint +W101 */
760
761
762 /**
763  * @ngdoc service
764  * @name $animate
765  *
766  * @description
767  * Mock implementation of the {@link ng.$animate `$animate`} service. Exposes two additional methods
768  * for testing animations.
769  */
770 angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
771
772   .config(['$provide', function($provide) {
773
774     $provide.factory('$$forceReflow', function() {
775       function reflowFn() {
776         reflowFn.totalReflows++;
777       }
778       reflowFn.totalReflows = 0;
779       return reflowFn;
780     });
781
782     $provide.factory('$$animateAsyncRun', function() {
783       var queue = [];
784       var queueFn = function() {
785         return function(fn) {
786           queue.push(fn);
787         };
788       };
789       queueFn.flush = function() {
790         if (queue.length === 0) return false;
791
792         for (var i = 0; i < queue.length; i++) {
793           queue[i]();
794         }
795         queue = [];
796
797         return true;
798       };
799       return queueFn;
800     });
801
802     $provide.decorator('$$animateJs', ['$delegate', function($delegate) {
803       var runners = [];
804
805       var animateJsConstructor = function() {
806         var animator = $delegate.apply($delegate, arguments);
807         // If no javascript animation is found, animator is undefined
808         if (animator) {
809           runners.push(animator);
810         }
811         return animator;
812       };
813
814       animateJsConstructor.$closeAndFlush = function() {
815         runners.forEach(function(runner) {
816           runner.end();
817         });
818         runners = [];
819       };
820
821       return animateJsConstructor;
822     }]);
823
824     $provide.decorator('$animateCss', ['$delegate', function($delegate) {
825       var runners = [];
826
827       var animateCssConstructor = function(element, options) {
828         var animator = $delegate(element, options);
829         runners.push(animator);
830         return animator;
831       };
832
833       animateCssConstructor.$closeAndFlush = function() {
834         runners.forEach(function(runner) {
835           runner.end();
836         });
837         runners = [];
838       };
839
840       return animateCssConstructor;
841     }]);
842
843     $provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF', '$animateCss', '$$animateJs',
844                                     '$$forceReflow', '$$animateAsyncRun', '$rootScope',
845                             function($delegate,   $timeout,   $browser,   $$rAF,   $animateCss,   $$animateJs,
846                                      $$forceReflow,   $$animateAsyncRun,  $rootScope) {
847       var animate = {
848         queue: [],
849         cancel: $delegate.cancel,
850         on: $delegate.on,
851         off: $delegate.off,
852         pin: $delegate.pin,
853         get reflows() {
854           return $$forceReflow.totalReflows;
855         },
856         enabled: $delegate.enabled,
857         /**
858          * @ngdoc method
859          * @name $animate#closeAndFlush
860          * @description
861          *
862          * This method will close all pending animations (both {@link ngAnimate#javascript-based-animations Javascript}
863          * and {@link ngAnimate.$animateCss CSS}) and it will also flush any remaining animation frames and/or callbacks.
864          */
865         closeAndFlush: function() {
866           // we allow the flush command to swallow the errors
867           // because depending on whether CSS or JS animations are
868           // used, there may not be a RAF flush. The primary flush
869           // at the end of this function must throw an exception
870           // because it will track if there were pending animations
871           this.flush(true);
872           $animateCss.$closeAndFlush();
873           $$animateJs.$closeAndFlush();
874           this.flush();
875         },
876         /**
877          * @ngdoc method
878          * @name $animate#flush
879          * @description
880          *
881          * This method is used to flush the pending callbacks and animation frames to either start
882          * an animation or conclude an animation. Note that this will not actually close an
883          * actively running animation (see {@link ngMock.$animate#closeAndFlush `closeAndFlush()`} for that).
884          */
885         flush: function(hideErrors) {
886           $rootScope.$digest();
887
888           var doNextRun, somethingFlushed = false;
889           do {
890             doNextRun = false;
891
892             if ($$rAF.queue.length) {
893               $$rAF.flush();
894               doNextRun = somethingFlushed = true;
895             }
896
897             if ($$animateAsyncRun.flush()) {
898               doNextRun = somethingFlushed = true;
899             }
900           } while (doNextRun);
901
902           if (!somethingFlushed && !hideErrors) {
903             throw new Error('No pending animations ready to be closed or flushed');
904           }
905
906           $rootScope.$digest();
907         }
908       };
909
910       angular.forEach(
911         ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {
912         animate[method] = function() {
913           animate.queue.push({
914             event: method,
915             element: arguments[0],
916             options: arguments[arguments.length - 1],
917             args: arguments
918           });
919           return $delegate[method].apply($delegate, arguments);
920         };
921       });
922
923       return animate;
924     }]);
925
926   }]);
927
928
929 /**
930  * @ngdoc function
931  * @name angular.mock.dump
932  * @description
933  *
934  * *NOTE*: this is not an injectable instance, just a globally available function.
935  *
936  * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
937  * debugging.
938  *
939  * This method is also available on window, where it can be used to display objects on debug
940  * console.
941  *
942  * @param {*} object - any object to turn into string.
943  * @return {string} a serialized string of the argument
944  */
945 angular.mock.dump = function(object) {
946   return serialize(object);
947
948   function serialize(object) {
949     var out;
950
951     if (angular.isElement(object)) {
952       object = angular.element(object);
953       out = angular.element('<div></div>');
954       angular.forEach(object, function(element) {
955         out.append(angular.element(element).clone());
956       });
957       out = out.html();
958     } else if (angular.isArray(object)) {
959       out = [];
960       angular.forEach(object, function(o) {
961         out.push(serialize(o));
962       });
963       out = '[ ' + out.join(', ') + ' ]';
964     } else if (angular.isObject(object)) {
965       if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
966         out = serializeScope(object);
967       } else if (object instanceof Error) {
968         out = object.stack || ('' + object.name + ': ' + object.message);
969       } else {
970         // TODO(i): this prevents methods being logged,
971         // we should have a better way to serialize objects
972         out = angular.toJson(object, true);
973       }
974     } else {
975       out = String(object);
976     }
977
978     return out;
979   }
980
981   function serializeScope(scope, offset) {
982     offset = offset ||  '  ';
983     var log = [offset + 'Scope(' + scope.$id + '): {'];
984     for (var key in scope) {
985       if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
986         log.push('  ' + key + ': ' + angular.toJson(scope[key]));
987       }
988     }
989     var child = scope.$$childHead;
990     while (child) {
991       log.push(serializeScope(child, offset + '  '));
992       child = child.$$nextSibling;
993     }
994     log.push('}');
995     return log.join('\n' + offset);
996   }
997 };
998
999 /**
1000  * @ngdoc service
1001  * @name $httpBackend
1002  * @description
1003  * Fake HTTP backend implementation suitable for unit testing applications that use the
1004  * {@link ng.$http $http service}.
1005  *
1006  * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
1007  * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
1008  *
1009  * During unit testing, we want our unit tests to run quickly and have no external dependencies so
1010  * we don’t want to send [XHR](https://developer.mozilla.org/en/xmlhttprequest) or
1011  * [JSONP](http://en.wikipedia.org/wiki/JSONP) requests to a real server. All we really need is
1012  * to verify whether a certain request has been sent or not, or alternatively just let the
1013  * application make requests, respond with pre-trained responses and assert that the end result is
1014  * what we expect it to be.
1015  *
1016  * This mock implementation can be used to respond with static or dynamic responses via the
1017  * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
1018  *
1019  * When an Angular application needs some data from a server, it calls the $http service, which
1020  * sends the request to a real server using $httpBackend service. With dependency injection, it is
1021  * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
1022  * the requests and respond with some testing data without sending a request to a real server.
1023  *
1024  * There are two ways to specify what test data should be returned as http responses by the mock
1025  * backend when the code under test makes http requests:
1026  *
1027  * - `$httpBackend.expect` - specifies a request expectation
1028  * - `$httpBackend.when` - specifies a backend definition
1029  *
1030  *
1031  * ## Request Expectations vs Backend Definitions
1032  *
1033  * Request expectations provide a way to make assertions about requests made by the application and
1034  * to define responses for those requests. The test will fail if the expected requests are not made
1035  * or they are made in the wrong order.
1036  *
1037  * Backend definitions allow you to define a fake backend for your application which doesn't assert
1038  * if a particular request was made or not, it just returns a trained response if a request is made.
1039  * The test will pass whether or not the request gets made during testing.
1040  *
1041  *
1042  * <table class="table">
1043  *   <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
1044  *   <tr>
1045  *     <th>Syntax</th>
1046  *     <td>.expect(...).respond(...)</td>
1047  *     <td>.when(...).respond(...)</td>
1048  *   </tr>
1049  *   <tr>
1050  *     <th>Typical usage</th>
1051  *     <td>strict unit tests</td>
1052  *     <td>loose (black-box) unit testing</td>
1053  *   </tr>
1054  *   <tr>
1055  *     <th>Fulfills multiple requests</th>
1056  *     <td>NO</td>
1057  *     <td>YES</td>
1058  *   </tr>
1059  *   <tr>
1060  *     <th>Order of requests matters</th>
1061  *     <td>YES</td>
1062  *     <td>NO</td>
1063  *   </tr>
1064  *   <tr>
1065  *     <th>Request required</th>
1066  *     <td>YES</td>
1067  *     <td>NO</td>
1068  *   </tr>
1069  *   <tr>
1070  *     <th>Response required</th>
1071  *     <td>optional (see below)</td>
1072  *     <td>YES</td>
1073  *   </tr>
1074  * </table>
1075  *
1076  * In cases where both backend definitions and request expectations are specified during unit
1077  * testing, the request expectations are evaluated first.
1078  *
1079  * If a request expectation has no response specified, the algorithm will search your backend
1080  * definitions for an appropriate response.
1081  *
1082  * If a request didn't match any expectation or if the expectation doesn't have the response
1083  * defined, the backend definitions are evaluated in sequential order to see if any of them match
1084  * the request. The response from the first matched definition is returned.
1085  *
1086  *
1087  * ## Flushing HTTP requests
1088  *
1089  * The $httpBackend used in production always responds to requests asynchronously. If we preserved
1090  * this behavior in unit testing, we'd have to create async unit tests, which are hard to write,
1091  * to follow and to maintain. But neither can the testing mock respond synchronously; that would
1092  * change the execution of the code under test. For this reason, the mock $httpBackend has a
1093  * `flush()` method, which allows the test to explicitly flush pending requests. This preserves
1094  * the async api of the backend, while allowing the test to execute synchronously.
1095  *
1096  *
1097  * ## Unit testing with mock $httpBackend
1098  * The following code shows how to setup and use the mock backend when unit testing a controller.
1099  * First we create the controller under test:
1100  *
1101   ```js
1102   // The module code
1103   angular
1104     .module('MyApp', [])
1105     .controller('MyController', MyController);
1106
1107   // The controller code
1108   function MyController($scope, $http) {
1109     var authToken;
1110
1111     $http.get('/auth.py').then(function(response) {
1112       authToken = response.headers('A-Token');
1113       $scope.user = response.data;
1114     });
1115
1116     $scope.saveMessage = function(message) {
1117       var headers = { 'Authorization': authToken };
1118       $scope.status = 'Saving...';
1119
1120       $http.post('/add-msg.py', message, { headers: headers } ).then(function(response) {
1121         $scope.status = '';
1122       }).catch(function() {
1123         $scope.status = 'Failed...';
1124       });
1125     };
1126   }
1127   ```
1128  *
1129  * Now we setup the mock backend and create the test specs:
1130  *
1131   ```js
1132     // testing controller
1133     describe('MyController', function() {
1134        var $httpBackend, $rootScope, createController, authRequestHandler;
1135
1136        // Set up the module
1137        beforeEach(module('MyApp'));
1138
1139        beforeEach(inject(function($injector) {
1140          // Set up the mock http service responses
1141          $httpBackend = $injector.get('$httpBackend');
1142          // backend definition common for all tests
1143          authRequestHandler = $httpBackend.when('GET', '/auth.py')
1144                                 .respond({userId: 'userX'}, {'A-Token': 'xxx'});
1145
1146          // Get hold of a scope (i.e. the root scope)
1147          $rootScope = $injector.get('$rootScope');
1148          // The $controller service is used to create instances of controllers
1149          var $controller = $injector.get('$controller');
1150
1151          createController = function() {
1152            return $controller('MyController', {'$scope' : $rootScope });
1153          };
1154        }));
1155
1156
1157        afterEach(function() {
1158          $httpBackend.verifyNoOutstandingExpectation();
1159          $httpBackend.verifyNoOutstandingRequest();
1160        });
1161
1162
1163        it('should fetch authentication token', function() {
1164          $httpBackend.expectGET('/auth.py');
1165          var controller = createController();
1166          $httpBackend.flush();
1167        });
1168
1169
1170        it('should fail authentication', function() {
1171
1172          // Notice how you can change the response even after it was set
1173          authRequestHandler.respond(401, '');
1174
1175          $httpBackend.expectGET('/auth.py');
1176          var controller = createController();
1177          $httpBackend.flush();
1178          expect($rootScope.status).toBe('Failed...');
1179        });
1180
1181
1182        it('should send msg to server', function() {
1183          var controller = createController();
1184          $httpBackend.flush();
1185
1186          // now you don’t care about the authentication, but
1187          // the controller will still send the request and
1188          // $httpBackend will respond without you having to
1189          // specify the expectation and response for this request
1190
1191          $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
1192          $rootScope.saveMessage('message content');
1193          expect($rootScope.status).toBe('Saving...');
1194          $httpBackend.flush();
1195          expect($rootScope.status).toBe('');
1196        });
1197
1198
1199        it('should send auth header', function() {
1200          var controller = createController();
1201          $httpBackend.flush();
1202
1203          $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
1204            // check if the header was sent, if it wasn't the expectation won't
1205            // match the request and the test will fail
1206            return headers['Authorization'] == 'xxx';
1207          }).respond(201, '');
1208
1209          $rootScope.saveMessage('whatever');
1210          $httpBackend.flush();
1211        });
1212     });
1213   ```
1214  *
1215  * ## Dynamic responses
1216  *
1217  * You define a response to a request by chaining a call to `respond()` onto a definition or expectation.
1218  * If you provide a **callback** as the first parameter to `respond(callback)` then you can dynamically generate
1219  * a response based on the properties of the request.
1220  *
1221  * The `callback` function should be of the form `function(method, url, data, headers, params)`.
1222  *
1223  * ### Query parameters
1224  *
1225  * By default, query parameters on request URLs are parsed into the `params` object. So a request URL
1226  * of `/list?q=searchstr&orderby=-name` would set `params` to be `{q: 'searchstr', orderby: '-name'}`.
1227  *
1228  * ### Regex parameter matching
1229  *
1230  * If an expectation or definition uses a **regex** to match the URL, you can provide an array of **keys** via a
1231  * `params` argument. The index of each **key** in the array will match the index of a **group** in the
1232  * **regex**.
1233  *
1234  * The `params` object in the **callback** will now have properties with these keys, which hold the value of the
1235  * corresponding **group** in the **regex**.
1236  *
1237  * This also applies to the `when` and `expect` shortcut methods.
1238  *
1239  *
1240  * ```js
1241  *   $httpBackend.expect('GET', /\/user\/(.+)/, undefined, undefined, ['id'])
1242  *     .respond(function(method, url, data, headers, params) {
1243  *       // for requested url of '/user/1234' params is {id: '1234'}
1244  *     });
1245  *
1246  *   $httpBackend.whenPATCH(/\/user\/(.+)\/article\/(.+)/, undefined, undefined, ['user', 'article'])
1247  *     .respond(function(method, url, data, headers, params) {
1248  *       // for url of '/user/1234/article/567' params is {user: '1234', article: '567'}
1249  *     });
1250  * ```
1251  *
1252  * ## Matching route requests
1253  *
1254  * For extra convenience, `whenRoute` and `expectRoute` shortcuts are available. These methods offer colon
1255  * delimited matching of the url path, ignoring the query string. This allows declarations
1256  * similar to how application routes are configured with `$routeProvider`. Because these methods convert
1257  * the definition url to regex, declaration order is important. Combined with query parameter parsing,
1258  * the following is possible:
1259  *
1260   ```js
1261     $httpBackend.whenRoute('GET', '/users/:id')
1262       .respond(function(method, url, data, headers, params) {
1263         return [200, MockUserList[Number(params.id)]];
1264       });
1265
1266     $httpBackend.whenRoute('GET', '/users')
1267       .respond(function(method, url, data, headers, params) {
1268         var userList = angular.copy(MockUserList),
1269           defaultSort = 'lastName',
1270           count, pages, isPrevious, isNext;
1271
1272         // paged api response '/v1/users?page=2'
1273         params.page = Number(params.page) || 1;
1274
1275         // query for last names '/v1/users?q=Archer'
1276         if (params.q) {
1277           userList = $filter('filter')({lastName: params.q});
1278         }
1279
1280         pages = Math.ceil(userList.length / pagingLength);
1281         isPrevious = params.page > 1;
1282         isNext = params.page < pages;
1283
1284         return [200, {
1285           count:    userList.length,
1286           previous: isPrevious,
1287           next:     isNext,
1288           // sort field -> '/v1/users?sortBy=firstName'
1289           results:  $filter('orderBy')(userList, params.sortBy || defaultSort)
1290                       .splice((params.page - 1) * pagingLength, pagingLength)
1291         }];
1292       });
1293   ```
1294  */
1295 angular.mock.$HttpBackendProvider = function() {
1296   this.$get = ['$rootScope', '$timeout', createHttpBackendMock];
1297 };
1298
1299 /**
1300  * General factory function for $httpBackend mock.
1301  * Returns instance for unit testing (when no arguments specified):
1302  *   - passing through is disabled
1303  *   - auto flushing is disabled
1304  *
1305  * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
1306  *   - passing through (delegating request to real backend) is enabled
1307  *   - auto flushing is enabled
1308  *
1309  * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
1310  * @param {Object=} $browser Auto-flushing enabled if specified
1311  * @return {Object} Instance of $httpBackend mock
1312  */
1313 function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1314   var definitions = [],
1315       expectations = [],
1316       responses = [],
1317       responsesPush = angular.bind(responses, responses.push),
1318       copy = angular.copy;
1319
1320   function createResponse(status, data, headers, statusText) {
1321     if (angular.isFunction(status)) return status;
1322
1323     return function() {
1324       return angular.isNumber(status)
1325           ? [status, data, headers, statusText]
1326           : [200, status, data, headers];
1327     };
1328   }
1329
1330   // TODO(vojta): change params to: method, url, data, headers, callback
1331   function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
1332     var xhr = new MockXhr(),
1333         expectation = expectations[0],
1334         wasExpected = false;
1335
1336     function prettyPrint(data) {
1337       return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
1338           ? data
1339           : angular.toJson(data);
1340     }
1341
1342     function wrapResponse(wrapped) {
1343       if (!$browser && timeout) {
1344         timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout);
1345       }
1346
1347       return handleResponse;
1348
1349       function handleResponse() {
1350         var response = wrapped.response(method, url, data, headers, wrapped.params(url));
1351         xhr.$$respHeaders = response[2];
1352         callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
1353                  copy(response[3] || ''));
1354       }
1355
1356       function handleTimeout() {
1357         for (var i = 0, ii = responses.length; i < ii; i++) {
1358           if (responses[i] === handleResponse) {
1359             responses.splice(i, 1);
1360             callback(-1, undefined, '');
1361             break;
1362           }
1363         }
1364       }
1365     }
1366
1367     if (expectation && expectation.match(method, url)) {
1368       if (!expectation.matchData(data)) {
1369         throw new Error('Expected ' + expectation + ' with different data\n' +
1370             'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT:      ' + data);
1371       }
1372
1373       if (!expectation.matchHeaders(headers)) {
1374         throw new Error('Expected ' + expectation + ' with different headers\n' +
1375                         'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT:      ' +
1376                         prettyPrint(headers));
1377       }
1378
1379       expectations.shift();
1380
1381       if (expectation.response) {
1382         responses.push(wrapResponse(expectation));
1383         return;
1384       }
1385       wasExpected = true;
1386     }
1387
1388     var i = -1, definition;
1389     while ((definition = definitions[++i])) {
1390       if (definition.match(method, url, data, headers || {})) {
1391         if (definition.response) {
1392           // if $browser specified, we do auto flush all requests
1393           ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
1394         } else if (definition.passThrough) {
1395           $delegate(method, url, data, callback, headers, timeout, withCredentials);
1396         } else throw new Error('No response defined !');
1397         return;
1398       }
1399     }
1400     throw wasExpected ?
1401         new Error('No response defined !') :
1402         new Error('Unexpected request: ' + method + ' ' + url + '\n' +
1403                   (expectation ? 'Expected ' + expectation : 'No more request expected'));
1404   }
1405
1406   /**
1407    * @ngdoc method
1408    * @name $httpBackend#when
1409    * @description
1410    * Creates a new backend definition.
1411    *
1412    * @param {string} method HTTP method.
1413    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1414    *   and returns true if the url matches the current definition.
1415    * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1416    *   data string and returns true if the data is as expected.
1417    * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1418    *   object and returns true if the headers match the current definition.
1419    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1420    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1421    *   request is handled. You can save this object for later use and invoke `respond` again in
1422    *   order to change how a matched request is handled.
1423    *
1424    *  - respond â€“
1425    *      `{function([status,] data[, headers, statusText])
1426    *      | function(function(method, url, data, headers, params)}`
1427    *    â€“ The respond method takes a set of static data to be returned or a function that can
1428    *    return an array containing response status (number), response data (string), response
1429    *    headers (Object), and the text for the status (string). The respond method returns the
1430    *    `requestHandler` object for possible overrides.
1431    */
1432   $httpBackend.when = function(method, url, data, headers, keys) {
1433     var definition = new MockHttpExpectation(method, url, data, headers, keys),
1434         chain = {
1435           respond: function(status, data, headers, statusText) {
1436             definition.passThrough = undefined;
1437             definition.response = createResponse(status, data, headers, statusText);
1438             return chain;
1439           }
1440         };
1441
1442     if ($browser) {
1443       chain.passThrough = function() {
1444         definition.response = undefined;
1445         definition.passThrough = true;
1446         return chain;
1447       };
1448     }
1449
1450     definitions.push(definition);
1451     return chain;
1452   };
1453
1454   /**
1455    * @ngdoc method
1456    * @name $httpBackend#whenGET
1457    * @description
1458    * Creates a new backend definition for GET requests. For more info see `when()`.
1459    *
1460    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1461    *   and returns true if the url matches the current definition.
1462    * @param {(Object|function(Object))=} headers HTTP headers.
1463    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1464    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1465    * request is handled. You can save this object for later use and invoke `respond` again in
1466    * order to change how a matched request is handled.
1467    */
1468
1469   /**
1470    * @ngdoc method
1471    * @name $httpBackend#whenHEAD
1472    * @description
1473    * Creates a new backend definition for HEAD requests. For more info see `when()`.
1474    *
1475    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1476    *   and returns true if the url matches the current definition.
1477    * @param {(Object|function(Object))=} headers HTTP headers.
1478    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1479    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1480    * request is handled. You can save this object for later use and invoke `respond` again in
1481    * order to change how a matched request is handled.
1482    */
1483
1484   /**
1485    * @ngdoc method
1486    * @name $httpBackend#whenDELETE
1487    * @description
1488    * Creates a new backend definition for DELETE requests. For more info see `when()`.
1489    *
1490    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1491    *   and returns true if the url matches the current definition.
1492    * @param {(Object|function(Object))=} headers HTTP headers.
1493    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1494    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1495    * request is handled. You can save this object for later use and invoke `respond` again in
1496    * order to change how a matched request is handled.
1497    */
1498
1499   /**
1500    * @ngdoc method
1501    * @name $httpBackend#whenPOST
1502    * @description
1503    * Creates a new backend definition for POST requests. For more info see `when()`.
1504    *
1505    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1506    *   and returns true if the url matches the current definition.
1507    * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1508    *   data string and returns true if the data is as expected.
1509    * @param {(Object|function(Object))=} headers HTTP headers.
1510    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1511    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1512    * request is handled. You can save this object for later use and invoke `respond` again in
1513    * order to change how a matched request is handled.
1514    */
1515
1516   /**
1517    * @ngdoc method
1518    * @name $httpBackend#whenPUT
1519    * @description
1520    * Creates a new backend definition for PUT requests.  For more info see `when()`.
1521    *
1522    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1523    *   and returns true if the url matches the current definition.
1524    * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1525    *   data string and returns true if the data is as expected.
1526    * @param {(Object|function(Object))=} headers HTTP headers.
1527    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1528    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1529    * request is handled. You can save this object for later use and invoke `respond` again in
1530    * order to change how a matched request is handled.
1531    */
1532
1533   /**
1534    * @ngdoc method
1535    * @name $httpBackend#whenJSONP
1536    * @description
1537    * Creates a new backend definition for JSONP requests. For more info see `when()`.
1538    *
1539    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1540    *   and returns true if the url matches the current definition.
1541    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1542    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1543    * request is handled. You can save this object for later use and invoke `respond` again in
1544    * order to change how a matched request is handled.
1545    */
1546   createShortMethods('when');
1547
1548   /**
1549    * @ngdoc method
1550    * @name $httpBackend#whenRoute
1551    * @description
1552    * Creates a new backend definition that compares only with the requested route.
1553    *
1554    * @param {string} method HTTP method.
1555    * @param {string} url HTTP url string that supports colon param matching.
1556    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1557    * request is handled. You can save this object for later use and invoke `respond` again in
1558    * order to change how a matched request is handled. See #when for more info.
1559    */
1560   $httpBackend.whenRoute = function(method, url) {
1561     var pathObj = parseRoute(url);
1562     return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys);
1563   };
1564
1565   function parseRoute(url) {
1566     var ret = {
1567       regexp: url
1568     },
1569     keys = ret.keys = [];
1570
1571     if (!url || !angular.isString(url)) return ret;
1572
1573     url = url
1574       .replace(/([().])/g, '\\$1')
1575       .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
1576         var optional = option === '?' ? option : null;
1577         var star = option === '*' ? option : null;
1578         keys.push({ name: key, optional: !!optional });
1579         slash = slash || '';
1580         return ''
1581           + (optional ? '' : slash)
1582           + '(?:'
1583           + (optional ? slash : '')
1584           + (star && '(.+?)' || '([^/]+)')
1585           + (optional || '')
1586           + ')'
1587           + (optional || '');
1588       })
1589       .replace(/([\/$\*])/g, '\\$1');
1590
1591     ret.regexp = new RegExp('^' + url, 'i');
1592     return ret;
1593   }
1594
1595   /**
1596    * @ngdoc method
1597    * @name $httpBackend#expect
1598    * @description
1599    * Creates a new request expectation.
1600    *
1601    * @param {string} method HTTP method.
1602    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1603    *   and returns true if the url matches the current definition.
1604    * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1605    *  receives data string and returns true if the data is as expected, or Object if request body
1606    *  is in JSON format.
1607    * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1608    *   object and returns true if the headers match the current expectation.
1609    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1610    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1611    *  request is handled. You can save this object for later use and invoke `respond` again in
1612    *  order to change how a matched request is handled.
1613    *
1614    *  - respond â€“
1615    *    `{function([status,] data[, headers, statusText])
1616    *    | function(function(method, url, data, headers, params)}`
1617    *    â€“ The respond method takes a set of static data to be returned or a function that can
1618    *    return an array containing response status (number), response data (string), response
1619    *    headers (Object), and the text for the status (string). The respond method returns the
1620    *    `requestHandler` object for possible overrides.
1621    */
1622   $httpBackend.expect = function(method, url, data, headers, keys) {
1623     var expectation = new MockHttpExpectation(method, url, data, headers, keys),
1624         chain = {
1625           respond: function(status, data, headers, statusText) {
1626             expectation.response = createResponse(status, data, headers, statusText);
1627             return chain;
1628           }
1629         };
1630
1631     expectations.push(expectation);
1632     return chain;
1633   };
1634
1635   /**
1636    * @ngdoc method
1637    * @name $httpBackend#expectGET
1638    * @description
1639    * Creates a new request expectation for GET requests. For more info see `expect()`.
1640    *
1641    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1642    *   and returns true if the url matches the current definition.
1643    * @param {Object=} headers HTTP headers.
1644    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1645    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1646    * request is handled. You can save this object for later use and invoke `respond` again in
1647    * order to change how a matched request is handled. See #expect for more info.
1648    */
1649
1650   /**
1651    * @ngdoc method
1652    * @name $httpBackend#expectHEAD
1653    * @description
1654    * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1655    *
1656    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1657    *   and returns true if the url matches the current definition.
1658    * @param {Object=} headers HTTP headers.
1659    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1660    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1661    *   request is handled. You can save this object for later use and invoke `respond` again in
1662    *   order to change how a matched request is handled.
1663    */
1664
1665   /**
1666    * @ngdoc method
1667    * @name $httpBackend#expectDELETE
1668    * @description
1669    * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1670    *
1671    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1672    *   and returns true if the url matches the current definition.
1673    * @param {Object=} headers HTTP headers.
1674    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1675    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1676    *   request is handled. You can save this object for later use and invoke `respond` again in
1677    *   order to change how a matched request is handled.
1678    */
1679
1680   /**
1681    * @ngdoc method
1682    * @name $httpBackend#expectPOST
1683    * @description
1684    * Creates a new request expectation for POST requests. For more info see `expect()`.
1685    *
1686    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1687    *   and returns true if the url matches the current definition.
1688    * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1689    *  receives data string and returns true if the data is as expected, or Object if request body
1690    *  is in JSON format.
1691    * @param {Object=} headers HTTP headers.
1692    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1693    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1694    *   request is handled. You can save this object for later use and invoke `respond` again in
1695    *   order to change how a matched request is handled.
1696    */
1697
1698   /**
1699    * @ngdoc method
1700    * @name $httpBackend#expectPUT
1701    * @description
1702    * Creates a new request expectation for PUT requests. For more info see `expect()`.
1703    *
1704    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1705    *   and returns true if the url matches the current definition.
1706    * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1707    *  receives data string and returns true if the data is as expected, or Object if request body
1708    *  is in JSON format.
1709    * @param {Object=} headers HTTP headers.
1710    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1711    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1712    *   request is handled. You can save this object for later use and invoke `respond` again in
1713    *   order to change how a matched request is handled.
1714    */
1715
1716   /**
1717    * @ngdoc method
1718    * @name $httpBackend#expectPATCH
1719    * @description
1720    * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1721    *
1722    * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1723    *   and returns true if the url matches the current definition.
1724    * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1725    *  receives data string and returns true if the data is as expected, or Object if request body
1726    *  is in JSON format.
1727    * @param {Object=} headers HTTP headers.
1728    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1729    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1730    *   request is handled. You can save this object for later use and invoke `respond` again in
1731    *   order to change how a matched request is handled.
1732    */
1733
1734   /**
1735    * @ngdoc method
1736    * @name $httpBackend#expectJSONP
1737    * @description
1738    * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1739    *
1740    * @param {string|RegExp|function(string)} url HTTP url or function that receives an url
1741    *   and returns true if the url matches the current definition.
1742    * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1743    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1744    *   request is handled. You can save this object for later use and invoke `respond` again in
1745    *   order to change how a matched request is handled.
1746    */
1747   createShortMethods('expect');
1748
1749   /**
1750    * @ngdoc method
1751    * @name $httpBackend#expectRoute
1752    * @description
1753    * Creates a new request expectation that compares only with the requested route.
1754    *
1755    * @param {string} method HTTP method.
1756    * @param {string} url HTTP url string that supports colon param matching.
1757    * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1758    * request is handled. You can save this object for later use and invoke `respond` again in
1759    * order to change how a matched request is handled. See #expect for more info.
1760    */
1761   $httpBackend.expectRoute = function(method, url) {
1762     var pathObj = parseRoute(url);
1763     return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys);
1764   };
1765
1766
1767   /**
1768    * @ngdoc method
1769    * @name $httpBackend#flush
1770    * @description
1771    * Flushes all pending requests using the trained responses.
1772    *
1773    * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
1774    *   all pending requests will be flushed. If there are no pending requests when the flush method
1775    *   is called an exception is thrown (as this typically a sign of programming error).
1776    */
1777   $httpBackend.flush = function(count, digest) {
1778     if (digest !== false) $rootScope.$digest();
1779     if (!responses.length) throw new Error('No pending request to flush !');
1780
1781     if (angular.isDefined(count) && count !== null) {
1782       while (count--) {
1783         if (!responses.length) throw new Error('No more pending request to flush !');
1784         responses.shift()();
1785       }
1786     } else {
1787       while (responses.length) {
1788         responses.shift()();
1789       }
1790     }
1791     $httpBackend.verifyNoOutstandingExpectation(digest);
1792   };
1793
1794
1795   /**
1796    * @ngdoc method
1797    * @name $httpBackend#verifyNoOutstandingExpectation
1798    * @description
1799    * Verifies that all of the requests defined via the `expect` api were made. If any of the
1800    * requests were not made, verifyNoOutstandingExpectation throws an exception.
1801    *
1802    * Typically, you would call this method following each test case that asserts requests using an
1803    * "afterEach" clause.
1804    *
1805    * ```js
1806    *   afterEach($httpBackend.verifyNoOutstandingExpectation);
1807    * ```
1808    */
1809   $httpBackend.verifyNoOutstandingExpectation = function(digest) {
1810     if (digest !== false) $rootScope.$digest();
1811     if (expectations.length) {
1812       throw new Error('Unsatisfied requests: ' + expectations.join(', '));
1813     }
1814   };
1815
1816
1817   /**
1818    * @ngdoc method
1819    * @name $httpBackend#verifyNoOutstandingRequest
1820    * @description
1821    * Verifies that there are no outstanding requests that need to be flushed.
1822    *
1823    * Typically, you would call this method following each test case that asserts requests using an
1824    * "afterEach" clause.
1825    *
1826    * ```js
1827    *   afterEach($httpBackend.verifyNoOutstandingRequest);
1828    * ```
1829    */
1830   $httpBackend.verifyNoOutstandingRequest = function() {
1831     if (responses.length) {
1832       throw new Error('Unflushed requests: ' + responses.length);
1833     }
1834   };
1835
1836
1837   /**
1838    * @ngdoc method
1839    * @name $httpBackend#resetExpectations
1840    * @description
1841    * Resets all request expectations, but preserves all backend definitions. Typically, you would
1842    * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
1843    * $httpBackend mock.
1844    */
1845   $httpBackend.resetExpectations = function() {
1846     expectations.length = 0;
1847     responses.length = 0;
1848   };
1849
1850   return $httpBackend;
1851
1852
1853   function createShortMethods(prefix) {
1854     angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
1855      $httpBackend[prefix + method] = function(url, headers, keys) {
1856        return $httpBackend[prefix](method, url, undefined, headers, keys);
1857      };
1858     });
1859
1860     angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
1861       $httpBackend[prefix + method] = function(url, data, headers, keys) {
1862         return $httpBackend[prefix](method, url, data, headers, keys);
1863       };
1864     });
1865   }
1866 }
1867
1868 function MockHttpExpectation(method, url, data, headers, keys) {
1869
1870   this.data = data;
1871   this.headers = headers;
1872
1873   this.match = function(m, u, d, h) {
1874     if (method != m) return false;
1875     if (!this.matchUrl(u)) return false;
1876     if (angular.isDefined(d) && !this.matchData(d)) return false;
1877     if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
1878     return true;
1879   };
1880
1881   this.matchUrl = function(u) {
1882     if (!url) return true;
1883     if (angular.isFunction(url.test)) return url.test(u);
1884     if (angular.isFunction(url)) return url(u);
1885     return url == u;
1886   };
1887
1888   this.matchHeaders = function(h) {
1889     if (angular.isUndefined(headers)) return true;
1890     if (angular.isFunction(headers)) return headers(h);
1891     return angular.equals(headers, h);
1892   };
1893
1894   this.matchData = function(d) {
1895     if (angular.isUndefined(data)) return true;
1896     if (data && angular.isFunction(data.test)) return data.test(d);
1897     if (data && angular.isFunction(data)) return data(d);
1898     if (data && !angular.isString(data)) {
1899       return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d));
1900     }
1901     return data == d;
1902   };
1903
1904   this.toString = function() {
1905     return method + ' ' + url;
1906   };
1907
1908   this.params = function(u) {
1909     return angular.extend(parseQuery(), pathParams());
1910
1911     function pathParams() {
1912       var keyObj = {};
1913       if (!url || !angular.isFunction(url.test) || !keys || keys.length === 0) return keyObj;
1914
1915       var m = url.exec(u);
1916       if (!m) return keyObj;
1917       for (var i = 1, len = m.length; i < len; ++i) {
1918         var key = keys[i - 1];
1919         var val = m[i];
1920         if (key && val) {
1921           keyObj[key.name || key] = val;
1922         }
1923       }
1924
1925       return keyObj;
1926     }
1927
1928     function parseQuery() {
1929       var obj = {}, key_value, key,
1930           queryStr = u.indexOf('?') > -1
1931           ? u.substring(u.indexOf('?') + 1)
1932           : "";
1933
1934       angular.forEach(queryStr.split('&'), function(keyValue) {
1935         if (keyValue) {
1936           key_value = keyValue.replace(/\+/g,'%20').split('=');
1937           key = tryDecodeURIComponent(key_value[0]);
1938           if (angular.isDefined(key)) {
1939             var val = angular.isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
1940             if (!hasOwnProperty.call(obj, key)) {
1941               obj[key] = val;
1942             } else if (angular.isArray(obj[key])) {
1943               obj[key].push(val);
1944             } else {
1945               obj[key] = [obj[key],val];
1946             }
1947           }
1948         }
1949       });
1950       return obj;
1951     }
1952     function tryDecodeURIComponent(value) {
1953       try {
1954         return decodeURIComponent(value);
1955       } catch (e) {
1956         // Ignore any invalid uri component
1957       }
1958     }
1959   };
1960 }
1961
1962 function createMockXhr() {
1963   return new MockXhr();
1964 }
1965
1966 function MockXhr() {
1967
1968   // hack for testing $http, $httpBackend
1969   MockXhr.$$lastInstance = this;
1970
1971   this.open = function(method, url, async) {
1972     this.$$method = method;
1973     this.$$url = url;
1974     this.$$async = async;
1975     this.$$reqHeaders = {};
1976     this.$$respHeaders = {};
1977   };
1978
1979   this.send = function(data) {
1980     this.$$data = data;
1981   };
1982
1983   this.setRequestHeader = function(key, value) {
1984     this.$$reqHeaders[key] = value;
1985   };
1986
1987   this.getResponseHeader = function(name) {
1988     // the lookup must be case insensitive,
1989     // that's why we try two quick lookups first and full scan last
1990     var header = this.$$respHeaders[name];
1991     if (header) return header;
1992
1993     name = angular.lowercase(name);
1994     header = this.$$respHeaders[name];
1995     if (header) return header;
1996
1997     header = undefined;
1998     angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
1999       if (!header && angular.lowercase(headerName) == name) header = headerVal;
2000     });
2001     return header;
2002   };
2003
2004   this.getAllResponseHeaders = function() {
2005     var lines = [];
2006
2007     angular.forEach(this.$$respHeaders, function(value, key) {
2008       lines.push(key + ': ' + value);
2009     });
2010     return lines.join('\n');
2011   };
2012
2013   this.abort = angular.noop;
2014 }
2015
2016
2017 /**
2018  * @ngdoc service
2019  * @name $timeout
2020  * @description
2021  *
2022  * This service is just a simple decorator for {@link ng.$timeout $timeout} service
2023  * that adds a "flush" and "verifyNoPendingTasks" methods.
2024  */
2025
2026 angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) {
2027
2028   /**
2029    * @ngdoc method
2030    * @name $timeout#flush
2031    * @description
2032    *
2033    * Flushes the queue of pending tasks.
2034    *
2035    * @param {number=} delay maximum timeout amount to flush up until
2036    */
2037   $delegate.flush = function(delay) {
2038     $browser.defer.flush(delay);
2039   };
2040
2041   /**
2042    * @ngdoc method
2043    * @name $timeout#verifyNoPendingTasks
2044    * @description
2045    *
2046    * Verifies that there are no pending tasks that need to be flushed.
2047    */
2048   $delegate.verifyNoPendingTasks = function() {
2049     if ($browser.deferredFns.length) {
2050       throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
2051           formatPendingTasksAsString($browser.deferredFns));
2052     }
2053   };
2054
2055   function formatPendingTasksAsString(tasks) {
2056     var result = [];
2057     angular.forEach(tasks, function(task) {
2058       result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
2059     });
2060
2061     return result.join(', ');
2062   }
2063
2064   return $delegate;
2065 }];
2066
2067 angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
2068   var rafFn = function(fn) {
2069     var index = rafFn.queue.length;
2070     rafFn.queue.push(fn);
2071     return function() {
2072       rafFn.queue.splice(index, 1);
2073     };
2074   };
2075
2076   rafFn.queue = [];
2077   rafFn.supported = $delegate.supported;
2078
2079   rafFn.flush = function() {
2080     if (rafFn.queue.length === 0) {
2081       throw new Error('No rAF callbacks present');
2082     }
2083
2084     var length = rafFn.queue.length;
2085     for (var i = 0; i < length; i++) {
2086       rafFn.queue[i]();
2087     }
2088
2089     rafFn.queue = rafFn.queue.slice(i);
2090   };
2091
2092   return rafFn;
2093 }];
2094
2095 /**
2096  *
2097  */
2098 angular.mock.$RootElementProvider = function() {
2099   this.$get = function() {
2100     return angular.element('<div ng-app></div>');
2101   };
2102 };
2103
2104 /**
2105  * @ngdoc service
2106  * @name $controller
2107  * @description
2108  * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing
2109  * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}.
2110  *
2111  *
2112  * ## Example
2113  *
2114  * ```js
2115  *
2116  * // Directive definition ...
2117  *
2118  * myMod.directive('myDirective', {
2119  *   controller: 'MyDirectiveController',
2120  *   bindToController: {
2121  *     name: '@'
2122  *   }
2123  * });
2124  *
2125  *
2126  * // Controller definition ...
2127  *
2128  * myMod.controller('MyDirectiveController', ['$log', function($log) {
2129  *   $log.info(this.name);
2130  * })];
2131  *
2132  *
2133  * // In a test ...
2134  *
2135  * describe('myDirectiveController', function() {
2136  *   it('should write the bound name to the log', inject(function($controller, $log) {
2137  *     var ctrl = $controller('MyDirectiveController', { /* no locals &#42;/ }, { name: 'Clark Kent' });
2138  *     expect(ctrl.name).toEqual('Clark Kent');
2139  *     expect($log.info.logs).toEqual(['Clark Kent']);
2140  *   });
2141  * });
2142  *
2143  * ```
2144  *
2145  * @param {Function|string} constructor If called with a function then it's considered to be the
2146  *    controller constructor function. Otherwise it's considered to be a string which is used
2147  *    to retrieve the controller constructor using the following steps:
2148  *
2149  *    * check if a controller with given name is registered via `$controllerProvider`
2150  *    * check if evaluating the string on the current scope returns a constructor
2151  *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
2152  *      `window` object (not recommended)
2153  *
2154  *    The string can use the `controller as property` syntax, where the controller instance is published
2155  *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
2156  *    to work correctly.
2157  *
2158  * @param {Object} locals Injection locals for Controller.
2159  * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
2160  *                           to simulate the `bindToController` feature and simplify certain kinds of tests.
2161  * @return {Object} Instance of given controller.
2162  */
2163 angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
2164   return function(expression, locals, later, ident) {
2165     if (later && typeof later === 'object') {
2166       var create = $delegate(expression, locals, true, ident);
2167       angular.extend(create.instance, later);
2168       return create();
2169     }
2170     return $delegate(expression, locals, later, ident);
2171   };
2172 }];
2173
2174 /**
2175  * @ngdoc service
2176  * @name $componentController
2177  * @description
2178  * A service that can be used to create instances of component controllers.
2179  * <div class="alert alert-info">
2180  * Be aware that the controller will be instantiated and attached to the scope as specified in
2181  * the component definition object. That means that you must always provide a `$scope` object
2182  * in the `locals` param.
2183  * </div>
2184  * @param {string} componentName the name of the component whose controller we want to instantiate
2185  * @param {Object} locals Injection locals for Controller.
2186  * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
2187  *                           to simulate the `bindToController` feature and simplify certain kinds of tests.
2188  * @param {string=} ident Override the property name to use when attaching the controller to the scope.
2189  * @return {Object} Instance of requested controller.
2190  */
2191 angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) {
2192   return {
2193     $get: ['$controller','$injector', function($controller,$injector) {
2194       return function $componentController(componentName, locals, bindings, ident) {
2195         // get all directives associated to the component name
2196         var directives = $injector.get(componentName + 'Directive');
2197         // look for those directives that are components
2198         var candidateDirectives = directives.filter(function(directiveInfo) {
2199           // components have controller, controllerAs and restrict:'E'
2200           return directiveInfo.controller && directiveInfo.controllerAs && directiveInfo.restrict === 'E';
2201         });
2202         // check if valid directives found
2203         if (candidateDirectives.length === 0) {
2204           throw new Error('No component found');
2205         }
2206         if (candidateDirectives.length > 1) {
2207           throw new Error('Too many components found');
2208         }
2209         // get the info of the component
2210         var directiveInfo = candidateDirectives[0];
2211         return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
2212       };
2213     }]
2214   };
2215 }];
2216
2217
2218 /**
2219  * @ngdoc module
2220  * @name ngMock
2221  * @packageName angular-mocks
2222  * @description
2223  *
2224  * # ngMock
2225  *
2226  * The `ngMock` module provides support to inject and mock Angular services into unit tests.
2227  * In addition, ngMock also extends various core ng services such that they can be
2228  * inspected and controlled in a synchronous manner within test code.
2229  *
2230  *
2231  * <div doc-module-components="ngMock"></div>
2232  *
2233  */
2234 angular.module('ngMock', ['ng']).provider({
2235   $browser: angular.mock.$BrowserProvider,
2236   $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
2237   $log: angular.mock.$LogProvider,
2238   $interval: angular.mock.$IntervalProvider,
2239   $httpBackend: angular.mock.$HttpBackendProvider,
2240   $rootElement: angular.mock.$RootElementProvider,
2241   $componentController: angular.mock.$ComponentControllerProvider
2242 }).config(['$provide', function($provide) {
2243   $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
2244   $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
2245   $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
2246   $provide.decorator('$controller', angular.mock.$ControllerDecorator);
2247 }]);
2248
2249 /**
2250  * @ngdoc module
2251  * @name ngMockE2E
2252  * @module ngMockE2E
2253  * @packageName angular-mocks
2254  * @description
2255  *
2256  * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
2257  * Currently there is only one mock present in this module -
2258  * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
2259  */
2260 angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
2261   $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
2262 }]);
2263
2264 /**
2265  * @ngdoc service
2266  * @name $httpBackend
2267  * @module ngMockE2E
2268  * @description
2269  * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
2270  * applications that use the {@link ng.$http $http service}.
2271  *
2272  * *Note*: For fake http backend implementation suitable for unit testing please see
2273  * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
2274  *
2275  * This implementation can be used to respond with static or dynamic responses via the `when` api
2276  * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
2277  * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
2278  * templates from a webserver).
2279  *
2280  * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
2281  * is being developed with the real backend api replaced with a mock, it is often desirable for
2282  * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
2283  * templates or static files from the webserver). To configure the backend with this behavior
2284  * use the `passThrough` request handler of `when` instead of `respond`.
2285  *
2286  * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
2287  * testing. For this reason the e2e $httpBackend flushes mocked out requests
2288  * automatically, closely simulating the behavior of the XMLHttpRequest object.
2289  *
2290  * To setup the application to run with this http backend, you have to create a module that depends
2291  * on the `ngMockE2E` and your application modules and defines the fake backend:
2292  *
2293  * ```js
2294  *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
2295  *   myAppDev.run(function($httpBackend) {
2296  *     phones = [{name: 'phone1'}, {name: 'phone2'}];
2297  *
2298  *     // returns the current list of phones
2299  *     $httpBackend.whenGET('/phones').respond(phones);
2300  *
2301  *     // adds a new phone to the phones array
2302  *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
2303  *       var phone = angular.fromJson(data);
2304  *       phones.push(phone);
2305  *       return [200, phone, {}];
2306  *     });
2307  *     $httpBackend.whenGET(/^\/templates\//).passThrough();
2308  *     //...
2309  *   });
2310  * ```
2311  *
2312  * Afterwards, bootstrap your app with this new module.
2313  */
2314
2315 /**
2316  * @ngdoc method
2317  * @name $httpBackend#when
2318  * @module ngMockE2E
2319  * @description
2320  * Creates a new backend definition.
2321  *
2322  * @param {string} method HTTP method.
2323  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2324  *   and returns true if the url matches the current definition.
2325  * @param {(string|RegExp)=} data HTTP request body.
2326  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
2327  *   object and returns true if the headers match the current definition.
2328  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2329  *   {@link ngMock.$httpBackend $httpBackend mock}.
2330  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2331  *   control how a matched request is handled. You can save this object for later use and invoke
2332  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2333  *
2334  *  - respond â€“
2335  *    `{function([status,] data[, headers, statusText])
2336  *    | function(function(method, url, data, headers, params)}`
2337  *    â€“ The respond method takes a set of static data to be returned or a function that can return
2338  *    an array containing response status (number), response data (string), response headers
2339  *    (Object), and the text for the status (string).
2340  *  - passThrough â€“ `{function()}` â€“ Any request matching a backend definition with
2341  *    `passThrough` handler will be passed through to the real backend (an XHR request will be made
2342  *    to the server.)
2343  *  - Both methods return the `requestHandler` object for possible overrides.
2344  */
2345
2346 /**
2347  * @ngdoc method
2348  * @name $httpBackend#whenGET
2349  * @module ngMockE2E
2350  * @description
2351  * Creates a new backend definition for GET requests. For more info see `when()`.
2352  *
2353  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2354  *   and returns true if the url matches the current definition.
2355  * @param {(Object|function(Object))=} headers HTTP headers.
2356  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2357  *   {@link ngMock.$httpBackend $httpBackend mock}.
2358  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2359  *   control how a matched request is handled. You can save this object for later use and invoke
2360  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2361  */
2362
2363 /**
2364  * @ngdoc method
2365  * @name $httpBackend#whenHEAD
2366  * @module ngMockE2E
2367  * @description
2368  * Creates a new backend definition for HEAD requests. For more info see `when()`.
2369  *
2370  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2371  *   and returns true if the url matches the current definition.
2372  * @param {(Object|function(Object))=} headers HTTP headers.
2373  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2374  *   {@link ngMock.$httpBackend $httpBackend mock}.
2375  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2376  *   control how a matched request is handled. You can save this object for later use and invoke
2377  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2378  */
2379
2380 /**
2381  * @ngdoc method
2382  * @name $httpBackend#whenDELETE
2383  * @module ngMockE2E
2384  * @description
2385  * Creates a new backend definition for DELETE requests. For more info see `when()`.
2386  *
2387  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2388  *   and returns true if the url matches the current definition.
2389  * @param {(Object|function(Object))=} headers HTTP headers.
2390  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2391  *   {@link ngMock.$httpBackend $httpBackend mock}.
2392  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2393  *   control how a matched request is handled. You can save this object for later use and invoke
2394  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2395  */
2396
2397 /**
2398  * @ngdoc method
2399  * @name $httpBackend#whenPOST
2400  * @module ngMockE2E
2401  * @description
2402  * Creates a new backend definition for POST requests. For more info see `when()`.
2403  *
2404  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2405  *   and returns true if the url matches the current definition.
2406  * @param {(string|RegExp)=} data HTTP request body.
2407  * @param {(Object|function(Object))=} headers HTTP headers.
2408  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2409  *   {@link ngMock.$httpBackend $httpBackend mock}.
2410  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2411  *   control how a matched request is handled. You can save this object for later use and invoke
2412  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2413  */
2414
2415 /**
2416  * @ngdoc method
2417  * @name $httpBackend#whenPUT
2418  * @module ngMockE2E
2419  * @description
2420  * Creates a new backend definition for PUT requests.  For more info see `when()`.
2421  *
2422  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2423  *   and returns true if the url matches the current definition.
2424  * @param {(string|RegExp)=} data HTTP request body.
2425  * @param {(Object|function(Object))=} headers HTTP headers.
2426  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2427  *   {@link ngMock.$httpBackend $httpBackend mock}.
2428  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2429  *   control how a matched request is handled. You can save this object for later use and invoke
2430  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2431  */
2432
2433 /**
2434  * @ngdoc method
2435  * @name $httpBackend#whenPATCH
2436  * @module ngMockE2E
2437  * @description
2438  * Creates a new backend definition for PATCH requests.  For more info see `when()`.
2439  *
2440  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2441  *   and returns true if the url matches the current definition.
2442  * @param {(string|RegExp)=} data HTTP request body.
2443  * @param {(Object|function(Object))=} headers HTTP headers.
2444  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2445  *   {@link ngMock.$httpBackend $httpBackend mock}.
2446  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2447  *   control how a matched request is handled. You can save this object for later use and invoke
2448  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2449  */
2450
2451 /**
2452  * @ngdoc method
2453  * @name $httpBackend#whenJSONP
2454  * @module ngMockE2E
2455  * @description
2456  * Creates a new backend definition for JSONP requests. For more info see `when()`.
2457  *
2458  * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2459  *   and returns true if the url matches the current definition.
2460  * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2461  *   {@link ngMock.$httpBackend $httpBackend mock}.
2462  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2463  *   control how a matched request is handled. You can save this object for later use and invoke
2464  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2465  */
2466 /**
2467  * @ngdoc method
2468  * @name $httpBackend#whenRoute
2469  * @module ngMockE2E
2470  * @description
2471  * Creates a new backend definition that compares only with the requested route.
2472  *
2473  * @param {string} method HTTP method.
2474  * @param {string} url HTTP url string that supports colon param matching.
2475  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2476  *   control how a matched request is handled. You can save this object for later use and invoke
2477  *   `respond` or `passThrough` again in order to change how a matched request is handled.
2478  */
2479 angular.mock.e2e = {};
2480 angular.mock.e2e.$httpBackendDecorator =
2481   ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];
2482
2483
2484 /**
2485  * @ngdoc type
2486  * @name $rootScope.Scope
2487  * @module ngMock
2488  * @description
2489  * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These
2490  * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when
2491  * `ngMock` module is loaded.
2492  *
2493  * In addition to all the regular `Scope` methods, the following helper methods are available:
2494  */
2495 angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
2496
2497   var $rootScopePrototype = Object.getPrototypeOf($delegate);
2498
2499   $rootScopePrototype.$countChildScopes = countChildScopes;
2500   $rootScopePrototype.$countWatchers = countWatchers;
2501
2502   return $delegate;
2503
2504   // ------------------------------------------------------------------------------------------ //
2505
2506   /**
2507    * @ngdoc method
2508    * @name $rootScope.Scope#$countChildScopes
2509    * @module ngMock
2510    * @description
2511    * Counts all the direct and indirect child scopes of the current scope.
2512    *
2513    * The current scope is excluded from the count. The count includes all isolate child scopes.
2514    *
2515    * @returns {number} Total number of child scopes.
2516    */
2517   function countChildScopes() {
2518     // jshint validthis: true
2519     var count = 0; // exclude the current scope
2520     var pendingChildHeads = [this.$$childHead];
2521     var currentScope;
2522
2523     while (pendingChildHeads.length) {
2524       currentScope = pendingChildHeads.shift();
2525
2526       while (currentScope) {
2527         count += 1;
2528         pendingChildHeads.push(currentScope.$$childHead);
2529         currentScope = currentScope.$$nextSibling;
2530       }
2531     }
2532
2533     return count;
2534   }
2535
2536
2537   /**
2538    * @ngdoc method
2539    * @name $rootScope.Scope#$countWatchers
2540    * @module ngMock
2541    * @description
2542    * Counts all the watchers of direct and indirect child scopes of the current scope.
2543    *
2544    * The watchers of the current scope are included in the count and so are all the watchers of
2545    * isolate child scopes.
2546    *
2547    * @returns {number} Total number of watchers.
2548    */
2549   function countWatchers() {
2550     // jshint validthis: true
2551     var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope
2552     var pendingChildHeads = [this.$$childHead];
2553     var currentScope;
2554
2555     while (pendingChildHeads.length) {
2556       currentScope = pendingChildHeads.shift();
2557
2558       while (currentScope) {
2559         count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
2560         pendingChildHeads.push(currentScope.$$childHead);
2561         currentScope = currentScope.$$nextSibling;
2562       }
2563     }
2564
2565     return count;
2566   }
2567 }];
2568
2569
2570 if (window.jasmine || window.mocha) {
2571
2572   var currentSpec = null,
2573       annotatedFunctions = [],
2574       isSpecRunning = function() {
2575         return !!currentSpec;
2576       };
2577
2578   angular.mock.$$annotate = angular.injector.$$annotate;
2579   angular.injector.$$annotate = function(fn) {
2580     if (typeof fn === 'function' && !fn.$inject) {
2581       annotatedFunctions.push(fn);
2582     }
2583     return angular.mock.$$annotate.apply(this, arguments);
2584   };
2585
2586
2587   (window.beforeEach || window.setup)(function() {
2588     annotatedFunctions = [];
2589     currentSpec = this;
2590   });
2591
2592   (window.afterEach || window.teardown)(function() {
2593     var injector = currentSpec.$injector;
2594
2595     annotatedFunctions.forEach(function(fn) {
2596       delete fn.$inject;
2597     });
2598
2599     angular.forEach(currentSpec.$modules, function(module) {
2600       if (module && module.$$hashKey) {
2601         module.$$hashKey = undefined;
2602       }
2603     });
2604
2605     currentSpec.$injector = null;
2606     currentSpec.$modules = null;
2607     currentSpec.$providerInjector = null;
2608     currentSpec = null;
2609
2610     if (injector) {
2611       injector.get('$rootElement').off();
2612       injector.get('$rootScope').$destroy();
2613     }
2614
2615     // clean up jquery's fragment cache
2616     angular.forEach(angular.element.fragments, function(val, key) {
2617       delete angular.element.fragments[key];
2618     });
2619
2620     MockXhr.$$lastInstance = null;
2621
2622     angular.forEach(angular.callbacks, function(val, key) {
2623       delete angular.callbacks[key];
2624     });
2625     angular.callbacks.counter = 0;
2626   });
2627
2628   /**
2629    * @ngdoc function
2630    * @name angular.mock.module
2631    * @description
2632    *
2633    * *NOTE*: This function is also published on window for easy access.<br>
2634    * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
2635    *
2636    * This function registers a module configuration code. It collects the configuration information
2637    * which will be used when the injector is created by {@link angular.mock.inject inject}.
2638    *
2639    * See {@link angular.mock.inject inject} for usage example
2640    *
2641    * @param {...(string|Function|Object)} fns any number of modules which are represented as string
2642    *        aliases or as anonymous module initialization functions. The modules are used to
2643    *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
2644    *        object literal is passed each key-value pair will be registered on the module via
2645    *        {@link auto.$provide $provide}.value, the key being the string name (or token) to associate
2646    *        with the value on the injector.
2647    */
2648   window.module = angular.mock.module = function() {
2649     var moduleFns = Array.prototype.slice.call(arguments, 0);
2650     return isSpecRunning() ? workFn() : workFn;
2651     /////////////////////
2652     function workFn() {
2653       if (currentSpec.$injector) {
2654         throw new Error('Injector already created, can not register a module!');
2655       } else {
2656         var fn, modules = currentSpec.$modules || (currentSpec.$modules = []);
2657         angular.forEach(moduleFns, function(module) {
2658           if (angular.isObject(module) && !angular.isArray(module)) {
2659             fn = function($provide) {
2660               angular.forEach(module, function(value, key) {
2661                 $provide.value(key, value);
2662               });
2663             };
2664           } else {
2665             fn = module;
2666           }
2667           if (currentSpec.$providerInjector) {
2668             currentSpec.$providerInjector.invoke(fn);
2669           } else {
2670             modules.push(fn);
2671           }
2672         });
2673       }
2674     }
2675   };
2676
2677   /**
2678    * @ngdoc function
2679    * @name angular.mock.inject
2680    * @description
2681    *
2682    * *NOTE*: This function is also published on window for easy access.<br>
2683    * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
2684    *
2685    * The inject function wraps a function into an injectable function. The inject() creates new
2686    * instance of {@link auto.$injector $injector} per test, which is then used for
2687    * resolving references.
2688    *
2689    *
2690    * ## Resolving References (Underscore Wrapping)
2691    * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
2692    * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
2693    * that is declared in the scope of the `describe()` block. Since we would, most likely, want
2694    * the variable to have the same name of the reference we have a problem, since the parameter
2695    * to the `inject()` function would hide the outer variable.
2696    *
2697    * To help with this, the injected parameters can, optionally, be enclosed with underscores.
2698    * These are ignored by the injector when the reference name is resolved.
2699    *
2700    * For example, the parameter `_myService_` would be resolved as the reference `myService`.
2701    * Since it is available in the function body as _myService_, we can then assign it to a variable
2702    * defined in an outer scope.
2703    *
2704    * ```
2705    * // Defined out reference variable outside
2706    * var myService;
2707    *
2708    * // Wrap the parameter in underscores
2709    * beforeEach( inject( function(_myService_){
2710    *   myService = _myService_;
2711    * }));
2712    *
2713    * // Use myService in a series of tests.
2714    * it('makes use of myService', function() {
2715    *   myService.doStuff();
2716    * });
2717    *
2718    * ```
2719    *
2720    * See also {@link angular.mock.module angular.mock.module}
2721    *
2722    * ## Example
2723    * Example of what a typical jasmine tests looks like with the inject method.
2724    * ```js
2725    *
2726    *   angular.module('myApplicationModule', [])
2727    *       .value('mode', 'app')
2728    *       .value('version', 'v1.0.1');
2729    *
2730    *
2731    *   describe('MyApp', function() {
2732    *
2733    *     // You need to load modules that you want to test,
2734    *     // it loads only the "ng" module by default.
2735    *     beforeEach(module('myApplicationModule'));
2736    *
2737    *
2738    *     // inject() is used to inject arguments of all given functions
2739    *     it('should provide a version', inject(function(mode, version) {
2740    *       expect(version).toEqual('v1.0.1');
2741    *       expect(mode).toEqual('app');
2742    *     }));
2743    *
2744    *
2745    *     // The inject and module method can also be used inside of the it or beforeEach
2746    *     it('should override a version and test the new version is injected', function() {
2747    *       // module() takes functions or strings (module aliases)
2748    *       module(function($provide) {
2749    *         $provide.value('version', 'overridden'); // override version here
2750    *       });
2751    *
2752    *       inject(function(version) {
2753    *         expect(version).toEqual('overridden');
2754    *       });
2755    *     });
2756    *   });
2757    *
2758    * ```
2759    *
2760    * @param {...Function} fns any number of functions which will be injected using the injector.
2761    */
2762
2763
2764
2765   var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {
2766     this.message = e.message;
2767     this.name = e.name;
2768     if (e.line) this.line = e.line;
2769     if (e.sourceId) this.sourceId = e.sourceId;
2770     if (e.stack && errorForStack)
2771       this.stack = e.stack + '\n' + errorForStack.stack;
2772     if (e.stackArray) this.stackArray = e.stackArray;
2773   };
2774   ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;
2775
2776   window.inject = angular.mock.inject = function() {
2777     var blockFns = Array.prototype.slice.call(arguments, 0);
2778     var errorForStack = new Error('Declaration Location');
2779     return isSpecRunning() ? workFn.call(currentSpec) : workFn;
2780     /////////////////////
2781     function workFn() {
2782       var modules = currentSpec.$modules || [];
2783       var strictDi = !!currentSpec.$injectorStrict;
2784       modules.unshift(function($injector) {
2785         currentSpec.$providerInjector = $injector;
2786       });
2787       modules.unshift('ngMock');
2788       modules.unshift('ng');
2789       var injector = currentSpec.$injector;
2790       if (!injector) {
2791         if (strictDi) {
2792           // If strictDi is enabled, annotate the providerInjector blocks
2793           angular.forEach(modules, function(moduleFn) {
2794             if (typeof moduleFn === "function") {
2795               angular.injector.$$annotate(moduleFn);
2796             }
2797           });
2798         }
2799         injector = currentSpec.$injector = angular.injector(modules, strictDi);
2800         currentSpec.$injectorStrict = strictDi;
2801       }
2802       for (var i = 0, ii = blockFns.length; i < ii; i++) {
2803         if (currentSpec.$injectorStrict) {
2804           // If the injector is strict / strictDi, and the spec wants to inject using automatic
2805           // annotation, then annotate the function here.
2806           injector.annotate(blockFns[i]);
2807         }
2808         try {
2809           /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
2810           injector.invoke(blockFns[i] || angular.noop, this);
2811           /* jshint +W040 */
2812         } catch (e) {
2813           if (e.stack && errorForStack) {
2814             throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
2815           }
2816           throw e;
2817         } finally {
2818           errorForStack = null;
2819         }
2820       }
2821     }
2822   };
2823
2824
2825   angular.mock.inject.strictDi = function(value) {
2826     value = arguments.length ? !!value : true;
2827     return isSpecRunning() ? workFn() : workFn;
2828
2829     function workFn() {
2830       if (value !== currentSpec.$injectorStrict) {
2831         if (currentSpec.$injector) {
2832           throw new Error('Injector already created, can not modify strict annotations');
2833         } else {
2834           currentSpec.$injectorStrict = value;
2835         }
2836       }
2837     }
2838   };
2839 }
2840
2841
2842 })(window, window.angular);