angular-gem 1.2.14 → 1.2.15

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