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