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