rails-angularjs 1.3.12

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