angular-gem 1.2.12 → 1.2.13

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