memcached-manager 0.0.0

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