angular-gem 1.2.10 → 1.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2165 @@
1
+ /**
2
+ * @license AngularJS v1.2.11
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
+ var fnIndex;
515
+
516
+ angular.forEach(repeatFns, function(fn, index) {
517
+ if (fn.id === promise.$$intervalId) fnIndex = index;
518
+ });
519
+
520
+ if (fnIndex !== undefined) {
521
+ repeatFns[fnIndex].deferred.reject('canceled');
522
+ repeatFns.splice(fnIndex, 1);
523
+ return true;
524
+ }
525
+
526
+ return false;
527
+ };
528
+
529
+ /**
530
+ * @ngdoc method
531
+ * @name ngMock.$interval#flush
532
+ * @methodOf ngMock.$interval
533
+ * @description
534
+ *
535
+ * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
536
+ *
537
+ * @param {number=} millis maximum timeout amount to flush up until.
538
+ *
539
+ * @return {number} The amount of time moved forward.
540
+ */
541
+ $interval.flush = function(millis) {
542
+ now += millis;
543
+ while (repeatFns.length && repeatFns[0].nextTime <= now) {
544
+ var task = repeatFns[0];
545
+ task.fn();
546
+ task.nextTime += task.delay;
547
+ repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
548
+ }
549
+ return millis;
550
+ };
551
+
552
+ return $interval;
553
+ }];
554
+ };
555
+
556
+
557
+ /* jshint -W101 */
558
+ /* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
559
+ * This directive should go inside the anonymous function but a bug in JSHint means that it would
560
+ * not be enacted early enough to prevent the warning.
561
+ */
562
+ var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
563
+
564
+ function jsonStringToDate(string) {
565
+ var match;
566
+ if (match = string.match(R_ISO8061_STR)) {
567
+ var date = new Date(0),
568
+ tzHour = 0,
569
+ tzMin = 0;
570
+ if (match[9]) {
571
+ tzHour = int(match[9] + match[10]);
572
+ tzMin = int(match[9] + match[11]);
573
+ }
574
+ date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
575
+ date.setUTCHours(int(match[4]||0) - tzHour,
576
+ int(match[5]||0) - tzMin,
577
+ int(match[6]||0),
578
+ int(match[7]||0));
579
+ return date;
580
+ }
581
+ return string;
582
+ }
583
+
584
+ function int(str) {
585
+ return parseInt(str, 10);
586
+ }
587
+
588
+ function padNumber(num, digits, trim) {
589
+ var neg = '';
590
+ if (num < 0) {
591
+ neg = '-';
592
+ num = -num;
593
+ }
594
+ num = '' + num;
595
+ while(num.length < digits) num = '0' + num;
596
+ if (trim)
597
+ num = num.substr(num.length - digits);
598
+ return neg + num;
599
+ }
600
+
601
+
602
+ /**
603
+ * @ngdoc object
604
+ * @name angular.mock.TzDate
605
+ * @description
606
+ *
607
+ * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
608
+ *
609
+ * Mock of the Date type which has its timezone specified via constructor arg.
610
+ *
611
+ * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
612
+ * offset, so that we can test code that depends on local timezone settings without dependency on
613
+ * the time zone settings of the machine where the code is running.
614
+ *
615
+ * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
616
+ * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
617
+ *
618
+ * @example
619
+ * !!!! WARNING !!!!!
620
+ * This is not a complete Date object so only methods that were implemented can be called safely.
621
+ * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
622
+ *
623
+ * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
624
+ * incomplete we might be missing some non-standard methods. This can result in errors like:
625
+ * "Date.prototype.foo called on incompatible Object".
626
+ *
627
+ * <pre>
628
+ * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
629
+ * newYearInBratislava.getTimezoneOffset() => -60;
630
+ * newYearInBratislava.getFullYear() => 2010;
631
+ * newYearInBratislava.getMonth() => 0;
632
+ * newYearInBratislava.getDate() => 1;
633
+ * newYearInBratislava.getHours() => 0;
634
+ * newYearInBratislava.getMinutes() => 0;
635
+ * newYearInBratislava.getSeconds() => 0;
636
+ * </pre>
637
+ *
638
+ */
639
+ angular.mock.TzDate = function (offset, timestamp) {
640
+ var self = new Date(0);
641
+ if (angular.isString(timestamp)) {
642
+ var tsStr = timestamp;
643
+
644
+ self.origDate = jsonStringToDate(timestamp);
645
+
646
+ timestamp = self.origDate.getTime();
647
+ if (isNaN(timestamp))
648
+ throw {
649
+ name: "Illegal Argument",
650
+ message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
651
+ };
652
+ } else {
653
+ self.origDate = new Date(timestamp);
654
+ }
655
+
656
+ var localOffset = new Date(timestamp).getTimezoneOffset();
657
+ self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
658
+ self.date = new Date(timestamp + self.offsetDiff);
659
+
660
+ self.getTime = function() {
661
+ return self.date.getTime() - self.offsetDiff;
662
+ };
663
+
664
+ self.toLocaleDateString = function() {
665
+ return self.date.toLocaleDateString();
666
+ };
667
+
668
+ self.getFullYear = function() {
669
+ return self.date.getFullYear();
670
+ };
671
+
672
+ self.getMonth = function() {
673
+ return self.date.getMonth();
674
+ };
675
+
676
+ self.getDate = function() {
677
+ return self.date.getDate();
678
+ };
679
+
680
+ self.getHours = function() {
681
+ return self.date.getHours();
682
+ };
683
+
684
+ self.getMinutes = function() {
685
+ return self.date.getMinutes();
686
+ };
687
+
688
+ self.getSeconds = function() {
689
+ return self.date.getSeconds();
690
+ };
691
+
692
+ self.getMilliseconds = function() {
693
+ return self.date.getMilliseconds();
694
+ };
695
+
696
+ self.getTimezoneOffset = function() {
697
+ return offset * 60;
698
+ };
699
+
700
+ self.getUTCFullYear = function() {
701
+ return self.origDate.getUTCFullYear();
702
+ };
703
+
704
+ self.getUTCMonth = function() {
705
+ return self.origDate.getUTCMonth();
706
+ };
707
+
708
+ self.getUTCDate = function() {
709
+ return self.origDate.getUTCDate();
710
+ };
711
+
712
+ self.getUTCHours = function() {
713
+ return self.origDate.getUTCHours();
714
+ };
715
+
716
+ self.getUTCMinutes = function() {
717
+ return self.origDate.getUTCMinutes();
718
+ };
719
+
720
+ self.getUTCSeconds = function() {
721
+ return self.origDate.getUTCSeconds();
722
+ };
723
+
724
+ self.getUTCMilliseconds = function() {
725
+ return self.origDate.getUTCMilliseconds();
726
+ };
727
+
728
+ self.getDay = function() {
729
+ return self.date.getDay();
730
+ };
731
+
732
+ // provide this method only on browsers that already have it
733
+ if (self.toISOString) {
734
+ self.toISOString = function() {
735
+ return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
736
+ padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
737
+ padNumber(self.origDate.getUTCDate(), 2) + 'T' +
738
+ padNumber(self.origDate.getUTCHours(), 2) + ':' +
739
+ padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
740
+ padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
741
+ padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
742
+ };
743
+ }
744
+
745
+ //hide all methods not implemented in this mock that the Date prototype exposes
746
+ var unimplementedMethods = ['getUTCDay',
747
+ 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
748
+ 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
749
+ 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
750
+ 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
751
+ 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
752
+
753
+ angular.forEach(unimplementedMethods, function(methodName) {
754
+ self[methodName] = function() {
755
+ throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
756
+ };
757
+ });
758
+
759
+ return self;
760
+ };
761
+
762
+ //make "tzDateInstance instanceof Date" return true
763
+ angular.mock.TzDate.prototype = Date.prototype;
764
+ /* jshint +W101 */
765
+
766
+ // TODO(matias): remove this IMMEDIATELY once we can properly detect the
767
+ // presence of a registered module
768
+ var animateLoaded;
769
+ try {
770
+ angular.module('ngAnimate');
771
+ animateLoaded = true;
772
+ } catch(e) {}
773
+
774
+ if(animateLoaded) {
775
+ angular.module('ngAnimate').config(['$provide', function($provide) {
776
+ var reflowQueue = [];
777
+ $provide.value('$$animateReflow', function(fn) {
778
+ reflowQueue.push(fn);
779
+ return angular.noop;
780
+ });
781
+ $provide.decorator('$animate', function($delegate) {
782
+ $delegate.triggerReflow = function() {
783
+ if(reflowQueue.length === 0) {
784
+ throw new Error('No animation reflows present');
785
+ }
786
+ angular.forEach(reflowQueue, function(fn) {
787
+ fn();
788
+ });
789
+ reflowQueue = [];
790
+ };
791
+ return $delegate;
792
+ });
793
+ }]);
794
+ }
795
+
796
+ angular.mock.animate = angular.module('mock.animate', ['ng'])
797
+
798
+ .config(['$provide', function($provide) {
799
+
800
+ $provide.decorator('$animate', function($delegate) {
801
+ var animate = {
802
+ queue : [],
803
+ enabled : $delegate.enabled,
804
+ flushNext : function(name) {
805
+ var tick = animate.queue.shift();
806
+
807
+ if (!tick) throw new Error('No animation to be flushed');
808
+ if(tick.method !== name) {
809
+ throw new Error('The next animation is not "' + name +
810
+ '", but is "' + tick.method + '"');
811
+ }
812
+ tick.fn();
813
+ return tick;
814
+ }
815
+ };
816
+
817
+ angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) {
818
+ animate[method] = function() {
819
+ var params = arguments;
820
+ animate.queue.push({
821
+ method : method,
822
+ params : params,
823
+ element : angular.isElement(params[0]) && params[0],
824
+ parent : angular.isElement(params[1]) && params[1],
825
+ after : angular.isElement(params[2]) && params[2],
826
+ fn : function() {
827
+ $delegate[method].apply($delegate, params);
828
+ }
829
+ });
830
+ };
831
+ });
832
+
833
+ return animate;
834
+ });
835
+
836
+ }]);
837
+
838
+
839
+ /**
840
+ * @ngdoc function
841
+ * @name angular.mock.dump
842
+ * @description
843
+ *
844
+ * *NOTE*: this is not an injectable instance, just a globally available function.
845
+ *
846
+ * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
847
+ * debugging.
848
+ *
849
+ * This method is also available on window, where it can be used to display objects on debug
850
+ * console.
851
+ *
852
+ * @param {*} object - any object to turn into string.
853
+ * @return {string} a serialized string of the argument
854
+ */
855
+ angular.mock.dump = function(object) {
856
+ return serialize(object);
857
+
858
+ function serialize(object) {
859
+ var out;
860
+
861
+ if (angular.isElement(object)) {
862
+ object = angular.element(object);
863
+ out = angular.element('<div></div>');
864
+ angular.forEach(object, function(element) {
865
+ out.append(angular.element(element).clone());
866
+ });
867
+ out = out.html();
868
+ } else if (angular.isArray(object)) {
869
+ out = [];
870
+ angular.forEach(object, function(o) {
871
+ out.push(serialize(o));
872
+ });
873
+ out = '[ ' + out.join(', ') + ' ]';
874
+ } else if (angular.isObject(object)) {
875
+ if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
876
+ out = serializeScope(object);
877
+ } else if (object instanceof Error) {
878
+ out = object.stack || ('' + object.name + ': ' + object.message);
879
+ } else {
880
+ // TODO(i): this prevents methods being logged,
881
+ // we should have a better way to serialize objects
882
+ out = angular.toJson(object, true);
883
+ }
884
+ } else {
885
+ out = String(object);
886
+ }
887
+
888
+ return out;
889
+ }
890
+
891
+ function serializeScope(scope, offset) {
892
+ offset = offset || ' ';
893
+ var log = [offset + 'Scope(' + scope.$id + '): {'];
894
+ for ( var key in scope ) {
895
+ if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
896
+ log.push(' ' + key + ': ' + angular.toJson(scope[key]));
897
+ }
898
+ }
899
+ var child = scope.$$childHead;
900
+ while(child) {
901
+ log.push(serializeScope(child, offset + ' '));
902
+ child = child.$$nextSibling;
903
+ }
904
+ log.push('}');
905
+ return log.join('\n' + offset);
906
+ }
907
+ };
908
+
909
+ /**
910
+ * @ngdoc object
911
+ * @name ngMock.$httpBackend
912
+ * @description
913
+ * Fake HTTP backend implementation suitable for unit testing applications that use the
914
+ * {@link ng.$http $http service}.
915
+ *
916
+ * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
917
+ * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
918
+ *
919
+ * During unit testing, we want our unit tests to run quickly and have no external dependencies so
920
+ * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
921
+ * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
922
+ * to verify whether a certain request has been sent or not, or alternatively just let the
923
+ * application make requests, respond with pre-trained responses and assert that the end result is
924
+ * what we expect it to be.
925
+ *
926
+ * This mock implementation can be used to respond with static or dynamic responses via the
927
+ * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
928
+ *
929
+ * When an Angular application needs some data from a server, it calls the $http service, which
930
+ * sends the request to a real server using $httpBackend service. With dependency injection, it is
931
+ * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
932
+ * the requests and respond with some testing data without sending a request to real server.
933
+ *
934
+ * There are two ways to specify what test data should be returned as http responses by the mock
935
+ * backend when the code under test makes http requests:
936
+ *
937
+ * - `$httpBackend.expect` - specifies a request expectation
938
+ * - `$httpBackend.when` - specifies a backend definition
939
+ *
940
+ *
941
+ * # Request Expectations vs Backend Definitions
942
+ *
943
+ * Request expectations provide a way to make assertions about requests made by the application and
944
+ * to define responses for those requests. The test will fail if the expected requests are not made
945
+ * or they are made in the wrong order.
946
+ *
947
+ * Backend definitions allow you to define a fake backend for your application which doesn't assert
948
+ * if a particular request was made or not, it just returns a trained response if a request is made.
949
+ * The test will pass whether or not the request gets made during testing.
950
+ *
951
+ *
952
+ * <table class="table">
953
+ * <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
954
+ * <tr>
955
+ * <th>Syntax</th>
956
+ * <td>.expect(...).respond(...)</td>
957
+ * <td>.when(...).respond(...)</td>
958
+ * </tr>
959
+ * <tr>
960
+ * <th>Typical usage</th>
961
+ * <td>strict unit tests</td>
962
+ * <td>loose (black-box) unit testing</td>
963
+ * </tr>
964
+ * <tr>
965
+ * <th>Fulfills multiple requests</th>
966
+ * <td>NO</td>
967
+ * <td>YES</td>
968
+ * </tr>
969
+ * <tr>
970
+ * <th>Order of requests matters</th>
971
+ * <td>YES</td>
972
+ * <td>NO</td>
973
+ * </tr>
974
+ * <tr>
975
+ * <th>Request required</th>
976
+ * <td>YES</td>
977
+ * <td>NO</td>
978
+ * </tr>
979
+ * <tr>
980
+ * <th>Response required</th>
981
+ * <td>optional (see below)</td>
982
+ * <td>YES</td>
983
+ * </tr>
984
+ * </table>
985
+ *
986
+ * In cases where both backend definitions and request expectations are specified during unit
987
+ * testing, the request expectations are evaluated first.
988
+ *
989
+ * If a request expectation has no response specified, the algorithm will search your backend
990
+ * definitions for an appropriate response.
991
+ *
992
+ * If a request didn't match any expectation or if the expectation doesn't have the response
993
+ * defined, the backend definitions are evaluated in sequential order to see if any of them match
994
+ * the request. The response from the first matched definition is returned.
995
+ *
996
+ *
997
+ * # Flushing HTTP requests
998
+ *
999
+ * The $httpBackend used in production always responds to requests with responses asynchronously.
1000
+ * If we preserved this behavior in unit testing we'd have to create async unit tests, which are
1001
+ * hard to write, understand, and maintain. However, the testing mock can't respond
1002
+ * synchronously because that would change the execution of the code under test. For this reason the
1003
+ * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
1004
+ * requests and thus preserve the async api of the backend while allowing the test to execute
1005
+ * synchronously.
1006
+ *
1007
+ *
1008
+ * # Unit testing with mock $httpBackend
1009
+ * The following code shows how to setup and use the mock backend when unit testing a controller.
1010
+ * First we create the controller under test:
1011
+ *
1012
+ <pre>
1013
+ // The controller code
1014
+ function MyController($scope, $http) {
1015
+ var authToken;
1016
+
1017
+ $http.get('/auth.py').success(function(data, status, headers) {
1018
+ authToken = headers('A-Token');
1019
+ $scope.user = data;
1020
+ });
1021
+
1022
+ $scope.saveMessage = function(message) {
1023
+ var headers = { 'Authorization': authToken };
1024
+ $scope.status = 'Saving...';
1025
+
1026
+ $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
1027
+ $scope.status = '';
1028
+ }).error(function() {
1029
+ $scope.status = 'ERROR!';
1030
+ });
1031
+ };
1032
+ }
1033
+ </pre>
1034
+ *
1035
+ * Now we setup the mock backend and create the test specs:
1036
+ *
1037
+ <pre>
1038
+ // testing controller
1039
+ describe('MyController', function() {
1040
+ var $httpBackend, $rootScope, createController;
1041
+
1042
+ beforeEach(inject(function($injector) {
1043
+ // Set up the mock http service responses
1044
+ $httpBackend = $injector.get('$httpBackend');
1045
+ // backend definition common for all tests
1046
+ $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
1047
+
1048
+ // Get hold of a scope (i.e. the root scope)
1049
+ $rootScope = $injector.get('$rootScope');
1050
+ // The $controller service is used to create instances of controllers
1051
+ var $controller = $injector.get('$controller');
1052
+
1053
+ createController = function() {
1054
+ return $controller('MyController', {'$scope' : $rootScope });
1055
+ };
1056
+ }));
1057
+
1058
+
1059
+ afterEach(function() {
1060
+ $httpBackend.verifyNoOutstandingExpectation();
1061
+ $httpBackend.verifyNoOutstandingRequest();
1062
+ });
1063
+
1064
+
1065
+ it('should fetch authentication token', function() {
1066
+ $httpBackend.expectGET('/auth.py');
1067
+ var controller = createController();
1068
+ $httpBackend.flush();
1069
+ });
1070
+
1071
+
1072
+ it('should send msg to server', function() {
1073
+ var controller = createController();
1074
+ $httpBackend.flush();
1075
+
1076
+ // now you don’t care about the authentication, but
1077
+ // the controller will still send the request and
1078
+ // $httpBackend will respond without you having to
1079
+ // specify the expectation and response for this request
1080
+
1081
+ $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
1082
+ $rootScope.saveMessage('message content');
1083
+ expect($rootScope.status).toBe('Saving...');
1084
+ $httpBackend.flush();
1085
+ expect($rootScope.status).toBe('');
1086
+ });
1087
+
1088
+
1089
+ it('should send auth header', function() {
1090
+ var controller = createController();
1091
+ $httpBackend.flush();
1092
+
1093
+ $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
1094
+ // check if the header was send, if it wasn't the expectation won't
1095
+ // match the request and the test will fail
1096
+ return headers['Authorization'] == 'xxx';
1097
+ }).respond(201, '');
1098
+
1099
+ $rootScope.saveMessage('whatever');
1100
+ $httpBackend.flush();
1101
+ });
1102
+ });
1103
+ </pre>
1104
+ */
1105
+ angular.mock.$HttpBackendProvider = function() {
1106
+ this.$get = ['$rootScope', createHttpBackendMock];
1107
+ };
1108
+
1109
+ /**
1110
+ * General factory function for $httpBackend mock.
1111
+ * Returns instance for unit testing (when no arguments specified):
1112
+ * - passing through is disabled
1113
+ * - auto flushing is disabled
1114
+ *
1115
+ * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
1116
+ * - passing through (delegating request to real backend) is enabled
1117
+ * - auto flushing is enabled
1118
+ *
1119
+ * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
1120
+ * @param {Object=} $browser Auto-flushing enabled if specified
1121
+ * @return {Object} Instance of $httpBackend mock
1122
+ */
1123
+ function createHttpBackendMock($rootScope, $delegate, $browser) {
1124
+ var definitions = [],
1125
+ expectations = [],
1126
+ responses = [],
1127
+ responsesPush = angular.bind(responses, responses.push),
1128
+ copy = angular.copy;
1129
+
1130
+ function createResponse(status, data, headers) {
1131
+ if (angular.isFunction(status)) return status;
1132
+
1133
+ return function() {
1134
+ return angular.isNumber(status)
1135
+ ? [status, data, headers]
1136
+ : [200, status, data];
1137
+ };
1138
+ }
1139
+
1140
+ // TODO(vojta): change params to: method, url, data, headers, callback
1141
+ function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
1142
+ var xhr = new MockXhr(),
1143
+ expectation = expectations[0],
1144
+ wasExpected = false;
1145
+
1146
+ function prettyPrint(data) {
1147
+ return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
1148
+ ? data
1149
+ : angular.toJson(data);
1150
+ }
1151
+
1152
+ function wrapResponse(wrapped) {
1153
+ if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
1154
+
1155
+ return handleResponse;
1156
+
1157
+ function handleResponse() {
1158
+ var response = wrapped.response(method, url, data, headers);
1159
+ xhr.$$respHeaders = response[2];
1160
+ callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());
1161
+ }
1162
+
1163
+ function handleTimeout() {
1164
+ for (var i = 0, ii = responses.length; i < ii; i++) {
1165
+ if (responses[i] === handleResponse) {
1166
+ responses.splice(i, 1);
1167
+ callback(-1, undefined, '');
1168
+ break;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+
1174
+ if (expectation && expectation.match(method, url)) {
1175
+ if (!expectation.matchData(data))
1176
+ throw new Error('Expected ' + expectation + ' with different data\n' +
1177
+ 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
1178
+
1179
+ if (!expectation.matchHeaders(headers))
1180
+ throw new Error('Expected ' + expectation + ' with different headers\n' +
1181
+ 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
1182
+ prettyPrint(headers));
1183
+
1184
+ expectations.shift();
1185
+
1186
+ if (expectation.response) {
1187
+ responses.push(wrapResponse(expectation));
1188
+ return;
1189
+ }
1190
+ wasExpected = true;
1191
+ }
1192
+
1193
+ var i = -1, definition;
1194
+ while ((definition = definitions[++i])) {
1195
+ if (definition.match(method, url, data, headers || {})) {
1196
+ if (definition.response) {
1197
+ // if $browser specified, we do auto flush all requests
1198
+ ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
1199
+ } else if (definition.passThrough) {
1200
+ $delegate(method, url, data, callback, headers, timeout, withCredentials);
1201
+ } else throw new Error('No response defined !');
1202
+ return;
1203
+ }
1204
+ }
1205
+ throw wasExpected ?
1206
+ new Error('No response defined !') :
1207
+ new Error('Unexpected request: ' + method + ' ' + url + '\n' +
1208
+ (expectation ? 'Expected ' + expectation : 'No more request expected'));
1209
+ }
1210
+
1211
+ /**
1212
+ * @ngdoc method
1213
+ * @name ngMock.$httpBackend#when
1214
+ * @methodOf ngMock.$httpBackend
1215
+ * @description
1216
+ * Creates a new backend definition.
1217
+ *
1218
+ * @param {string} method HTTP method.
1219
+ * @param {string|RegExp} url HTTP url.
1220
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1221
+ * data string and returns true if the data is as expected.
1222
+ * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1223
+ * object and returns true if the headers match the current definition.
1224
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1225
+ * request is handled.
1226
+ *
1227
+ * - respond –
1228
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1229
+ * – The respond method takes a set of static data to be returned or a function that can return
1230
+ * an array containing response status (number), response data (string) and response headers
1231
+ * (Object).
1232
+ */
1233
+ $httpBackend.when = function(method, url, data, headers) {
1234
+ var definition = new MockHttpExpectation(method, url, data, headers),
1235
+ chain = {
1236
+ respond: function(status, data, headers) {
1237
+ definition.response = createResponse(status, data, headers);
1238
+ }
1239
+ };
1240
+
1241
+ if ($browser) {
1242
+ chain.passThrough = function() {
1243
+ definition.passThrough = true;
1244
+ };
1245
+ }
1246
+
1247
+ definitions.push(definition);
1248
+ return chain;
1249
+ };
1250
+
1251
+ /**
1252
+ * @ngdoc method
1253
+ * @name ngMock.$httpBackend#whenGET
1254
+ * @methodOf ngMock.$httpBackend
1255
+ * @description
1256
+ * Creates a new backend definition for GET requests. For more info see `when()`.
1257
+ *
1258
+ * @param {string|RegExp} url HTTP url.
1259
+ * @param {(Object|function(Object))=} headers HTTP headers.
1260
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1261
+ * request is handled.
1262
+ */
1263
+
1264
+ /**
1265
+ * @ngdoc method
1266
+ * @name ngMock.$httpBackend#whenHEAD
1267
+ * @methodOf ngMock.$httpBackend
1268
+ * @description
1269
+ * Creates a new backend definition for HEAD requests. For more info see `when()`.
1270
+ *
1271
+ * @param {string|RegExp} url HTTP url.
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#whenDELETE
1280
+ * @methodOf ngMock.$httpBackend
1281
+ * @description
1282
+ * Creates a new backend definition for DELETE requests. For more info see `when()`.
1283
+ *
1284
+ * @param {string|RegExp} url HTTP url.
1285
+ * @param {(Object|function(Object))=} headers HTTP headers.
1286
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1287
+ * request is handled.
1288
+ */
1289
+
1290
+ /**
1291
+ * @ngdoc method
1292
+ * @name ngMock.$httpBackend#whenPOST
1293
+ * @methodOf ngMock.$httpBackend
1294
+ * @description
1295
+ * Creates a new backend definition for POST requests. For more info see `when()`.
1296
+ *
1297
+ * @param {string|RegExp} url HTTP url.
1298
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1299
+ * data string and returns true if the data is as expected.
1300
+ * @param {(Object|function(Object))=} headers HTTP headers.
1301
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1302
+ * request is handled.
1303
+ */
1304
+
1305
+ /**
1306
+ * @ngdoc method
1307
+ * @name ngMock.$httpBackend#whenPUT
1308
+ * @methodOf ngMock.$httpBackend
1309
+ * @description
1310
+ * Creates a new backend definition for PUT requests. For more info see `when()`.
1311
+ *
1312
+ * @param {string|RegExp} url HTTP url.
1313
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1314
+ * data string and returns true if the data is as expected.
1315
+ * @param {(Object|function(Object))=} headers HTTP headers.
1316
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1317
+ * request is handled.
1318
+ */
1319
+
1320
+ /**
1321
+ * @ngdoc method
1322
+ * @name ngMock.$httpBackend#whenJSONP
1323
+ * @methodOf ngMock.$httpBackend
1324
+ * @description
1325
+ * Creates a new backend definition for JSONP requests. For more info see `when()`.
1326
+ *
1327
+ * @param {string|RegExp} url HTTP url.
1328
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1329
+ * request is handled.
1330
+ */
1331
+ createShortMethods('when');
1332
+
1333
+
1334
+ /**
1335
+ * @ngdoc method
1336
+ * @name ngMock.$httpBackend#expect
1337
+ * @methodOf ngMock.$httpBackend
1338
+ * @description
1339
+ * Creates a new request expectation.
1340
+ *
1341
+ * @param {string} method HTTP method.
1342
+ * @param {string|RegExp} url HTTP url.
1343
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1344
+ * receives data string and returns true if the data is as expected, or Object if request body
1345
+ * is in JSON format.
1346
+ * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1347
+ * object and returns true if the headers match the current expectation.
1348
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1349
+ * request is handled.
1350
+ *
1351
+ * - respond –
1352
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1353
+ * – The respond method takes a set of static data to be returned or a function that can return
1354
+ * an array containing response status (number), response data (string) and response headers
1355
+ * (Object).
1356
+ */
1357
+ $httpBackend.expect = function(method, url, data, headers) {
1358
+ var expectation = new MockHttpExpectation(method, url, data, headers);
1359
+ expectations.push(expectation);
1360
+ return {
1361
+ respond: function(status, data, headers) {
1362
+ expectation.response = createResponse(status, data, headers);
1363
+ }
1364
+ };
1365
+ };
1366
+
1367
+
1368
+ /**
1369
+ * @ngdoc method
1370
+ * @name ngMock.$httpBackend#expectGET
1371
+ * @methodOf ngMock.$httpBackend
1372
+ * @description
1373
+ * Creates a new request expectation for GET requests. For more info see `expect()`.
1374
+ *
1375
+ * @param {string|RegExp} url HTTP url.
1376
+ * @param {Object=} headers HTTP headers.
1377
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1378
+ * request is handled. See #expect for more info.
1379
+ */
1380
+
1381
+ /**
1382
+ * @ngdoc method
1383
+ * @name ngMock.$httpBackend#expectHEAD
1384
+ * @methodOf ngMock.$httpBackend
1385
+ * @description
1386
+ * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1387
+ *
1388
+ * @param {string|RegExp} url HTTP url.
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#expectDELETE
1397
+ * @methodOf ngMock.$httpBackend
1398
+ * @description
1399
+ * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1400
+ *
1401
+ * @param {string|RegExp} url HTTP url.
1402
+ * @param {Object=} headers HTTP headers.
1403
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1404
+ * request is handled.
1405
+ */
1406
+
1407
+ /**
1408
+ * @ngdoc method
1409
+ * @name ngMock.$httpBackend#expectPOST
1410
+ * @methodOf ngMock.$httpBackend
1411
+ * @description
1412
+ * Creates a new request expectation for POST requests. For more info see `expect()`.
1413
+ *
1414
+ * @param {string|RegExp} url HTTP url.
1415
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1416
+ * receives data string and returns true if the data is as expected, or Object if request body
1417
+ * is in JSON format.
1418
+ * @param {Object=} headers HTTP headers.
1419
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1420
+ * request is handled.
1421
+ */
1422
+
1423
+ /**
1424
+ * @ngdoc method
1425
+ * @name ngMock.$httpBackend#expectPUT
1426
+ * @methodOf ngMock.$httpBackend
1427
+ * @description
1428
+ * Creates a new request expectation for PUT requests. For more info see `expect()`.
1429
+ *
1430
+ * @param {string|RegExp} url HTTP url.
1431
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1432
+ * receives data string and returns true if the data is as expected, or Object if request body
1433
+ * is in JSON format.
1434
+ * @param {Object=} headers HTTP headers.
1435
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1436
+ * request is handled.
1437
+ */
1438
+
1439
+ /**
1440
+ * @ngdoc method
1441
+ * @name ngMock.$httpBackend#expectPATCH
1442
+ * @methodOf ngMock.$httpBackend
1443
+ * @description
1444
+ * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1445
+ *
1446
+ * @param {string|RegExp} url HTTP url.
1447
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1448
+ * receives data string and returns true if the data is as expected, or Object if request body
1449
+ * is in JSON format.
1450
+ * @param {Object=} headers HTTP headers.
1451
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1452
+ * request is handled.
1453
+ */
1454
+
1455
+ /**
1456
+ * @ngdoc method
1457
+ * @name ngMock.$httpBackend#expectJSONP
1458
+ * @methodOf ngMock.$httpBackend
1459
+ * @description
1460
+ * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1461
+ *
1462
+ * @param {string|RegExp} url HTTP url.
1463
+ * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1464
+ * request is handled.
1465
+ */
1466
+ createShortMethods('expect');
1467
+
1468
+
1469
+ /**
1470
+ * @ngdoc method
1471
+ * @name ngMock.$httpBackend#flush
1472
+ * @methodOf ngMock.$httpBackend
1473
+ * @description
1474
+ * Flushes all pending requests using the trained responses.
1475
+ *
1476
+ * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
1477
+ * all pending requests will be flushed. If there are no pending requests when the flush method
1478
+ * is called an exception is thrown (as this typically a sign of programming error).
1479
+ */
1480
+ $httpBackend.flush = function(count) {
1481
+ $rootScope.$digest();
1482
+ if (!responses.length) throw new Error('No pending request to flush !');
1483
+
1484
+ if (angular.isDefined(count)) {
1485
+ while (count--) {
1486
+ if (!responses.length) throw new Error('No more pending request to flush !');
1487
+ responses.shift()();
1488
+ }
1489
+ } else {
1490
+ while (responses.length) {
1491
+ responses.shift()();
1492
+ }
1493
+ }
1494
+ $httpBackend.verifyNoOutstandingExpectation();
1495
+ };
1496
+
1497
+
1498
+ /**
1499
+ * @ngdoc method
1500
+ * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
1501
+ * @methodOf ngMock.$httpBackend
1502
+ * @description
1503
+ * Verifies that all of the requests defined via the `expect` api were made. If any of the
1504
+ * requests were not made, verifyNoOutstandingExpectation throws an exception.
1505
+ *
1506
+ * Typically, you would call this method following each test case that asserts requests using an
1507
+ * "afterEach" clause.
1508
+ *
1509
+ * <pre>
1510
+ * afterEach($httpBackend.verifyNoOutstandingExpectation);
1511
+ * </pre>
1512
+ */
1513
+ $httpBackend.verifyNoOutstandingExpectation = function() {
1514
+ $rootScope.$digest();
1515
+ if (expectations.length) {
1516
+ throw new Error('Unsatisfied requests: ' + expectations.join(', '));
1517
+ }
1518
+ };
1519
+
1520
+
1521
+ /**
1522
+ * @ngdoc method
1523
+ * @name ngMock.$httpBackend#verifyNoOutstandingRequest
1524
+ * @methodOf ngMock.$httpBackend
1525
+ * @description
1526
+ * Verifies that there are no outstanding requests that need to be flushed.
1527
+ *
1528
+ * Typically, you would call this method following each test case that asserts requests using an
1529
+ * "afterEach" clause.
1530
+ *
1531
+ * <pre>
1532
+ * afterEach($httpBackend.verifyNoOutstandingRequest);
1533
+ * </pre>
1534
+ */
1535
+ $httpBackend.verifyNoOutstandingRequest = function() {
1536
+ if (responses.length) {
1537
+ throw new Error('Unflushed requests: ' + responses.length);
1538
+ }
1539
+ };
1540
+
1541
+
1542
+ /**
1543
+ * @ngdoc method
1544
+ * @name ngMock.$httpBackend#resetExpectations
1545
+ * @methodOf ngMock.$httpBackend
1546
+ * @description
1547
+ * Resets all request expectations, but preserves all backend definitions. Typically, you would
1548
+ * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
1549
+ * $httpBackend mock.
1550
+ */
1551
+ $httpBackend.resetExpectations = function() {
1552
+ expectations.length = 0;
1553
+ responses.length = 0;
1554
+ };
1555
+
1556
+ return $httpBackend;
1557
+
1558
+
1559
+ function createShortMethods(prefix) {
1560
+ angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
1561
+ $httpBackend[prefix + method] = function(url, headers) {
1562
+ return $httpBackend[prefix](method, url, undefined, headers);
1563
+ };
1564
+ });
1565
+
1566
+ angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
1567
+ $httpBackend[prefix + method] = function(url, data, headers) {
1568
+ return $httpBackend[prefix](method, url, data, headers);
1569
+ };
1570
+ });
1571
+ }
1572
+ }
1573
+
1574
+ function MockHttpExpectation(method, url, data, headers) {
1575
+
1576
+ this.data = data;
1577
+ this.headers = headers;
1578
+
1579
+ this.match = function(m, u, d, h) {
1580
+ if (method != m) return false;
1581
+ if (!this.matchUrl(u)) return false;
1582
+ if (angular.isDefined(d) && !this.matchData(d)) return false;
1583
+ if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
1584
+ return true;
1585
+ };
1586
+
1587
+ this.matchUrl = function(u) {
1588
+ if (!url) return true;
1589
+ if (angular.isFunction(url.test)) return url.test(u);
1590
+ return url == u;
1591
+ };
1592
+
1593
+ this.matchHeaders = function(h) {
1594
+ if (angular.isUndefined(headers)) return true;
1595
+ if (angular.isFunction(headers)) return headers(h);
1596
+ return angular.equals(headers, h);
1597
+ };
1598
+
1599
+ this.matchData = function(d) {
1600
+ if (angular.isUndefined(data)) return true;
1601
+ if (data && angular.isFunction(data.test)) return data.test(d);
1602
+ if (data && angular.isFunction(data)) return data(d);
1603
+ if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d));
1604
+ return data == d;
1605
+ };
1606
+
1607
+ this.toString = function() {
1608
+ return method + ' ' + url;
1609
+ };
1610
+ }
1611
+
1612
+ function createMockXhr() {
1613
+ return new MockXhr();
1614
+ }
1615
+
1616
+ function MockXhr() {
1617
+
1618
+ // hack for testing $http, $httpBackend
1619
+ MockXhr.$$lastInstance = this;
1620
+
1621
+ this.open = function(method, url, async) {
1622
+ this.$$method = method;
1623
+ this.$$url = url;
1624
+ this.$$async = async;
1625
+ this.$$reqHeaders = {};
1626
+ this.$$respHeaders = {};
1627
+ };
1628
+
1629
+ this.send = function(data) {
1630
+ this.$$data = data;
1631
+ };
1632
+
1633
+ this.setRequestHeader = function(key, value) {
1634
+ this.$$reqHeaders[key] = value;
1635
+ };
1636
+
1637
+ this.getResponseHeader = function(name) {
1638
+ // the lookup must be case insensitive,
1639
+ // that's why we try two quick lookups first and full scan last
1640
+ var header = this.$$respHeaders[name];
1641
+ if (header) return header;
1642
+
1643
+ name = angular.lowercase(name);
1644
+ header = this.$$respHeaders[name];
1645
+ if (header) return header;
1646
+
1647
+ header = undefined;
1648
+ angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
1649
+ if (!header && angular.lowercase(headerName) == name) header = headerVal;
1650
+ });
1651
+ return header;
1652
+ };
1653
+
1654
+ this.getAllResponseHeaders = function() {
1655
+ var lines = [];
1656
+
1657
+ angular.forEach(this.$$respHeaders, function(value, key) {
1658
+ lines.push(key + ': ' + value);
1659
+ });
1660
+ return lines.join('\n');
1661
+ };
1662
+
1663
+ this.abort = angular.noop;
1664
+ }
1665
+
1666
+
1667
+ /**
1668
+ * @ngdoc function
1669
+ * @name ngMock.$timeout
1670
+ * @description
1671
+ *
1672
+ * This service is just a simple decorator for {@link ng.$timeout $timeout} service
1673
+ * that adds a "flush" and "verifyNoPendingTasks" methods.
1674
+ */
1675
+
1676
+ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
1677
+
1678
+ /**
1679
+ * @ngdoc method
1680
+ * @name ngMock.$timeout#flush
1681
+ * @methodOf ngMock.$timeout
1682
+ * @description
1683
+ *
1684
+ * Flushes the queue of pending tasks.
1685
+ *
1686
+ * @param {number=} delay maximum timeout amount to flush up until
1687
+ */
1688
+ $delegate.flush = function(delay) {
1689
+ $browser.defer.flush(delay);
1690
+ };
1691
+
1692
+ /**
1693
+ * @ngdoc method
1694
+ * @name ngMock.$timeout#verifyNoPendingTasks
1695
+ * @methodOf ngMock.$timeout
1696
+ * @description
1697
+ *
1698
+ * Verifies that there are no pending tasks that need to be flushed.
1699
+ */
1700
+ $delegate.verifyNoPendingTasks = function() {
1701
+ if ($browser.deferredFns.length) {
1702
+ throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
1703
+ formatPendingTasksAsString($browser.deferredFns));
1704
+ }
1705
+ };
1706
+
1707
+ function formatPendingTasksAsString(tasks) {
1708
+ var result = [];
1709
+ angular.forEach(tasks, function(task) {
1710
+ result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
1711
+ });
1712
+
1713
+ return result.join(', ');
1714
+ }
1715
+
1716
+ return $delegate;
1717
+ };
1718
+
1719
+ /**
1720
+ *
1721
+ */
1722
+ angular.mock.$RootElementProvider = function() {
1723
+ this.$get = function() {
1724
+ return angular.element('<div ng-app></div>');
1725
+ };
1726
+ };
1727
+
1728
+ /**
1729
+ * @ngdoc overview
1730
+ * @name ngMock
1731
+ * @description
1732
+ *
1733
+ * # ngMock
1734
+ *
1735
+ * The `ngMock` module providers support to inject and mock Angular services into unit tests.
1736
+ * In addition, ngMock also extends various core ng services such that they can be
1737
+ * inspected and controlled in a synchronous manner within test code.
1738
+ *
1739
+ * {@installModule mock}
1740
+ *
1741
+ * <div doc-module-components="ngMock"></div>
1742
+ *
1743
+ */
1744
+ angular.module('ngMock', ['ng']).provider({
1745
+ $browser: angular.mock.$BrowserProvider,
1746
+ $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
1747
+ $log: angular.mock.$LogProvider,
1748
+ $interval: angular.mock.$IntervalProvider,
1749
+ $httpBackend: angular.mock.$HttpBackendProvider,
1750
+ $rootElement: angular.mock.$RootElementProvider
1751
+ }).config(['$provide', function($provide) {
1752
+ $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
1753
+ }]);
1754
+
1755
+ /**
1756
+ * @ngdoc overview
1757
+ * @name ngMockE2E
1758
+ * @description
1759
+ *
1760
+ * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
1761
+ * Currently there is only one mock present in this module -
1762
+ * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
1763
+ */
1764
+ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1765
+ $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
1766
+ }]);
1767
+
1768
+ /**
1769
+ * @ngdoc object
1770
+ * @name ngMockE2E.$httpBackend
1771
+ * @description
1772
+ * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
1773
+ * applications that use the {@link ng.$http $http service}.
1774
+ *
1775
+ * *Note*: For fake http backend implementation suitable for unit testing please see
1776
+ * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
1777
+ *
1778
+ * This implementation can be used to respond with static or dynamic responses via the `when` api
1779
+ * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
1780
+ * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
1781
+ * templates from a webserver).
1782
+ *
1783
+ * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
1784
+ * is being developed with the real backend api replaced with a mock, it is often desirable for
1785
+ * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
1786
+ * templates or static files from the webserver). To configure the backend with this behavior
1787
+ * use the `passThrough` request handler of `when` instead of `respond`.
1788
+ *
1789
+ * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
1790
+ * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
1791
+ * automatically, closely simulating the behavior of the XMLHttpRequest object.
1792
+ *
1793
+ * To setup the application to run with this http backend, you have to create a module that depends
1794
+ * on the `ngMockE2E` and your application modules and defines the fake backend:
1795
+ *
1796
+ * <pre>
1797
+ * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
1798
+ * myAppDev.run(function($httpBackend) {
1799
+ * phones = [{name: 'phone1'}, {name: 'phone2'}];
1800
+ *
1801
+ * // returns the current list of phones
1802
+ * $httpBackend.whenGET('/phones').respond(phones);
1803
+ *
1804
+ * // adds a new phone to the phones array
1805
+ * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
1806
+ * phones.push(angular.fromJson(data));
1807
+ * });
1808
+ * $httpBackend.whenGET(/^\/templates\//).passThrough();
1809
+ * //...
1810
+ * });
1811
+ * </pre>
1812
+ *
1813
+ * Afterwards, bootstrap your app with this new module.
1814
+ */
1815
+
1816
+ /**
1817
+ * @ngdoc method
1818
+ * @name ngMockE2E.$httpBackend#when
1819
+ * @methodOf ngMockE2E.$httpBackend
1820
+ * @description
1821
+ * Creates a new backend definition.
1822
+ *
1823
+ * @param {string} method HTTP method.
1824
+ * @param {string|RegExp} url HTTP url.
1825
+ * @param {(string|RegExp)=} data HTTP request body.
1826
+ * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1827
+ * object and returns true if the headers match the current definition.
1828
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1829
+ * control how a matched request is handled.
1830
+ *
1831
+ * - respond –
1832
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1833
+ * – The respond method takes a set of static data to be returned or a function that can return
1834
+ * an array containing response status (number), response data (string) and response headers
1835
+ * (Object).
1836
+ * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
1837
+ * handler, will be pass through to the real backend (an XHR request will be made to the
1838
+ * server.
1839
+ */
1840
+
1841
+ /**
1842
+ * @ngdoc method
1843
+ * @name ngMockE2E.$httpBackend#whenGET
1844
+ * @methodOf ngMockE2E.$httpBackend
1845
+ * @description
1846
+ * Creates a new backend definition for GET requests. For more info see `when()`.
1847
+ *
1848
+ * @param {string|RegExp} url HTTP url.
1849
+ * @param {(Object|function(Object))=} headers HTTP headers.
1850
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1851
+ * control how a matched request is handled.
1852
+ */
1853
+
1854
+ /**
1855
+ * @ngdoc method
1856
+ * @name ngMockE2E.$httpBackend#whenHEAD
1857
+ * @methodOf ngMockE2E.$httpBackend
1858
+ * @description
1859
+ * Creates a new backend definition for HEAD requests. For more info see `when()`.
1860
+ *
1861
+ * @param {string|RegExp} url HTTP url.
1862
+ * @param {(Object|function(Object))=} headers HTTP headers.
1863
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1864
+ * control how a matched request is handled.
1865
+ */
1866
+
1867
+ /**
1868
+ * @ngdoc method
1869
+ * @name ngMockE2E.$httpBackend#whenDELETE
1870
+ * @methodOf ngMockE2E.$httpBackend
1871
+ * @description
1872
+ * Creates a new backend definition for DELETE requests. For more info see `when()`.
1873
+ *
1874
+ * @param {string|RegExp} url HTTP url.
1875
+ * @param {(Object|function(Object))=} headers HTTP headers.
1876
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1877
+ * control how a matched request is handled.
1878
+ */
1879
+
1880
+ /**
1881
+ * @ngdoc method
1882
+ * @name ngMockE2E.$httpBackend#whenPOST
1883
+ * @methodOf ngMockE2E.$httpBackend
1884
+ * @description
1885
+ * Creates a new backend definition for POST requests. For more info see `when()`.
1886
+ *
1887
+ * @param {string|RegExp} url HTTP url.
1888
+ * @param {(string|RegExp)=} data HTTP request body.
1889
+ * @param {(Object|function(Object))=} headers HTTP headers.
1890
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1891
+ * control how a matched request is handled.
1892
+ */
1893
+
1894
+ /**
1895
+ * @ngdoc method
1896
+ * @name ngMockE2E.$httpBackend#whenPUT
1897
+ * @methodOf ngMockE2E.$httpBackend
1898
+ * @description
1899
+ * Creates a new backend definition for PUT requests. For more info see `when()`.
1900
+ *
1901
+ * @param {string|RegExp} url HTTP url.
1902
+ * @param {(string|RegExp)=} data HTTP request body.
1903
+ * @param {(Object|function(Object))=} headers HTTP headers.
1904
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1905
+ * control how a matched request is handled.
1906
+ */
1907
+
1908
+ /**
1909
+ * @ngdoc method
1910
+ * @name ngMockE2E.$httpBackend#whenPATCH
1911
+ * @methodOf ngMockE2E.$httpBackend
1912
+ * @description
1913
+ * Creates a new backend definition for PATCH requests. For more info see `when()`.
1914
+ *
1915
+ * @param {string|RegExp} url HTTP url.
1916
+ * @param {(string|RegExp)=} data HTTP request body.
1917
+ * @param {(Object|function(Object))=} headers HTTP headers.
1918
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1919
+ * control how a matched request is handled.
1920
+ */
1921
+
1922
+ /**
1923
+ * @ngdoc method
1924
+ * @name ngMockE2E.$httpBackend#whenJSONP
1925
+ * @methodOf ngMockE2E.$httpBackend
1926
+ * @description
1927
+ * Creates a new backend definition for JSONP requests. For more info see `when()`.
1928
+ *
1929
+ * @param {string|RegExp} url HTTP url.
1930
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1931
+ * control how a matched request is handled.
1932
+ */
1933
+ angular.mock.e2e = {};
1934
+ angular.mock.e2e.$httpBackendDecorator =
1935
+ ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
1936
+
1937
+
1938
+ angular.mock.clearDataCache = function() {
1939
+ var key,
1940
+ cache = angular.element.cache;
1941
+
1942
+ for(key in cache) {
1943
+ if (Object.prototype.hasOwnProperty.call(cache,key)) {
1944
+ var handle = cache[key].handle;
1945
+
1946
+ handle && angular.element(handle.elem).off();
1947
+ delete cache[key];
1948
+ }
1949
+ }
1950
+ };
1951
+
1952
+
1953
+ if(window.jasmine || window.mocha) {
1954
+
1955
+ var currentSpec = null,
1956
+ isSpecRunning = function() {
1957
+ return !!currentSpec;
1958
+ };
1959
+
1960
+
1961
+ beforeEach(function() {
1962
+ currentSpec = this;
1963
+ });
1964
+
1965
+ afterEach(function() {
1966
+ var injector = currentSpec.$injector;
1967
+
1968
+ currentSpec.$injector = null;
1969
+ currentSpec.$modules = null;
1970
+ currentSpec = null;
1971
+
1972
+ if (injector) {
1973
+ injector.get('$rootElement').off();
1974
+ injector.get('$browser').pollFns.length = 0;
1975
+ }
1976
+
1977
+ angular.mock.clearDataCache();
1978
+
1979
+ // clean up jquery's fragment cache
1980
+ angular.forEach(angular.element.fragments, function(val, key) {
1981
+ delete angular.element.fragments[key];
1982
+ });
1983
+
1984
+ MockXhr.$$lastInstance = null;
1985
+
1986
+ angular.forEach(angular.callbacks, function(val, key) {
1987
+ delete angular.callbacks[key];
1988
+ });
1989
+ angular.callbacks.counter = 0;
1990
+ });
1991
+
1992
+ /**
1993
+ * @ngdoc function
1994
+ * @name angular.mock.module
1995
+ * @description
1996
+ *
1997
+ * *NOTE*: This function is also published on window for easy access.<br>
1998
+ *
1999
+ * This function registers a module configuration code. It collects the configuration information
2000
+ * which will be used when the injector is created by {@link angular.mock.inject inject}.
2001
+ *
2002
+ * See {@link angular.mock.inject inject} for usage example
2003
+ *
2004
+ * @param {...(string|Function|Object)} fns any number of modules which are represented as string
2005
+ * aliases or as anonymous module initialization functions. The modules are used to
2006
+ * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
2007
+ * object literal is passed they will be register as values in the module, the key being
2008
+ * the module name and the value being what is returned.
2009
+ */
2010
+ window.module = angular.mock.module = function() {
2011
+ var moduleFns = Array.prototype.slice.call(arguments, 0);
2012
+ return isSpecRunning() ? workFn() : workFn;
2013
+ /////////////////////
2014
+ function workFn() {
2015
+ if (currentSpec.$injector) {
2016
+ throw new Error('Injector already created, can not register a module!');
2017
+ } else {
2018
+ var modules = currentSpec.$modules || (currentSpec.$modules = []);
2019
+ angular.forEach(moduleFns, function(module) {
2020
+ if (angular.isObject(module) && !angular.isArray(module)) {
2021
+ modules.push(function($provide) {
2022
+ angular.forEach(module, function(value, key) {
2023
+ $provide.value(key, value);
2024
+ });
2025
+ });
2026
+ } else {
2027
+ modules.push(module);
2028
+ }
2029
+ });
2030
+ }
2031
+ }
2032
+ };
2033
+
2034
+ /**
2035
+ * @ngdoc function
2036
+ * @name angular.mock.inject
2037
+ * @description
2038
+ *
2039
+ * *NOTE*: This function is also published on window for easy access.<br>
2040
+ *
2041
+ * The inject function wraps a function into an injectable function. The inject() creates new
2042
+ * instance of {@link AUTO.$injector $injector} per test, which is then used for
2043
+ * resolving references.
2044
+ *
2045
+ *
2046
+ * ## Resolving References (Underscore Wrapping)
2047
+ * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
2048
+ * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
2049
+ * that is declared in the scope of the `describe()` block. Since we would, most likely, want
2050
+ * the variable to have the same name of the reference we have a problem, since the parameter
2051
+ * to the `inject()` function would hide the outer variable.
2052
+ *
2053
+ * To help with this, the injected parameters can, optionally, be enclosed with underscores.
2054
+ * These are ignored by the injector when the reference name is resolved.
2055
+ *
2056
+ * For example, the parameter `_myService_` would be resolved as the reference `myService`.
2057
+ * Since it is available in the function body as _myService_, we can then assign it to a variable
2058
+ * defined in an outer scope.
2059
+ *
2060
+ * ```
2061
+ * // Defined out reference variable outside
2062
+ * var myService;
2063
+ *
2064
+ * // Wrap the parameter in underscores
2065
+ * beforeEach( inject( function(_myService_){
2066
+ * myService = _myService_;
2067
+ * }));
2068
+ *
2069
+ * // Use myService in a series of tests.
2070
+ * it('makes use of myService', function() {
2071
+ * myService.doStuff();
2072
+ * });
2073
+ *
2074
+ * ```
2075
+ *
2076
+ * See also {@link angular.mock.module angular.mock.module}
2077
+ *
2078
+ * ## Example
2079
+ * Example of what a typical jasmine tests looks like with the inject method.
2080
+ * <pre>
2081
+ *
2082
+ * angular.module('myApplicationModule', [])
2083
+ * .value('mode', 'app')
2084
+ * .value('version', 'v1.0.1');
2085
+ *
2086
+ *
2087
+ * describe('MyApp', function() {
2088
+ *
2089
+ * // You need to load modules that you want to test,
2090
+ * // it loads only the "ng" module by default.
2091
+ * beforeEach(module('myApplicationModule'));
2092
+ *
2093
+ *
2094
+ * // inject() is used to inject arguments of all given functions
2095
+ * it('should provide a version', inject(function(mode, version) {
2096
+ * expect(version).toEqual('v1.0.1');
2097
+ * expect(mode).toEqual('app');
2098
+ * }));
2099
+ *
2100
+ *
2101
+ * // The inject and module method can also be used inside of the it or beforeEach
2102
+ * it('should override a version and test the new version is injected', function() {
2103
+ * // module() takes functions or strings (module aliases)
2104
+ * module(function($provide) {
2105
+ * $provide.value('version', 'overridden'); // override version here
2106
+ * });
2107
+ *
2108
+ * inject(function(version) {
2109
+ * expect(version).toEqual('overridden');
2110
+ * });
2111
+ * });
2112
+ * });
2113
+ *
2114
+ * </pre>
2115
+ *
2116
+ * @param {...Function} fns any number of functions which will be injected using the injector.
2117
+ */
2118
+
2119
+
2120
+
2121
+ var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {
2122
+ this.message = e.message;
2123
+ this.name = e.name;
2124
+ if (e.line) this.line = e.line;
2125
+ if (e.sourceId) this.sourceId = e.sourceId;
2126
+ if (e.stack && errorForStack)
2127
+ this.stack = e.stack + '\n' + errorForStack.stack;
2128
+ if (e.stackArray) this.stackArray = e.stackArray;
2129
+ };
2130
+ ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;
2131
+
2132
+ window.inject = angular.mock.inject = function() {
2133
+ var blockFns = Array.prototype.slice.call(arguments, 0);
2134
+ var errorForStack = new Error('Declaration Location');
2135
+ return isSpecRunning() ? workFn() : workFn;
2136
+ /////////////////////
2137
+ function workFn() {
2138
+ var modules = currentSpec.$modules || [];
2139
+
2140
+ modules.unshift('ngMock');
2141
+ modules.unshift('ng');
2142
+ var injector = currentSpec.$injector;
2143
+ if (!injector) {
2144
+ injector = currentSpec.$injector = angular.injector(modules);
2145
+ }
2146
+ for(var i = 0, ii = blockFns.length; i < ii; i++) {
2147
+ try {
2148
+ /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
2149
+ injector.invoke(blockFns[i] || angular.noop, this);
2150
+ /* jshint +W040 */
2151
+ } catch (e) {
2152
+ if (e.stack && errorForStack) {
2153
+ throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
2154
+ }
2155
+ throw e;
2156
+ } finally {
2157
+ errorForStack = null;
2158
+ }
2159
+ }
2160
+ }
2161
+ };
2162
+ }
2163
+
2164
+
2165
+ })(window, window.angular);