angular-gem 1.2.0.1 → 1.2.1

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