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