Add an AngularJS test to DoYouEvenBench
[WebKit-https.git] / PerformanceTests / DoYouEvenBench / todomvc / architecture-examples / angularjs / bower_components / angular-mocks / angular-mocks.js
1 /**
2  * @license AngularJS v1.0.4
3  * (c) 2010-2012 Google, Inc. http://angularjs.org
4  * License: MIT
5  *
6  * TODO(vojta): wrap whole file into closure during build
7  */
8
9 /**
10  * @ngdoc overview
11  * @name angular.mock
12  * @description
13  *
14  * Namespace from 'angular-mocks.js' which contains testing related code.
15  */
16 angular.mock = {};
17
18 /**
19  * ! This is a private undocumented service !
20  *
21  * @name ngMock.$browser
22  *
23  * @description
24  * This service is a mock implementation of {@link ng.$browser}. It provides fake
25  * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
26  * cookies, etc...
27  *
28  * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
29  * that there are several helper methods available which can be used in tests.
30  */
31 angular.mock.$BrowserProvider = function() {
32   this.$get = function(){
33     return new angular.mock.$Browser();
34   };
35 };
36
37 angular.mock.$Browser = function() {
38   var self = this;
39
40   this.isMock = true;
41   self.$$url = "http://server/";
42   self.$$lastUrl = self.$$url; // used by url polling fn
43   self.pollFns = [];
44
45   // TODO(vojta): remove this temporary api
46   self.$$completeOutstandingRequest = angular.noop;
47   self.$$incOutstandingRequestCount = angular.noop;
48
49
50   // register url polling fn
51
52   self.onUrlChange = function(listener) {
53     self.pollFns.push(
54       function() {
55         if (self.$$lastUrl != self.$$url) {
56           self.$$lastUrl = self.$$url;
57           listener(self.$$url);
58         }
59       }
60     );
61
62     return listener;
63   };
64
65   self.cookieHash = {};
66   self.lastCookieHash = {};
67   self.deferredFns = [];
68   self.deferredNextId = 0;
69
70   self.defer = function(fn, delay) {
71     delay = delay || 0;
72     self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
73     self.deferredFns.sort(function(a,b){ return a.time - b.time;});
74     return self.deferredNextId++;
75   };
76
77
78   self.defer.now = 0;
79
80
81   self.defer.cancel = function(deferId) {
82     var fnIndex;
83
84     angular.forEach(self.deferredFns, function(fn, index) {
85       if (fn.id === deferId) fnIndex = index;
86     });
87
88     if (fnIndex !== undefined) {
89       self.deferredFns.splice(fnIndex, 1);
90       return true;
91     }
92
93     return false;
94   };
95
96
97   /**
98    * @name ngMock.$browser#defer.flush
99    * @methodOf ngMock.$browser
100    *
101    * @description
102    * Flushes all pending requests and executes the defer callbacks.
103    *
104    * @param {number=} number of milliseconds to flush. See {@link #defer.now}
105    */
106   self.defer.flush = function(delay) {
107     if (angular.isDefined(delay)) {
108       self.defer.now += delay;
109     } else {
110       if (self.deferredFns.length) {
111         self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
112       } else {
113         throw Error('No deferred tasks to be flushed');
114       }
115     }
116
117     while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
118       self.deferredFns.shift().fn();
119     }
120   };
121   /**
122    * @name ngMock.$browser#defer.now
123    * @propertyOf ngMock.$browser
124    *
125    * @description
126    * Current milliseconds mock time.
127    */
128
129   self.$$baseHref = '';
130   self.baseHref = function() {
131     return this.$$baseHref;
132   };
133 };
134 angular.mock.$Browser.prototype = {
135
136 /**
137   * @name ngMock.$browser#poll
138   * @methodOf ngMock.$browser
139   *
140   * @description
141   * run all fns in pollFns
142   */
143   poll: function poll() {
144     angular.forEach(this.pollFns, function(pollFn){
145       pollFn();
146     });
147   },
148
149   addPollFn: function(pollFn) {
150     this.pollFns.push(pollFn);
151     return pollFn;
152   },
153
154   url: function(url, replace) {
155     if (url) {
156       this.$$url = url;
157       return this;
158     }
159
160     return this.$$url;
161   },
162
163   cookies:  function(name, value) {
164     if (name) {
165       if (value == undefined) {
166         delete this.cookieHash[name];
167       } else {
168         if (angular.isString(value) &&       //strings only
169             value.length <= 4096) {          //strict cookie storage limits
170           this.cookieHash[name] = value;
171         }
172       }
173     } else {
174       if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
175         this.lastCookieHash = angular.copy(this.cookieHash);
176         this.cookieHash = angular.copy(this.cookieHash);
177       }
178       return this.cookieHash;
179     }
180   },
181
182   notifyWhenNoOutstandingRequests: function(fn) {
183     fn();
184   }
185 };
186
187
188 /**
189  * @ngdoc object
190  * @name ngMock.$exceptionHandlerProvider
191  *
192  * @description
193  * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed
194  * into the `$exceptionHandler`.
195  */
196
197 /**
198  * @ngdoc object
199  * @name ngMock.$exceptionHandler
200  *
201  * @description
202  * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
203  * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
204  * information.
205  *
206  *
207  * <pre>
208  *   describe('$exceptionHandlerProvider', function() {
209  *
210  *     it('should capture log messages and exceptions', function() {
211  *
212  *       module(function($exceptionHandlerProvider) {
213  *         $exceptionHandlerProvider.mode('log');
214  *       });
215  *
216  *       inject(function($log, $exceptionHandler, $timeout) {
217  *         $timeout(function() { $log.log(1); });
218  *         $timeout(function() { $log.log(2); throw 'banana peel'; });
219  *         $timeout(function() { $log.log(3); });
220  *         expect($exceptionHandler.errors).toEqual([]);
221  *         expect($log.assertEmpty());
222  *         $timeout.flush();
223  *         expect($exceptionHandler.errors).toEqual(['banana peel']);
224  *         expect($log.log.logs).toEqual([[1], [2], [3]]);
225  *       });
226  *     });
227  *   });
228  * </pre>
229  */
230
231 angular.mock.$ExceptionHandlerProvider = function() {
232   var handler;
233
234   /**
235    * @ngdoc method
236    * @name ngMock.$exceptionHandlerProvider#mode
237    * @methodOf ngMock.$exceptionHandlerProvider
238    *
239    * @description
240    * Sets the logging mode.
241    *
242    * @param {string} mode Mode of operation, defaults to `rethrow`.
243    *
244    *   - `rethrow`: If any errors are are passed into the handler in tests, it typically
245    *                means that there is a bug in the application or test, so this mock will
246    *                make these tests fail.
247    *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an
248    *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
249    *            See {@link ngMock.$log#assertEmpty assertEmpty()} and
250    *             {@link ngMock.$log#reset reset()}
251    */
252   this.mode = function(mode) {
253     switch(mode) {
254       case 'rethrow':
255         handler = function(e) {
256           throw e;
257         };
258         break;
259       case 'log':
260         var errors = [];
261
262         handler = function(e) {
263           if (arguments.length == 1) {
264             errors.push(e);
265           } else {
266             errors.push([].slice.call(arguments, 0));
267           }
268         };
269
270         handler.errors = errors;
271         break;
272       default:
273         throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
274     }
275   };
276
277   this.$get = function() {
278     return handler;
279   };
280
281   this.mode('rethrow');
282 };
283
284
285 /**
286  * @ngdoc service
287  * @name ngMock.$log
288  *
289  * @description
290  * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
291  * (one array per logging level). These arrays are exposed as `logs` property of each of the
292  * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
293  *
294  */
295 angular.mock.$LogProvider = function() {
296
297   function concat(array1, array2, index) {
298     return array1.concat(Array.prototype.slice.call(array2, index));
299   }
300
301
302   this.$get = function () {
303     var $log = {
304       log: function() { $log.log.logs.push(concat([], arguments, 0)); },
305       warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
306       info: function() { $log.info.logs.push(concat([], arguments, 0)); },
307       error: function() { $log.error.logs.push(concat([], arguments, 0)); }
308     };
309
310     /**
311      * @ngdoc method
312      * @name ngMock.$log#reset
313      * @methodOf ngMock.$log
314      *
315      * @description
316      * Reset all of the logging arrays to empty.
317      */
318     $log.reset = function () {
319       /**
320        * @ngdoc property
321        * @name ngMock.$log#log.logs
322        * @propertyOf ngMock.$log
323        *
324        * @description
325        * Array of logged messages.
326        */
327       $log.log.logs = [];
328       /**
329        * @ngdoc property
330        * @name ngMock.$log#warn.logs
331        * @propertyOf ngMock.$log
332        *
333        * @description
334        * Array of logged messages.
335        */
336       $log.warn.logs = [];
337       /**
338        * @ngdoc property
339        * @name ngMock.$log#info.logs
340        * @propertyOf ngMock.$log
341        *
342        * @description
343        * Array of logged messages.
344        */
345       $log.info.logs = [];
346       /**
347        * @ngdoc property
348        * @name ngMock.$log#error.logs
349        * @propertyOf ngMock.$log
350        *
351        * @description
352        * Array of logged messages.
353        */
354       $log.error.logs = [];
355     };
356
357     /**
358      * @ngdoc method
359      * @name ngMock.$log#assertEmpty
360      * @methodOf ngMock.$log
361      *
362      * @description
363      * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
364      */
365     $log.assertEmpty = function() {
366       var errors = [];
367       angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
368         angular.forEach($log[logLevel].logs, function(log) {
369           angular.forEach(log, function (logItem) {
370             errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
371           });
372         });
373       });
374       if (errors.length) {
375         errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " +
376           "log message was not checked and removed:");
377         errors.push('');
378         throw new Error(errors.join('\n---------\n'));
379       }
380     };
381
382     $log.reset();
383     return $log;
384   };
385 };
386
387
388 (function() {
389   var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
390
391   function jsonStringToDate(string){
392     var match;
393     if (match = string.match(R_ISO8061_STR)) {
394       var date = new Date(0),
395           tzHour = 0,
396           tzMin  = 0;
397       if (match[9]) {
398         tzHour = int(match[9] + match[10]);
399         tzMin = int(match[9] + match[11]);
400       }
401       date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
402       date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
403       return date;
404     }
405     return string;
406   }
407
408   function int(str) {
409     return parseInt(str, 10);
410   }
411
412   function padNumber(num, digits, trim) {
413     var neg = '';
414     if (num < 0) {
415       neg =  '-';
416       num = -num;
417     }
418     num = '' + num;
419     while(num.length < digits) num = '0' + num;
420     if (trim)
421       num = num.substr(num.length - digits);
422     return neg + num;
423   }
424
425
426   /**
427    * @ngdoc object
428    * @name angular.mock.TzDate
429    * @description
430    *
431    * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
432    *
433    * Mock of the Date type which has its timezone specified via constroctor arg.
434    *
435    * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
436    * offset, so that we can test code that depends on local timezone settings without dependency on
437    * the time zone settings of the machine where the code is running.
438    *
439    * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
440    * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
441    *
442    * @example
443    * !!!! WARNING !!!!!
444    * This is not a complete Date object so only methods that were implemented can be called safely.
445    * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
446    *
447    * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
448    * incomplete we might be missing some non-standard methods. This can result in errors like:
449    * "Date.prototype.foo called on incompatible Object".
450    *
451    * <pre>
452    * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
453    * newYearInBratislava.getTimezoneOffset() => -60;
454    * newYearInBratislava.getFullYear() => 2010;
455    * newYearInBratislava.getMonth() => 0;
456    * newYearInBratislava.getDate() => 1;
457    * newYearInBratislava.getHours() => 0;
458    * newYearInBratislava.getMinutes() => 0;
459    * </pre>
460    *
461    */
462   angular.mock.TzDate = function (offset, timestamp) {
463     var self = new Date(0);
464     if (angular.isString(timestamp)) {
465       var tsStr = timestamp;
466
467       self.origDate = jsonStringToDate(timestamp);
468
469       timestamp = self.origDate.getTime();
470       if (isNaN(timestamp))
471         throw {
472           name: "Illegal Argument",
473           message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
474         };
475     } else {
476       self.origDate = new Date(timestamp);
477     }
478
479     var localOffset = new Date(timestamp).getTimezoneOffset();
480     self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
481     self.date = new Date(timestamp + self.offsetDiff);
482
483     self.getTime = function() {
484       return self.date.getTime() - self.offsetDiff;
485     };
486
487     self.toLocaleDateString = function() {
488       return self.date.toLocaleDateString();
489     };
490
491     self.getFullYear = function() {
492       return self.date.getFullYear();
493     };
494
495     self.getMonth = function() {
496       return self.date.getMonth();
497     };
498
499     self.getDate = function() {
500       return self.date.getDate();
501     };
502
503     self.getHours = function() {
504       return self.date.getHours();
505     };
506
507     self.getMinutes = function() {
508       return self.date.getMinutes();
509     };
510
511     self.getSeconds = function() {
512       return self.date.getSeconds();
513     };
514
515     self.getTimezoneOffset = function() {
516       return offset * 60;
517     };
518
519     self.getUTCFullYear = function() {
520       return self.origDate.getUTCFullYear();
521     };
522
523     self.getUTCMonth = function() {
524       return self.origDate.getUTCMonth();
525     };
526
527     self.getUTCDate = function() {
528       return self.origDate.getUTCDate();
529     };
530
531     self.getUTCHours = function() {
532       return self.origDate.getUTCHours();
533     };
534
535     self.getUTCMinutes = function() {
536       return self.origDate.getUTCMinutes();
537     };
538
539     self.getUTCSeconds = function() {
540       return self.origDate.getUTCSeconds();
541     };
542
543     self.getUTCMilliseconds = function() {
544       return self.origDate.getUTCMilliseconds();
545     };
546
547     self.getDay = function() {
548       return self.date.getDay();
549     };
550
551     // provide this method only on browsers that already have it
552     if (self.toISOString) {
553       self.toISOString = function() {
554         return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
555               padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
556               padNumber(self.origDate.getUTCDate(), 2) + 'T' +
557               padNumber(self.origDate.getUTCHours(), 2) + ':' +
558               padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
559               padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
560               padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
561       }
562     }
563
564     //hide all methods not implemented in this mock that the Date prototype exposes
565     var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
566         'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
567         'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
568         'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
569         'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
570         'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
571
572     angular.forEach(unimplementedMethods, function(methodName) {
573       self[methodName] = function() {
574         throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
575       };
576     });
577
578     return self;
579   };
580
581   //make "tzDateInstance instanceof Date" return true
582   angular.mock.TzDate.prototype = Date.prototype;
583 })();
584
585
586 /**
587  * @ngdoc function
588  * @name angular.mock.dump
589  * @description
590  *
591  * *NOTE*: this is not an injectable instance, just a globally available function.
592  *
593  * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
594  *
595  * This method is also available on window, where it can be used to display objects on debug console.
596  *
597  * @param {*} object - any object to turn into string.
598  * @return {string} a serialized string of the argument
599  */
600 angular.mock.dump = function(object) {
601   return serialize(object);
602
603   function serialize(object) {
604     var out;
605
606     if (angular.isElement(object)) {
607       object = angular.element(object);
608       out = angular.element('<div></div>');
609       angular.forEach(object, function(element) {
610         out.append(angular.element(element).clone());
611       });
612       out = out.html();
613     } else if (angular.isArray(object)) {
614       out = [];
615       angular.forEach(object, function(o) {
616         out.push(serialize(o));
617       });
618       out = '[ ' + out.join(', ') + ' ]';
619     } else if (angular.isObject(object)) {
620       if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
621         out = serializeScope(object);
622       } else if (object instanceof Error) {
623         out = object.stack || ('' + object.name + ': ' + object.message);
624       } else {
625         out = angular.toJson(object, true);
626       }
627     } else {
628       out = String(object);
629     }
630
631     return out;
632   }
633
634   function serializeScope(scope, offset) {
635     offset = offset ||  '  ';
636     var log = [offset + 'Scope(' + scope.$id + '): {'];
637     for ( var key in scope ) {
638       if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
639         log.push('  ' + key + ': ' + angular.toJson(scope[key]));
640       }
641     }
642     var child = scope.$$childHead;
643     while(child) {
644       log.push(serializeScope(child, offset + '  '));
645       child = child.$$nextSibling;
646     }
647     log.push('}');
648     return log.join('\n' + offset);
649   }
650 };
651
652 /**
653  * @ngdoc object
654  * @name ngMock.$httpBackend
655  * @description
656  * Fake HTTP backend implementation suitable for unit testing application that use the
657  * {@link ng.$http $http service}.
658  *
659  * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less
660  * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
661  *
662  * During unit testing, we want our unit tests to run quickly and have no external dependencies so
663  * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
664  * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
665  * to verify whether a certain request has been sent or not, or alternatively just let the
666  * application make requests, respond with pre-trained responses and assert that the end result is
667  * what we expect it to be.
668  *
669  * This mock implementation can be used to respond with static or dynamic responses via the
670  * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
671  *
672  * When an Angular application needs some data from a server, it calls the $http service, which
673  * sends the request to a real server using $httpBackend service. With dependency injection, it is
674  * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
675  * the requests and respond with some testing data without sending a request to real server.
676  *
677  * There are two ways to specify what test data should be returned as http responses by the mock
678  * backend when the code under test makes http requests:
679  *
680  * - `$httpBackend.expect` - specifies a request expectation
681  * - `$httpBackend.when` - specifies a backend definition
682  *
683  *
684  * # Request Expectations vs Backend Definitions
685  *
686  * Request expectations provide a way to make assertions about requests made by the application and
687  * to define responses for those requests. The test will fail if the expected requests are not made
688  * or they are made in the wrong order.
689  *
690  * Backend definitions allow you to define a fake backend for your application which doesn't assert
691  * if a particular request was made or not, it just returns a trained response if a request is made.
692  * The test will pass whether or not the request gets made during testing.
693  *
694  *
695  * <table class="table">
696  *   <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
697  *   <tr>
698  *     <th>Syntax</th>
699  *     <td>.expect(...).respond(...)</td>
700  *     <td>.when(...).respond(...)</td>
701  *   </tr>
702  *   <tr>
703  *     <th>Typical usage</th>
704  *     <td>strict unit tests</td>
705  *     <td>loose (black-box) unit testing</td>
706  *   </tr>
707  *   <tr>
708  *     <th>Fulfills multiple requests</th>
709  *     <td>NO</td>
710  *     <td>YES</td>
711  *   </tr>
712  *   <tr>
713  *     <th>Order of requests matters</th>
714  *     <td>YES</td>
715  *     <td>NO</td>
716  *   </tr>
717  *   <tr>
718  *     <th>Request required</th>
719  *     <td>YES</td>
720  *     <td>NO</td>
721  *   </tr>
722  *   <tr>
723  *     <th>Response required</th>
724  *     <td>optional (see below)</td>
725  *     <td>YES</td>
726  *   </tr>
727  * </table>
728  *
729  * In cases where both backend definitions and request expectations are specified during unit
730  * testing, the request expectations are evaluated first.
731  *
732  * If a request expectation has no response specified, the algorithm will search your backend
733  * definitions for an appropriate response.
734  *
735  * If a request didn't match any expectation or if the expectation doesn't have the response
736  * defined, the backend definitions are evaluated in sequential order to see if any of them match
737  * the request. The response from the first matched definition is returned.
738  *
739  *
740  * # Flushing HTTP requests
741  *
742  * The $httpBackend used in production, always responds to requests with responses asynchronously.
743  * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are
744  * hard to write, follow and maintain. At the same time the testing mock, can't respond
745  * synchronously because that would change the execution of the code under test. For this reason the
746  * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
747  * requests and thus preserving the async api of the backend, while allowing the test to execute
748  * synchronously.
749  *
750  *
751  * # Unit testing with mock $httpBackend
752  *
753  * <pre>
754    // controller
755    function MyController($scope, $http) {
756      $http.get('/auth.py').success(function(data) {
757        $scope.user = data;
758      });
759
760      this.saveMessage = function(message) {
761        $scope.status = 'Saving...';
762        $http.post('/add-msg.py', message).success(function(response) {
763          $scope.status = '';
764        }).error(function() {
765          $scope.status = 'ERROR!';
766        });
767      };
768    }
769
770    // testing controller
771    var $httpBackend;
772
773    beforeEach(inject(function($injector) {
774      $httpBackend = $injector.get('$httpBackend');
775
776      // backend definition common for all tests
777      $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
778    }));
779
780
781    afterEach(function() {
782      $httpBackend.verifyNoOutstandingExpectation();
783      $httpBackend.verifyNoOutstandingRequest();
784    });
785
786
787    it('should fetch authentication token', function() {
788      $httpBackend.expectGET('/auth.py');
789      var controller = scope.$new(MyController);
790      $httpBackend.flush();
791    });
792
793
794    it('should send msg to server', function() {
795      // now you don’t care about the authentication, but
796      // the controller will still send the request and
797      // $httpBackend will respond without you having to
798      // specify the expectation and response for this request
799      $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
800
801      var controller = scope.$new(MyController);
802      $httpBackend.flush();
803      controller.saveMessage('message content');
804      expect(controller.status).toBe('Saving...');
805      $httpBackend.flush();
806      expect(controller.status).toBe('');
807    });
808
809
810    it('should send auth header', function() {
811      $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
812        // check if the header was send, if it wasn't the expectation won't
813        // match the request and the test will fail
814        return headers['Authorization'] == 'xxx';
815      }).respond(201, '');
816
817      var controller = scope.$new(MyController);
818      controller.saveMessage('whatever');
819      $httpBackend.flush();
820    });
821    </pre>
822  */
823 angular.mock.$HttpBackendProvider = function() {
824   this.$get = [createHttpBackendMock];
825 };
826
827 /**
828  * General factory function for $httpBackend mock.
829  * Returns instance for unit testing (when no arguments specified):
830  *   - passing through is disabled
831  *   - auto flushing is disabled
832  *
833  * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
834  *   - passing through (delegating request to real backend) is enabled
835  *   - auto flushing is enabled
836  *
837  * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
838  * @param {Object=} $browser Auto-flushing enabled if specified
839  * @return {Object} Instance of $httpBackend mock
840  */
841 function createHttpBackendMock($delegate, $browser) {
842   var definitions = [],
843       expectations = [],
844       responses = [],
845       responsesPush = angular.bind(responses, responses.push);
846
847   function createResponse(status, data, headers) {
848     if (angular.isFunction(status)) return status;
849
850     return function() {
851       return angular.isNumber(status)
852           ? [status, data, headers]
853           : [200, status, data];
854     };
855   }
856
857   // TODO(vojta): change params to: method, url, data, headers, callback
858   function $httpBackend(method, url, data, callback, headers) {
859     var xhr = new MockXhr(),
860         expectation = expectations[0],
861         wasExpected = false;
862
863     function prettyPrint(data) {
864       return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
865           ? data
866           : angular.toJson(data);
867     }
868
869     if (expectation && expectation.match(method, url)) {
870       if (!expectation.matchData(data))
871         throw Error('Expected ' + expectation + ' with different data\n' +
872             'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT:      ' + data);
873
874       if (!expectation.matchHeaders(headers))
875         throw Error('Expected ' + expectation + ' with different headers\n' +
876             'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT:      ' +
877             prettyPrint(headers));
878
879       expectations.shift();
880
881       if (expectation.response) {
882         responses.push(function() {
883           var response = expectation.response(method, url, data, headers);
884           xhr.$$respHeaders = response[2];
885           callback(response[0], response[1], xhr.getAllResponseHeaders());
886         });
887         return;
888       }
889       wasExpected = true;
890     }
891
892     var i = -1, definition;
893     while ((definition = definitions[++i])) {
894       if (definition.match(method, url, data, headers || {})) {
895         if (definition.response) {
896           // if $browser specified, we do auto flush all requests
897           ($browser ? $browser.defer : responsesPush)(function() {
898             var response = definition.response(method, url, data, headers);
899             xhr.$$respHeaders = response[2];
900             callback(response[0], response[1], xhr.getAllResponseHeaders());
901           });
902         } else if (definition.passThrough) {
903           $delegate(method, url, data, callback, headers);
904         } else throw Error('No response defined !');
905         return;
906       }
907     }
908     throw wasExpected ?
909         Error('No response defined !') :
910         Error('Unexpected request: ' + method + ' ' + url + '\n' +
911               (expectation ? 'Expected ' + expectation : 'No more request expected'));
912   }
913
914   /**
915    * @ngdoc method
916    * @name ngMock.$httpBackend#when
917    * @methodOf ngMock.$httpBackend
918    * @description
919    * Creates a new backend definition.
920    *
921    * @param {string} method HTTP method.
922    * @param {string|RegExp} url HTTP url.
923    * @param {(string|RegExp)=} data HTTP request body.
924    * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
925    *   object and returns true if the headers match the current definition.
926    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
927    *   request is handled.
928    *
929    *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
930    *    – The respond method takes a set of static data to be returned or a function that can return
931    *    an array containing response status (number), response data (string) and response headers
932    *    (Object).
933    */
934   $httpBackend.when = function(method, url, data, headers) {
935     var definition = new MockHttpExpectation(method, url, data, headers),
936         chain = {
937           respond: function(status, data, headers) {
938             definition.response = createResponse(status, data, headers);
939           }
940         };
941
942     if ($browser) {
943       chain.passThrough = function() {
944         definition.passThrough = true;
945       };
946     }
947
948     definitions.push(definition);
949     return chain;
950   };
951
952   /**
953    * @ngdoc method
954    * @name ngMock.$httpBackend#whenGET
955    * @methodOf ngMock.$httpBackend
956    * @description
957    * Creates a new backend definition for GET requests. For more info see `when()`.
958    *
959    * @param {string|RegExp} url HTTP url.
960    * @param {(Object|function(Object))=} headers HTTP headers.
961    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
962    * request is handled.
963    */
964
965   /**
966    * @ngdoc method
967    * @name ngMock.$httpBackend#whenHEAD
968    * @methodOf ngMock.$httpBackend
969    * @description
970    * Creates a new backend definition for HEAD requests. For more info see `when()`.
971    *
972    * @param {string|RegExp} url HTTP url.
973    * @param {(Object|function(Object))=} headers HTTP headers.
974    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
975    * request is handled.
976    */
977
978   /**
979    * @ngdoc method
980    * @name ngMock.$httpBackend#whenDELETE
981    * @methodOf ngMock.$httpBackend
982    * @description
983    * Creates a new backend definition for DELETE requests. For more info see `when()`.
984    *
985    * @param {string|RegExp} url HTTP url.
986    * @param {(Object|function(Object))=} headers HTTP headers.
987    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
988    * request is handled.
989    */
990
991   /**
992    * @ngdoc method
993    * @name ngMock.$httpBackend#whenPOST
994    * @methodOf ngMock.$httpBackend
995    * @description
996    * Creates a new backend definition for POST requests. For more info see `when()`.
997    *
998    * @param {string|RegExp} url HTTP url.
999    * @param {(string|RegExp)=} data HTTP request body.
1000    * @param {(Object|function(Object))=} headers HTTP headers.
1001    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1002    * request is handled.
1003    */
1004
1005   /**
1006    * @ngdoc method
1007    * @name ngMock.$httpBackend#whenPUT
1008    * @methodOf ngMock.$httpBackend
1009    * @description
1010    * Creates a new backend definition for PUT requests.  For more info see `when()`.
1011    *
1012    * @param {string|RegExp} url HTTP url.
1013    * @param {(string|RegExp)=} data HTTP request body.
1014    * @param {(Object|function(Object))=} headers HTTP headers.
1015    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1016    * request is handled.
1017    */
1018
1019   /**
1020    * @ngdoc method
1021    * @name ngMock.$httpBackend#whenJSONP
1022    * @methodOf ngMock.$httpBackend
1023    * @description
1024    * Creates a new backend definition for JSONP requests. For more info see `when()`.
1025    *
1026    * @param {string|RegExp} url HTTP url.
1027    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1028    * request is handled.
1029    */
1030   createShortMethods('when');
1031
1032
1033   /**
1034    * @ngdoc method
1035    * @name ngMock.$httpBackend#expect
1036    * @methodOf ngMock.$httpBackend
1037    * @description
1038    * Creates a new request expectation.
1039    *
1040    * @param {string} method HTTP method.
1041    * @param {string|RegExp} url HTTP url.
1042    * @param {(string|RegExp)=} data HTTP request body.
1043    * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1044    *   object and returns true if the headers match the current expectation.
1045    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1046    *  request is handled.
1047    *
1048    *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1049    *    – The respond method takes a set of static data to be returned or a function that can return
1050    *    an array containing response status (number), response data (string) and response headers
1051    *    (Object).
1052    */
1053   $httpBackend.expect = function(method, url, data, headers) {
1054     var expectation = new MockHttpExpectation(method, url, data, headers);
1055     expectations.push(expectation);
1056     return {
1057       respond: function(status, data, headers) {
1058         expectation.response = createResponse(status, data, headers);
1059       }
1060     };
1061   };
1062
1063
1064   /**
1065    * @ngdoc method
1066    * @name ngMock.$httpBackend#expectGET
1067    * @methodOf ngMock.$httpBackend
1068    * @description
1069    * Creates a new request expectation for GET requests. For more info see `expect()`.
1070    *
1071    * @param {string|RegExp} url HTTP url.
1072    * @param {Object=} headers HTTP headers.
1073    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1074    * request is handled. See #expect for more info.
1075    */
1076
1077   /**
1078    * @ngdoc method
1079    * @name ngMock.$httpBackend#expectHEAD
1080    * @methodOf ngMock.$httpBackend
1081    * @description
1082    * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1083    *
1084    * @param {string|RegExp} url HTTP url.
1085    * @param {Object=} headers HTTP headers.
1086    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1087    *   request is handled.
1088    */
1089
1090   /**
1091    * @ngdoc method
1092    * @name ngMock.$httpBackend#expectDELETE
1093    * @methodOf ngMock.$httpBackend
1094    * @description
1095    * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1096    *
1097    * @param {string|RegExp} url HTTP url.
1098    * @param {Object=} headers HTTP headers.
1099    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1100    *   request is handled.
1101    */
1102
1103   /**
1104    * @ngdoc method
1105    * @name ngMock.$httpBackend#expectPOST
1106    * @methodOf ngMock.$httpBackend
1107    * @description
1108    * Creates a new request expectation for POST requests. For more info see `expect()`.
1109    *
1110    * @param {string|RegExp} url HTTP url.
1111    * @param {(string|RegExp)=} data HTTP request body.
1112    * @param {Object=} headers HTTP headers.
1113    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1114    *   request is handled.
1115    */
1116
1117   /**
1118    * @ngdoc method
1119    * @name ngMock.$httpBackend#expectPUT
1120    * @methodOf ngMock.$httpBackend
1121    * @description
1122    * Creates a new request expectation for PUT requests. For more info see `expect()`.
1123    *
1124    * @param {string|RegExp} url HTTP url.
1125    * @param {(string|RegExp)=} data HTTP request body.
1126    * @param {Object=} headers HTTP headers.
1127    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1128    *   request is handled.
1129    */
1130
1131   /**
1132    * @ngdoc method
1133    * @name ngMock.$httpBackend#expectPATCH
1134    * @methodOf ngMock.$httpBackend
1135    * @description
1136    * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1137    *
1138    * @param {string|RegExp} url HTTP url.
1139    * @param {(string|RegExp)=} data HTTP request body.
1140    * @param {Object=} headers HTTP headers.
1141    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1142    *   request is handled.
1143    */
1144
1145   /**
1146    * @ngdoc method
1147    * @name ngMock.$httpBackend#expectJSONP
1148    * @methodOf ngMock.$httpBackend
1149    * @description
1150    * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1151    *
1152    * @param {string|RegExp} url HTTP url.
1153    * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1154    *   request is handled.
1155    */
1156   createShortMethods('expect');
1157
1158
1159   /**
1160    * @ngdoc method
1161    * @name ngMock.$httpBackend#flush
1162    * @methodOf ngMock.$httpBackend
1163    * @description
1164    * Flushes all pending requests using the trained responses.
1165    *
1166    * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
1167    *   all pending requests will be flushed. If there are no pending requests when the flush method
1168    *   is called an exception is thrown (as this typically a sign of programming error).
1169    */
1170   $httpBackend.flush = function(count) {
1171     if (!responses.length) throw Error('No pending request to flush !');
1172
1173     if (angular.isDefined(count)) {
1174       while (count--) {
1175         if (!responses.length) throw Error('No more pending request to flush !');
1176         responses.shift()();
1177       }
1178     } else {
1179       while (responses.length) {
1180         responses.shift()();
1181       }
1182     }
1183     $httpBackend.verifyNoOutstandingExpectation();
1184   };
1185
1186
1187   /**
1188    * @ngdoc method
1189    * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
1190    * @methodOf ngMock.$httpBackend
1191    * @description
1192    * Verifies that all of the requests defined via the `expect` api were made. If any of the
1193    * requests were not made, verifyNoOutstandingExpectation throws an exception.
1194    *
1195    * Typically, you would call this method following each test case that asserts requests using an
1196    * "afterEach" clause.
1197    *
1198    * <pre>
1199    *   afterEach($httpBackend.verifyExpectations);
1200    * </pre>
1201    */
1202   $httpBackend.verifyNoOutstandingExpectation = function() {
1203     if (expectations.length) {
1204       throw Error('Unsatisfied requests: ' + expectations.join(', '));
1205     }
1206   };
1207
1208
1209   /**
1210    * @ngdoc method
1211    * @name ngMock.$httpBackend#verifyNoOutstandingRequest
1212    * @methodOf ngMock.$httpBackend
1213    * @description
1214    * Verifies that there are no outstanding requests that need to be flushed.
1215    *
1216    * Typically, you would call this method following each test case that asserts requests using an
1217    * "afterEach" clause.
1218    *
1219    * <pre>
1220    *   afterEach($httpBackend.verifyNoOutstandingRequest);
1221    * </pre>
1222    */
1223   $httpBackend.verifyNoOutstandingRequest = function() {
1224     if (responses.length) {
1225       throw Error('Unflushed requests: ' + responses.length);
1226     }
1227   };
1228
1229
1230   /**
1231    * @ngdoc method
1232    * @name ngMock.$httpBackend#resetExpectations
1233    * @methodOf ngMock.$httpBackend
1234    * @description
1235    * Resets all request expectations, but preserves all backend definitions. Typically, you would
1236    * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
1237    * $httpBackend mock.
1238    */
1239   $httpBackend.resetExpectations = function() {
1240     expectations.length = 0;
1241     responses.length = 0;
1242   };
1243
1244   return $httpBackend;
1245
1246
1247   function createShortMethods(prefix) {
1248     angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
1249      $httpBackend[prefix + method] = function(url, headers) {
1250        return $httpBackend[prefix](method, url, undefined, headers)
1251      }
1252     });
1253
1254     angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
1255       $httpBackend[prefix + method] = function(url, data, headers) {
1256         return $httpBackend[prefix](method, url, data, headers)
1257       }
1258     });
1259   }
1260 }
1261
1262 function MockHttpExpectation(method, url, data, headers) {
1263
1264   this.data = data;
1265   this.headers = headers;
1266
1267   this.match = function(m, u, d, h) {
1268     if (method != m) return false;
1269     if (!this.matchUrl(u)) return false;
1270     if (angular.isDefined(d) && !this.matchData(d)) return false;
1271     if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
1272     return true;
1273   };
1274
1275   this.matchUrl = function(u) {
1276     if (!url) return true;
1277     if (angular.isFunction(url.test)) return url.test(u);
1278     return url == u;
1279   };
1280
1281   this.matchHeaders = function(h) {
1282     if (angular.isUndefined(headers)) return true;
1283     if (angular.isFunction(headers)) return headers(h);
1284     return angular.equals(headers, h);
1285   };
1286
1287   this.matchData = function(d) {
1288     if (angular.isUndefined(data)) return true;
1289     if (data && angular.isFunction(data.test)) return data.test(d);
1290     if (data && !angular.isString(data)) return angular.toJson(data) == d;
1291     return data == d;
1292   };
1293
1294   this.toString = function() {
1295     return method + ' ' + url;
1296   };
1297 }
1298
1299 function MockXhr() {
1300
1301   // hack for testing $http, $httpBackend
1302   MockXhr.$$lastInstance = this;
1303
1304   this.open = function(method, url, async) {
1305     this.$$method = method;
1306     this.$$url = url;
1307     this.$$async = async;
1308     this.$$reqHeaders = {};
1309     this.$$respHeaders = {};
1310   };
1311
1312   this.send = function(data) {
1313     this.$$data = data;
1314   };
1315
1316   this.setRequestHeader = function(key, value) {
1317     this.$$reqHeaders[key] = value;
1318   };
1319
1320   this.getResponseHeader = function(name) {
1321     // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last
1322     var header = this.$$respHeaders[name];
1323     if (header) return header;
1324
1325     name = angular.lowercase(name);
1326     header = this.$$respHeaders[name];
1327     if (header) return header;
1328
1329     header = undefined;
1330     angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
1331       if (!header && angular.lowercase(headerName) == name) header = headerVal;
1332     });
1333     return header;
1334   };
1335
1336   this.getAllResponseHeaders = function() {
1337     var lines = [];
1338
1339     angular.forEach(this.$$respHeaders, function(value, key) {
1340       lines.push(key + ': ' + value);
1341     });
1342     return lines.join('\n');
1343   };
1344
1345   this.abort = angular.noop;
1346 }
1347
1348
1349 /**
1350  * @ngdoc function
1351  * @name ngMock.$timeout
1352  * @description
1353  *
1354  * This service is just a simple decorator for {@link ng.$timeout $timeout} service
1355  * that adds a "flush" method.
1356  */
1357
1358 /**
1359  * @ngdoc method
1360  * @name ngMock.$timeout#flush
1361  * @methodOf ngMock.$timeout
1362  * @description
1363  *
1364  * Flushes the queue of pending tasks.
1365  */
1366
1367 /**
1368  *
1369  */
1370 angular.mock.$RootElementProvider = function() {
1371   this.$get = function() {
1372     return angular.element('<div ng-app></div>');
1373   }
1374 };
1375
1376 /**
1377  * @ngdoc overview
1378  * @name ngMock
1379  * @description
1380  *
1381  * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful
1382  * mocks to the {@link AUTO.$injector $injector}.
1383  */
1384 angular.module('ngMock', ['ng']).provider({
1385   $browser: angular.mock.$BrowserProvider,
1386   $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
1387   $log: angular.mock.$LogProvider,
1388   $httpBackend: angular.mock.$HttpBackendProvider,
1389   $rootElement: angular.mock.$RootElementProvider
1390 }).config(function($provide) {
1391   $provide.decorator('$timeout', function($delegate, $browser) {
1392     $delegate.flush = function() {
1393       $browser.defer.flush();
1394     };
1395     return $delegate;
1396   });
1397 });
1398
1399
1400 /**
1401  * @ngdoc overview
1402  * @name ngMockE2E
1403  * @description
1404  *
1405  * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
1406  * Currently there is only one mock present in this module -
1407  * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
1408  */
1409 angular.module('ngMockE2E', ['ng']).config(function($provide) {
1410   $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
1411 });
1412
1413 /**
1414  * @ngdoc object
1415  * @name ngMockE2E.$httpBackend
1416  * @description
1417  * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
1418  * applications that use the {@link ng.$http $http service}.
1419  *
1420  * *Note*: For fake http backend implementation suitable for unit testing please see
1421  * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
1422  *
1423  * This implementation can be used to respond with static or dynamic responses via the `when` api
1424  * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
1425  * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
1426  * templates from a webserver).
1427  *
1428  * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
1429  * is being developed with the real backend api replaced with a mock, it is often desirable for
1430  * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
1431  * templates or static files from the webserver). To configure the backend with this behavior
1432  * use the `passThrough` request handler of `when` instead of `respond`.
1433  *
1434  * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
1435  * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
1436  * automatically, closely simulating the behavior of the XMLHttpRequest object.
1437  *
1438  * To setup the application to run with this http backend, you have to create a module that depends
1439  * on the `ngMockE2E` and your application modules and defines the fake backend:
1440  *
1441  * <pre>
1442  *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
1443  *   myAppDev.run(function($httpBackend) {
1444  *     phones = [{name: 'phone1'}, {name: 'phone2'}];
1445  *
1446  *     // returns the current list of phones
1447  *     $httpBackend.whenGET('/phones').respond(phones);
1448  *
1449  *     // adds a new phone to the phones array
1450  *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
1451  *       phones.push(angular.fromJSON(data));
1452  *     });
1453  *     $httpBackend.whenGET(/^\/templates\//).passThrough();
1454  *     //...
1455  *   });
1456  * </pre>
1457  *
1458  * Afterwards, bootstrap your app with this new module.
1459  */
1460
1461 /**
1462  * @ngdoc method
1463  * @name ngMockE2E.$httpBackend#when
1464  * @methodOf ngMockE2E.$httpBackend
1465  * @description
1466  * Creates a new backend definition.
1467  *
1468  * @param {string} method HTTP method.
1469  * @param {string|RegExp} url HTTP url.
1470  * @param {(string|RegExp)=} data HTTP request body.
1471  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1472  *   object and returns true if the headers match the current definition.
1473  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1474  *   control how a matched request is handled.
1475  *
1476  *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1477  *    – The respond method takes a set of static data to be returned or a function that can return
1478  *    an array containing response status (number), response data (string) and response headers
1479  *    (Object).
1480  *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
1481  *    handler, will be pass through to the real backend (an XHR request will be made to the
1482  *    server.
1483  */
1484
1485 /**
1486  * @ngdoc method
1487  * @name ngMockE2E.$httpBackend#whenGET
1488  * @methodOf ngMockE2E.$httpBackend
1489  * @description
1490  * Creates a new backend definition for GET requests. For more info see `when()`.
1491  *
1492  * @param {string|RegExp} url HTTP url.
1493  * @param {(Object|function(Object))=} headers HTTP headers.
1494  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1495  *   control how a matched request is handled.
1496  */
1497
1498 /**
1499  * @ngdoc method
1500  * @name ngMockE2E.$httpBackend#whenHEAD
1501  * @methodOf ngMockE2E.$httpBackend
1502  * @description
1503  * Creates a new backend definition for HEAD requests. For more info see `when()`.
1504  *
1505  * @param {string|RegExp} url HTTP url.
1506  * @param {(Object|function(Object))=} headers HTTP headers.
1507  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1508  *   control how a matched request is handled.
1509  */
1510
1511 /**
1512  * @ngdoc method
1513  * @name ngMockE2E.$httpBackend#whenDELETE
1514  * @methodOf ngMockE2E.$httpBackend
1515  * @description
1516  * Creates a new backend definition for DELETE requests. For more info see `when()`.
1517  *
1518  * @param {string|RegExp} url HTTP url.
1519  * @param {(Object|function(Object))=} headers HTTP headers.
1520  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1521  *   control how a matched request is handled.
1522  */
1523
1524 /**
1525  * @ngdoc method
1526  * @name ngMockE2E.$httpBackend#whenPOST
1527  * @methodOf ngMockE2E.$httpBackend
1528  * @description
1529  * Creates a new backend definition for POST requests. For more info see `when()`.
1530  *
1531  * @param {string|RegExp} url HTTP url.
1532  * @param {(string|RegExp)=} data HTTP request body.
1533  * @param {(Object|function(Object))=} headers HTTP headers.
1534  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1535  *   control how a matched request is handled.
1536  */
1537
1538 /**
1539  * @ngdoc method
1540  * @name ngMockE2E.$httpBackend#whenPUT
1541  * @methodOf ngMockE2E.$httpBackend
1542  * @description
1543  * Creates a new backend definition for PUT requests.  For more info see `when()`.
1544  *
1545  * @param {string|RegExp} url HTTP url.
1546  * @param {(string|RegExp)=} data HTTP request body.
1547  * @param {(Object|function(Object))=} headers HTTP headers.
1548  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1549  *   control how a matched request is handled.
1550  */
1551
1552 /**
1553  * @ngdoc method
1554  * @name ngMockE2E.$httpBackend#whenPATCH
1555  * @methodOf ngMockE2E.$httpBackend
1556  * @description
1557  * Creates a new backend definition for PATCH requests.  For more info see `when()`.
1558  *
1559  * @param {string|RegExp} url HTTP url.
1560  * @param {(string|RegExp)=} data HTTP request body.
1561  * @param {(Object|function(Object))=} headers HTTP headers.
1562  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1563  *   control how a matched request is handled.
1564  */
1565
1566 /**
1567  * @ngdoc method
1568  * @name ngMockE2E.$httpBackend#whenJSONP
1569  * @methodOf ngMockE2E.$httpBackend
1570  * @description
1571  * Creates a new backend definition for JSONP requests. For more info see `when()`.
1572  *
1573  * @param {string|RegExp} url HTTP url.
1574  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1575  *   control how a matched request is handled.
1576  */
1577 angular.mock.e2e = {};
1578 angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
1579
1580
1581 angular.mock.clearDataCache = function() {
1582   var key,
1583       cache = angular.element.cache;
1584
1585   for(key in cache) {
1586     if (cache.hasOwnProperty(key)) {
1587       var handle = cache[key].handle;
1588
1589       handle && angular.element(handle.elem).unbind();
1590       delete cache[key];
1591     }
1592   }
1593 };
1594
1595
1596 window.jstestdriver && (function(window) {
1597   /**
1598    * Global method to output any number of objects into JSTD console. Useful for debugging.
1599    */
1600   window.dump = function() {
1601     var args = [];
1602     angular.forEach(arguments, function(arg) {
1603       args.push(angular.mock.dump(arg));
1604     });
1605     jstestdriver.console.log.apply(jstestdriver.console, args);
1606     if (window.console) {
1607       window.console.log.apply(window.console, args);
1608     }
1609   };
1610 })(window);
1611
1612
1613 window.jasmine && (function(window) {
1614
1615   afterEach(function() {
1616     var spec = getCurrentSpec();
1617     var injector = spec.$injector;
1618
1619     spec.$injector = null;
1620     spec.$modules = null;
1621
1622     if (injector) {
1623       injector.get('$rootElement').unbind();
1624       injector.get('$browser').pollFns.length = 0;
1625     }
1626
1627     angular.mock.clearDataCache();
1628
1629     // clean up jquery's fragment cache
1630     angular.forEach(angular.element.fragments, function(val, key) {
1631       delete angular.element.fragments[key];
1632     });
1633
1634     MockXhr.$$lastInstance = null;
1635
1636     angular.forEach(angular.callbacks, function(val, key) {
1637       delete angular.callbacks[key];
1638     });
1639     angular.callbacks.counter = 0;
1640   });
1641
1642   function getCurrentSpec() {
1643     return jasmine.getEnv().currentSpec;
1644   }
1645
1646   function isSpecRunning() {
1647     var spec = getCurrentSpec();
1648     return spec && spec.queue.running;
1649   }
1650
1651   /**
1652    * @ngdoc function
1653    * @name angular.mock.module
1654    * @description
1655    *
1656    * *NOTE*: This is function is also published on window for easy access.<br>
1657    * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
1658    *
1659    * This function registers a module configuration code. It collects the configuration information
1660    * which will be used when the injector is created by {@link angular.mock.inject inject}.
1661    *
1662    * See {@link angular.mock.inject inject} for usage example
1663    *
1664    * @param {...(string|Function)} fns any number of modules which are represented as string
1665    *        aliases or as anonymous module initialization functions. The modules are used to
1666    *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
1667    */
1668   window.module = angular.mock.module = function() {
1669     var moduleFns = Array.prototype.slice.call(arguments, 0);
1670     return isSpecRunning() ? workFn() : workFn;
1671     /////////////////////
1672     function workFn() {
1673       var spec = getCurrentSpec();
1674       if (spec.$injector) {
1675         throw Error('Injector already created, can not register a module!');
1676       } else {
1677         var modules = spec.$modules || (spec.$modules = []);
1678         angular.forEach(moduleFns, function(module) {
1679           modules.push(module);
1680         });
1681       }
1682     }
1683   };
1684
1685   /**
1686    * @ngdoc function
1687    * @name angular.mock.inject
1688    * @description
1689    *
1690    * *NOTE*: This is function is also published on window for easy access.<br>
1691    * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
1692    *
1693    * The inject function wraps a function into an injectable function. The inject() creates new
1694    * instance of {@link AUTO.$injector $injector} per test, which is then used for
1695    * resolving references.
1696    *
1697    * See also {@link angular.mock.module module}
1698    *
1699    * Example of what a typical jasmine tests looks like with the inject method.
1700    * <pre>
1701    *
1702    *   angular.module('myApplicationModule', [])
1703    *       .value('mode', 'app')
1704    *       .value('version', 'v1.0.1');
1705    *
1706    *
1707    *   describe('MyApp', function() {
1708    *
1709    *     // You need to load modules that you want to test,
1710    *     // it loads only the "ng" module by default.
1711    *     beforeEach(module('myApplicationModule'));
1712    *
1713    *
1714    *     // inject() is used to inject arguments of all given functions
1715    *     it('should provide a version', inject(function(mode, version) {
1716    *       expect(version).toEqual('v1.0.1');
1717    *       expect(mode).toEqual('app');
1718    *     }));
1719    *
1720    *
1721    *     // The inject and module method can also be used inside of the it or beforeEach
1722    *     it('should override a version and test the new version is injected', function() {
1723    *       // module() takes functions or strings (module aliases)
1724    *       module(function($provide) {
1725    *         $provide.value('version', 'overridden'); // override version here
1726    *       });
1727    *
1728    *       inject(function(version) {
1729    *         expect(version).toEqual('overridden');
1730    *       });
1731    *     ));
1732    *   });
1733    *
1734    * </pre>
1735    *
1736    * @param {...Function} fns any number of functions which will be injected using the injector.
1737    */
1738   window.inject = angular.mock.inject = function() {
1739     var blockFns = Array.prototype.slice.call(arguments, 0);
1740     var errorForStack = new Error('Declaration Location');
1741     return isSpecRunning() ? workFn() : workFn;
1742     /////////////////////
1743     function workFn() {
1744       var spec = getCurrentSpec();
1745       var modules = spec.$modules || [];
1746       modules.unshift('ngMock');
1747       modules.unshift('ng');
1748       var injector = spec.$injector;
1749       if (!injector) {
1750         injector = spec.$injector = angular.injector(modules);
1751       }
1752       for(var i = 0, ii = blockFns.length; i < ii; i++) {
1753         try {
1754           injector.invoke(blockFns[i] || angular.noop, this);
1755         } catch (e) {
1756           if(e.stack) e.stack +=  '\n' + errorForStack.stack;
1757           throw e;
1758         } finally {
1759           errorForStack = null;
1760         }
1761       }
1762     }
1763   };
1764 })(window);