@angular-wave/angular.ts 0.0.1 → 0.0.4

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 (84) hide show
  1. package/Makefile +1 -1
  2. package/dist/angular-ts.cjs.js +506 -1696
  3. package/dist/angular-ts.esm.js +506 -1696
  4. package/dist/angular-ts.umd.js +506 -1696
  5. package/package.json +1 -1
  6. package/public/README.md +1 -0
  7. package/src/animations/{animateCss.js → animate-css.js} +0 -1
  8. package/src/animations/animation.js +428 -431
  9. package/src/animations/module.js +9 -9
  10. package/src/core/cache.js +2 -0
  11. package/src/core/compile.js +6 -1102
  12. package/src/core/compile.md +1192 -0
  13. package/src/core/location.js +1 -1
  14. package/src/core/utils.js +1 -1
  15. package/src/directive/a.js +1 -1
  16. package/src/directive/attrs.js +1 -1
  17. package/src/directive/csp.md +89 -0
  18. package/src/directive/input.js +3 -3
  19. package/src/directive/{ngModel.js → model.js} +1 -1
  20. package/src/directive/select.js +5 -5
  21. package/src/jqLite.js +1 -22
  22. package/src/public.js +24 -24
  23. package/src/services/log.js +66 -116
  24. package/src/services/log.md +39 -0
  25. package/test/jqlite.spec.js +5 -35
  26. package/test/messages/messages.spec.js +1 -1
  27. package/test/ng/compile.spec.js +17 -16
  28. package/test/ng/directive/model-options.spec.js +1 -1
  29. package/test/ng/directive/model.spec.js +1 -1
  30. package/test/ng/directive/options.spec.js +61 -61
  31. package/test/ng/directive/select.spec.js +22 -22
  32. package/test/ng/http-backend.spec.js +1 -1
  33. package/test/ng/on.spec.js +1 -1
  34. package/test/ng/prop.spec.js +54 -62
  35. package/test/ng/sanitize-uri.spec.js +1 -1
  36. package/test/ng/scope.spec.js +1 -1
  37. package/test/original-test.html +1 -1
  38. package/types/jqlite.d.ts +1 -32
  39. package/dist/build/angular-mocks.js +0 -3757
  40. package/dist/build/angular-parse-ext.js +0 -1275
  41. package/dist/build/angular-resource.js +0 -911
  42. package/dist/build/angular-touch.js +0 -368
  43. package/src/core/attributes.js +0 -199
  44. package/src/directive/ngCsp.js +0 -82
  45. /package/{dist/build → legacy}/angular-animate.js +0 -0
  46. /package/{dist/build → legacy}/angular-aria.js +0 -0
  47. /package/{dist/build → legacy}/angular-message-format.js +0 -0
  48. /package/{dist/build → legacy}/angular-messages.js +0 -0
  49. /package/{dist/build → legacy}/angular-route.js +0 -0
  50. /package/{dist/build → legacy}/angular-sanitize.js +0 -0
  51. /package/{dist/build → legacy}/angular.js +0 -0
  52. /package/src/animations/{animateCache.js → animate-cache.js} +0 -0
  53. /package/src/animations/{animateChildrenDirective.js → animate-children-directive.js} +0 -0
  54. /package/src/animations/{animateCssDriver.js → animate-css-driver.js} +0 -0
  55. /package/src/animations/{animateJsDriver.js → animate-js-driver.js} +0 -0
  56. /package/src/animations/{animateJs.js → animate-js.js} +0 -0
  57. /package/src/animations/{animateQueue.js → animate-queue.js} +0 -0
  58. /package/src/animations/{ngAnimateSwap.js → animate-swap.js} +0 -0
  59. /package/src/animations/{rafScheduler.js → raf-scheduler.js} +0 -0
  60. /package/src/core/{animateCss.js → animate-css.js} +0 -0
  61. /package/src/core/{animateRunner.js → animate-runner.js} +0 -0
  62. /package/src/core/{exceptionHandler.js → exception-handler.js} +0 -0
  63. /package/src/core/{intervalFactory.js → interval-factory.js} +0 -0
  64. /package/src/core/{rootScope.js → root-scope.js} +0 -0
  65. /package/src/core/{sanitizeUri.js → sanitize-uri.js} +0 -0
  66. /package/src/core/{taskTrackerFactory.js → task-tracker-factory.js} +0 -0
  67. /package/src/directive/{ngClass.js → class.js} +0 -0
  68. /package/src/directive/{ngController.js → controller.js} +0 -0
  69. /package/src/directive/{ngIf.js → if.js} +0 -0
  70. /package/src/directive/{ngInclude.js → include.js} +0 -0
  71. /package/src/directive/{ngModelOptions.js → model-options.js} +0 -0
  72. /package/src/directive/{ngOptions.js → options.js} +0 -0
  73. /package/src/directive/{ngRef.js → ref.js} +0 -0
  74. /package/src/directive/{ngRepeat.js → repeat.js} +0 -0
  75. /package/src/directive/{ngShowHide.js → show-hide.js} +0 -0
  76. /package/src/directive/{ngSwitch.js → switch.js} +0 -0
  77. /package/src/directive/{ngTransclude.js → transclude.js} +0 -0
  78. /package/src/{routeToRegExp.js → route-to-reg-exp.js} +0 -0
  79. /package/src/services/{anchorScroll.js → anchor-scroll.js} +0 -0
  80. /package/src/services/{cacheFactory.js → cache-factory.js} +0 -0
  81. /package/src/services/{cookieReader.js → cookie-reader.js} +0 -0
  82. /package/src/services/{httpBackend.js → http-backend.js} +0 -0
  83. /package/src/services/{templateRequest.js → template-request.js} +0 -0
  84. /package/test/ng/{anomate.spec.js → animate.spec.js} +0 -0
@@ -1,3757 +0,0 @@
1
- /**
2
- * @license AngularJS v1.8.4-local+sha.4e1bd4b90
3
- * (c) 2010-2020 Google LLC. http://angularjs.org
4
- * License: MIT
5
- */
6
- (function(window, angular) {
7
-
8
- 'use strict';
9
-
10
- /* global routeToRegExp: true */
11
-
12
- /**
13
- * @param {string} path - The path to parse. (It is assumed to have query and hash stripped off.)
14
- * @param {Object} opts - Options.
15
- * @return {Object} - An object containing an array of path parameter names (`keys`) and a regular
16
- * expression (`regexp`) that can be used to identify a matching URL and extract the path
17
- * parameter values.
18
- *
19
- * @description
20
- * Parses the given path, extracting path parameter names and a regular expression to match URLs.
21
- *
22
- * Originally inspired by `pathRexp` in `visionmedia/express/lib/utils.js`.
23
- */
24
- function routeToRegExp(path, opts) {
25
- var keys = [];
26
-
27
- var pattern = path
28
- .replace(/([().])/g, '\\$1')
29
- .replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) {
30
- var optional = option === '?' || option === '*?';
31
- var star = option === '*' || option === '*?';
32
- keys.push({name: key, optional: optional});
33
- slash = slash || '';
34
- return (
35
- (optional ? '(?:' + slash : slash + '(?:') +
36
- (star ? '(.+?)' : '([^/]+)') +
37
- (optional ? '?)?' : ')')
38
- );
39
- })
40
- .replace(/([/$*])/g, '\\$1');
41
-
42
- if (opts.ignoreTrailingSlashes) {
43
- pattern = pattern.replace(/\/+$/, '') + '/*';
44
- }
45
-
46
- return {
47
- keys: keys,
48
- regexp: new RegExp(
49
- '^' + pattern + '(?:[?#]|$)',
50
- opts.caseInsensitiveMatch ? 'i' : ''
51
- )
52
- };
53
- }
54
-
55
- 'use strict';
56
-
57
- /* global routeToRegExp: false */
58
-
59
- /**
60
- * @ngdoc object
61
- * @name angular.mock
62
- * @description
63
- *
64
- * Namespace from 'angular-mocks.js' which contains testing related code.
65
- *
66
- */
67
- angular.mock = {};
68
-
69
- /**
70
- * ! This is a private undocumented service !
71
- *
72
- * @name $browser
73
- *
74
- * @description
75
- * This service is a mock implementation of {@link ng.$browser}. It provides fake
76
- * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
77
- * cookies, etc.
78
- *
79
- * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
80
- * that there are several helper methods available which can be used in tests.
81
- */
82
- angular.mock.$BrowserProvider = function() {
83
- this.$get = [
84
- '$log', '$$taskTrackerFactory',
85
- function($log, $$taskTrackerFactory) {
86
- return new angular.mock.$Browser($log, $$taskTrackerFactory);
87
- }
88
- ];
89
- };
90
-
91
- angular.mock.$Browser = function($log, $$taskTrackerFactory) {
92
- var self = this;
93
- var taskTracker = $$taskTrackerFactory($log);
94
-
95
- this.isMock = true;
96
- self.$$url = 'http://server/';
97
- self.$$lastUrl = self.$$url; // used by url polling fn
98
- self.pollFns = [];
99
-
100
- // Task-tracking API
101
- self.$$completeOutstandingRequest = taskTracker.completeTask;
102
- self.$$incOutstandingRequestCount = taskTracker.incTaskCount;
103
- self.notifyWhenNoOutstandingRequests = taskTracker.notifyWhenNoPendingTasks;
104
-
105
- // register url polling fn
106
-
107
- self.onUrlChange = function(listener) {
108
- self.pollFns.push(
109
- function() {
110
- if (self.$$lastUrl !== self.$$url || self.$$state !== self.$$lastState) {
111
- self.$$lastUrl = self.$$url;
112
- self.$$lastState = self.$$state;
113
- listener(self.$$url, self.$$state);
114
- }
115
- }
116
- );
117
-
118
- return listener;
119
- };
120
-
121
- self.$$applicationDestroyed = angular.noop;
122
- self.$$checkUrlChange = angular.noop;
123
-
124
- self.deferredFns = [];
125
- self.deferredNextId = 0;
126
-
127
- self.defer = function(fn, delay, taskType) {
128
- var timeoutId = self.deferredNextId++;
129
-
130
- delay = delay || 0;
131
- taskType = taskType || taskTracker.DEFAULT_TASK_TYPE;
132
-
133
- taskTracker.incTaskCount(taskType);
134
- self.deferredFns.push({
135
- id: timeoutId,
136
- type: taskType,
137
- time: (self.defer.now + delay),
138
- fn: fn
139
- });
140
- self.deferredFns.sort(function(a, b) { return a.time - b.time; });
141
-
142
- return timeoutId;
143
- };
144
-
145
-
146
- /**
147
- * @name $browser#defer.now
148
- *
149
- * @description
150
- * Current milliseconds mock time.
151
- */
152
- self.defer.now = 0;
153
-
154
-
155
- self.defer.cancel = function(deferId) {
156
- var taskIndex;
157
-
158
- angular.forEach(self.deferredFns, function(task, index) {
159
- if (task.id === deferId) taskIndex = index;
160
- });
161
-
162
- if (angular.isDefined(taskIndex)) {
163
- var task = self.deferredFns.splice(taskIndex, 1)[0];
164
- taskTracker.completeTask(angular.noop, task.type);
165
- return true;
166
- }
167
-
168
- return false;
169
- };
170
-
171
-
172
- /**
173
- * @name $browser#defer.flush
174
- *
175
- * @description
176
- * Flushes all pending requests and executes the defer callbacks.
177
- *
178
- * See {@link ngMock.$flushPendingsTasks} for more info.
179
- *
180
- * @param {number=} number of milliseconds to flush. See {@link #defer.now}
181
- */
182
- self.defer.flush = function(delay) {
183
- var nextTime;
184
-
185
- if (angular.isDefined(delay)) {
186
- // A delay was passed so compute the next time
187
- nextTime = self.defer.now + delay;
188
- } else if (self.deferredFns.length) {
189
- // No delay was passed so set the next time so that it clears the deferred queue
190
- nextTime = self.deferredFns[self.deferredFns.length - 1].time;
191
- } else {
192
- // No delay passed, but there are no deferred tasks so flush - indicates an error!
193
- throw new Error('No deferred tasks to be flushed');
194
- }
195
-
196
- while (self.deferredFns.length && self.deferredFns[0].time <= nextTime) {
197
- // Increment the time and call the next deferred function
198
- self.defer.now = self.deferredFns[0].time;
199
- var task = self.deferredFns.shift();
200
- taskTracker.completeTask(task.fn, task.type);
201
- }
202
-
203
- // Ensure that the current time is correct
204
- self.defer.now = nextTime;
205
- };
206
-
207
- /**
208
- * @name $browser#defer.getPendingTasks
209
- *
210
- * @description
211
- * Returns the currently pending tasks that need to be flushed.
212
- * You can request a specific type of tasks only, by specifying a `taskType`.
213
- *
214
- * @param {string=} taskType - The type tasks to return.
215
- */
216
- self.defer.getPendingTasks = function(taskType) {
217
- return !taskType
218
- ? self.deferredFns
219
- : self.deferredFns.filter(function(task) { return task.type === taskType; });
220
- };
221
-
222
- /**
223
- * @name $browser#defer.formatPendingTasks
224
- *
225
- * @description
226
- * Formats each task in a list of pending tasks as a string, suitable for use in error messages.
227
- *
228
- * @param {Array<Object>} pendingTasks - A list of task objects.
229
- * @return {Array<string>} A list of stringified tasks.
230
- */
231
- self.defer.formatPendingTasks = function(pendingTasks) {
232
- return pendingTasks.map(function(task) {
233
- return '{id: ' + task.id + ', type: ' + task.type + ', time: ' + task.time + '}';
234
- });
235
- };
236
-
237
- /**
238
- * @name $browser#defer.verifyNoPendingTasks
239
- *
240
- * @description
241
- * Verifies that there are no pending tasks that need to be flushed.
242
- * You can check for a specific type of tasks only, by specifying a `taskType`.
243
- *
244
- * See {@link $verifyNoPendingTasks} for more info.
245
- *
246
- * @param {string=} taskType - The type tasks to check for.
247
- */
248
- self.defer.verifyNoPendingTasks = function(taskType) {
249
- var pendingTasks = self.defer.getPendingTasks(taskType);
250
-
251
- if (pendingTasks.length) {
252
- var formattedTasks = self.defer.formatPendingTasks(pendingTasks).join('\n ');
253
- throw new Error('Deferred tasks to flush (' + pendingTasks.length + '):\n ' +
254
- formattedTasks);
255
- }
256
- };
257
-
258
- self.$$baseHref = '/';
259
- self.baseHref = function() {
260
- return this.$$baseHref;
261
- };
262
- };
263
- angular.mock.$Browser.prototype = {
264
-
265
- /**
266
- * @name $browser#poll
267
- *
268
- * @description
269
- * run all fns in pollFns
270
- */
271
- poll: function poll() {
272
- angular.forEach(this.pollFns, function(pollFn) {
273
- pollFn();
274
- });
275
- },
276
-
277
- url: function(url, replace, state) {
278
- if (angular.isUndefined(state)) {
279
- state = null;
280
- }
281
- if (url) {
282
- // The `$browser` service trims empty hashes; simulate it.
283
- this.$$url = url.replace(/#$/, '');
284
- // Native pushState serializes & copies the object; simulate it.
285
- this.$$state = angular.copy(state);
286
- return this;
287
- }
288
-
289
- return this.$$url;
290
- },
291
-
292
- state: function() {
293
- return this.$$state;
294
- }
295
- };
296
-
297
- /**
298
- * @ngdoc service
299
- * @name $flushPendingTasks
300
- *
301
- * @description
302
- * Flushes all currently pending tasks and executes the corresponding callbacks.
303
- *
304
- * Optionally, you can also pass a `delay` argument to only flush tasks that are scheduled to be
305
- * executed within `delay` milliseconds. Currently, `delay` only applies to timeouts, since all
306
- * other tasks have a delay of 0 (i.e. they are scheduled to be executed as soon as possible, but
307
- * still asynchronously).
308
- *
309
- * If no delay is specified, it uses a delay such that all currently pending tasks are flushed.
310
- *
311
- * The types of tasks that are flushed include:
312
- *
313
- * - Pending timeouts (via {@link $timeout}).
314
- * - Pending tasks scheduled via {@link ng.$rootScope.Scope#$applyAsync $applyAsync}.
315
- * - Pending tasks scheduled via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}.
316
- * These include tasks scheduled via `$evalAsync()` indirectly (such as {@link $q} promises).
317
- *
318
- * <div class="alert alert-info">
319
- * Periodic tasks scheduled via {@link $interval} use a different queue and are not flushed by
320
- * `$flushPendingTasks()`. Use {@link ngMock.$interval#flush $interval.flush(millis)} instead.
321
- * </div>
322
- *
323
- * @param {number=} delay - The number of milliseconds to flush.
324
- */
325
- angular.mock.$FlushPendingTasksProvider = function() {
326
- this.$get = [
327
- '$browser',
328
- function($browser) {
329
- return function $flushPendingTasks(delay) {
330
- return $browser.defer.flush(delay);
331
- };
332
- }
333
- ];
334
- };
335
-
336
- /**
337
- * @ngdoc service
338
- * @name $verifyNoPendingTasks
339
- *
340
- * @description
341
- * Verifies that there are no pending tasks that need to be flushed. It throws an error if there are
342
- * still pending tasks.
343
- *
344
- * You can check for a specific type of tasks only, by specifying a `taskType`.
345
- *
346
- * Available task types:
347
- *
348
- * - `$timeout`: Pending timeouts (via {@link $timeout}).
349
- * - `$http`: Pending HTTP requests (via {@link $http}).
350
- * - `$route`: In-progress route transitions (via {@link $route}).
351
- * - `$applyAsync`: Pending tasks scheduled via {@link ng.$rootScope.Scope#$applyAsync $applyAsync}.
352
- * - `$evalAsync`: Pending tasks scheduled via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}.
353
- * These include tasks scheduled via `$evalAsync()` indirectly (such as {@link $q} promises).
354
- *
355
- * <div class="alert alert-info">
356
- * Periodic tasks scheduled via {@link $interval} use a different queue and are not taken into
357
- * account by `$verifyNoPendingTasks()`. There is currently no way to verify that there are no
358
- * pending {@link $interval} tasks.
359
- * </div>
360
- *
361
- * @param {string=} taskType - The type of tasks to check for.
362
- */
363
- angular.mock.$VerifyNoPendingTasksProvider = function() {
364
- this.$get = [
365
- '$browser',
366
- function($browser) {
367
- return function $verifyNoPendingTasks(taskType) {
368
- return $browser.defer.verifyNoPendingTasks(taskType);
369
- };
370
- }
371
- ];
372
- };
373
-
374
- /**
375
- * @ngdoc provider
376
- * @name $exceptionHandlerProvider
377
- *
378
- * @description
379
- * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
380
- * passed to the `$exceptionHandler`.
381
- */
382
-
383
- /**
384
- * @ngdoc service
385
- * @name $exceptionHandler
386
- *
387
- * @description
388
- * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
389
- * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
390
- * information.
391
- *
392
- *
393
- * ```js
394
- * describe('$exceptionHandlerProvider', function() {
395
- *
396
- * it('should capture log messages and exceptions', function() {
397
- *
398
- * module(function($exceptionHandlerProvider) {
399
- * $exceptionHandlerProvider.mode('log');
400
- * });
401
- *
402
- * inject(function($log, $exceptionHandler, $timeout) {
403
- * $timeout(function() { $log.log(1); });
404
- * $timeout(function() { $log.log(2); throw 'banana peel'; });
405
- * $timeout(function() { $log.log(3); });
406
- * expect($exceptionHandler.errors).toEqual([]);
407
- * expect($log.assertEmpty());
408
- * $timeout.flush();
409
- * expect($exceptionHandler.errors).toEqual(['banana peel']);
410
- * expect($log.log.logs).toEqual([[1], [2], [3]]);
411
- * });
412
- * });
413
- * });
414
- * ```
415
- */
416
-
417
- angular.mock.$ExceptionHandlerProvider = function() {
418
- var handler;
419
-
420
- /**
421
- * @ngdoc method
422
- * @name $exceptionHandlerProvider#mode
423
- *
424
- * @description
425
- * Sets the logging mode.
426
- *
427
- * @param {string} mode Mode of operation, defaults to `rethrow`.
428
- *
429
- * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
430
- * mode stores an array of errors in `$exceptionHandler.errors`, to allow later assertion of
431
- * them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
432
- * {@link ngMock.$log#reset reset()}.
433
- * - `rethrow`: If any errors are passed to the handler in tests, it typically means that there
434
- * is a bug in the application or test, so this mock will make these tests fail. For any
435
- * implementations that expect exceptions to be thrown, the `rethrow` mode will also maintain
436
- * a log of thrown errors in `$exceptionHandler.errors`.
437
- */
438
- this.mode = function(mode) {
439
-
440
- switch (mode) {
441
- case 'log':
442
- case 'rethrow':
443
- var errors = [];
444
- handler = function(e) {
445
- if (arguments.length === 1) {
446
- errors.push(e);
447
- } else {
448
- errors.push([].slice.call(arguments, 0));
449
- }
450
- if (mode === 'rethrow') {
451
- throw e;
452
- }
453
- };
454
- handler.errors = errors;
455
- break;
456
- default:
457
- throw new Error('Unknown mode \'' + mode + '\', only \'log\'/\'rethrow\' modes are allowed!');
458
- }
459
- };
460
-
461
- this.$get = function() {
462
- return handler;
463
- };
464
-
465
- this.mode('rethrow');
466
- };
467
-
468
-
469
- /**
470
- * @ngdoc service
471
- * @name $log
472
- *
473
- * @description
474
- * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
475
- * (one array per logging level). These arrays are exposed as `logs` property of each of the
476
- * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
477
- *
478
- */
479
- angular.mock.$LogProvider = function() {
480
- var debug = true;
481
-
482
- function concat(array1, array2, index) {
483
- return array1.concat(Array.prototype.slice.call(array2, index));
484
- }
485
-
486
- this.debugEnabled = function(flag) {
487
- if (angular.isDefined(flag)) {
488
- debug = flag;
489
- return this;
490
- } else {
491
- return debug;
492
- }
493
- };
494
-
495
- this.$get = function() {
496
- var $log = {
497
- log: function() { $log.log.logs.push(concat([], arguments, 0)); },
498
- warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
499
- info: function() { $log.info.logs.push(concat([], arguments, 0)); },
500
- error: function() { $log.error.logs.push(concat([], arguments, 0)); },
501
- debug: function() {
502
- if (debug) {
503
- $log.debug.logs.push(concat([], arguments, 0));
504
- }
505
- }
506
- };
507
-
508
- /**
509
- * @ngdoc method
510
- * @name $log#reset
511
- *
512
- * @description
513
- * Reset all of the logging arrays to empty.
514
- */
515
- $log.reset = function() {
516
- /**
517
- * @ngdoc property
518
- * @name $log#log.logs
519
- *
520
- * @description
521
- * Array of messages logged using {@link ng.$log#log `log()`}.
522
- *
523
- * @example
524
- * ```js
525
- * $log.log('Some Log');
526
- * var first = $log.log.logs.unshift();
527
- * ```
528
- */
529
- $log.log.logs = [];
530
- /**
531
- * @ngdoc property
532
- * @name $log#info.logs
533
- *
534
- * @description
535
- * Array of messages logged using {@link ng.$log#info `info()`}.
536
- *
537
- * @example
538
- * ```js
539
- * $log.info('Some Info');
540
- * var first = $log.info.logs.unshift();
541
- * ```
542
- */
543
- $log.info.logs = [];
544
- /**
545
- * @ngdoc property
546
- * @name $log#warn.logs
547
- *
548
- * @description
549
- * Array of messages logged using {@link ng.$log#warn `warn()`}.
550
- *
551
- * @example
552
- * ```js
553
- * $log.warn('Some Warning');
554
- * var first = $log.warn.logs.unshift();
555
- * ```
556
- */
557
- $log.warn.logs = [];
558
- /**
559
- * @ngdoc property
560
- * @name $log#error.logs
561
- *
562
- * @description
563
- * Array of messages logged using {@link ng.$log#error `error()`}.
564
- *
565
- * @example
566
- * ```js
567
- * $log.error('Some Error');
568
- * var first = $log.error.logs.unshift();
569
- * ```
570
- */
571
- $log.error.logs = [];
572
- /**
573
- * @ngdoc property
574
- * @name $log#debug.logs
575
- *
576
- * @description
577
- * Array of messages logged using {@link ng.$log#debug `debug()`}.
578
- *
579
- * @example
580
- * ```js
581
- * $log.debug('Some Error');
582
- * var first = $log.debug.logs.unshift();
583
- * ```
584
- */
585
- $log.debug.logs = [];
586
- };
587
-
588
- /**
589
- * @ngdoc method
590
- * @name $log#assertEmpty
591
- *
592
- * @description
593
- * Assert that all of the logging methods have no logged messages. If any messages are present,
594
- * an exception is thrown.
595
- */
596
- $log.assertEmpty = function() {
597
- var errors = [];
598
- angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
599
- angular.forEach($log[logLevel].logs, function(log) {
600
- angular.forEach(log, function(logItem) {
601
- errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
602
- (logItem.stack || ''));
603
- });
604
- });
605
- });
606
- if (errors.length) {
607
- errors.unshift('Expected $log to be empty! Either a message was logged unexpectedly, or ' +
608
- 'an expected log message was not checked and removed:');
609
- errors.push('');
610
- throw new Error(errors.join('\n---------\n'));
611
- }
612
- };
613
-
614
- $log.reset();
615
- return $log;
616
- };
617
- };
618
-
619
-
620
- /**
621
- * @ngdoc service
622
- * @name $interval
623
- *
624
- * @description
625
- * Mock implementation of the $interval service.
626
- *
627
- * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
628
- * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
629
- * time.
630
- *
631
- * @param {function()} fn A function that should be called repeatedly.
632
- * @param {number} delay Number of milliseconds between each function call.
633
- * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
634
- * indefinitely.
635
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
636
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
637
- * @param {...*=} Pass additional parameters to the executed function.
638
- * @returns {promise} A promise which will be notified on each iteration.
639
- */
640
- angular.mock.$IntervalProvider = function() {
641
- this.$get = ['$browser', '$$intervalFactory',
642
- function($browser, $$intervalFactory) {
643
- var repeatFns = [],
644
- nextRepeatId = 0,
645
- now = 0,
646
- setIntervalFn = function(tick, delay, deferred, skipApply) {
647
- var id = nextRepeatId++;
648
- var fn = !skipApply ? tick : function() {
649
- tick();
650
- $browser.defer.flush();
651
- };
652
-
653
- repeatFns.push({
654
- nextTime: (now + (delay || 0)),
655
- delay: delay || 1,
656
- fn: fn,
657
- id: id,
658
- deferred: deferred
659
- });
660
- repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime; });
661
-
662
- return id;
663
- },
664
- clearIntervalFn = function(id) {
665
- for (var fnIndex = repeatFns.length - 1; fnIndex >= 0; fnIndex--) {
666
- if (repeatFns[fnIndex].id === id) {
667
- repeatFns.splice(fnIndex, 1);
668
- break;
669
- }
670
- }
671
- };
672
-
673
- var $interval = $$intervalFactory(setIntervalFn, clearIntervalFn);
674
-
675
- /**
676
- * @ngdoc method
677
- * @name $interval#cancel
678
- *
679
- * @description
680
- * Cancels a task associated with the `promise`.
681
- *
682
- * @param {promise} promise A promise from calling the `$interval` function.
683
- * @returns {boolean} Returns `true` if the task was successfully cancelled.
684
- */
685
- $interval.cancel = function(promise) {
686
- if (!promise) return false;
687
-
688
- for (var fnIndex = repeatFns.length - 1; fnIndex >= 0; fnIndex--) {
689
- if (repeatFns[fnIndex].id === promise.$$intervalId) {
690
- var deferred = repeatFns[fnIndex].deferred;
691
- deferred.promise.then(undefined, function() {});
692
- deferred.reject('canceled');
693
- repeatFns.splice(fnIndex, 1);
694
- return true;
695
- }
696
- }
697
-
698
- return false;
699
- };
700
-
701
- /**
702
- * @ngdoc method
703
- * @name $interval#flush
704
- * @description
705
- *
706
- * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
707
- *
708
- * @param {number} millis maximum timeout amount to flush up until.
709
- *
710
- * @return {number} The amount of time moved forward.
711
- */
712
- $interval.flush = function(millis) {
713
- var before = now;
714
- now += millis;
715
- while (repeatFns.length && repeatFns[0].nextTime <= now) {
716
- var task = repeatFns[0];
717
- task.fn();
718
- if (task.nextTime === before) {
719
- // this can only happen the first time
720
- // a zero-delay interval gets triggered
721
- task.nextTime++;
722
- }
723
- task.nextTime += task.delay;
724
- repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
725
- }
726
- return millis;
727
- };
728
-
729
- return $interval;
730
- }];
731
- };
732
-
733
-
734
- function jsonStringToDate(string) {
735
- // The R_ISO8061_STR regex is never going to fit into the 100 char limit!
736
- // eslit-disable-next-line max-len
737
- var R_ISO8061_STR = /^(-?\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
738
-
739
- var match;
740
- if ((match = string.match(R_ISO8061_STR))) {
741
- var date = new Date(0),
742
- tzHour = 0,
743
- tzMin = 0;
744
- if (match[9]) {
745
- tzHour = toInt(match[9] + match[10]);
746
- tzMin = toInt(match[9] + match[11]);
747
- }
748
- date.setUTCFullYear(toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
749
- date.setUTCHours(toInt(match[4] || 0) - tzHour,
750
- toInt(match[5] || 0) - tzMin,
751
- toInt(match[6] || 0),
752
- toInt(match[7] || 0));
753
- return date;
754
- }
755
- return string;
756
- }
757
-
758
- function toInt(str) {
759
- return parseInt(str, 10);
760
- }
761
-
762
- function padNumberInMock(num, digits, trim) {
763
- var neg = '';
764
- if (num < 0) {
765
- neg = '-';
766
- num = -num;
767
- }
768
- num = '' + num;
769
- while (num.length < digits) num = '0' + num;
770
- if (trim) {
771
- num = num.substr(num.length - digits);
772
- }
773
- return neg + num;
774
- }
775
-
776
-
777
- /**
778
- * @ngdoc type
779
- * @name angular.mock.TzDate
780
- * @description
781
- *
782
- * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
783
- *
784
- * Mock of the Date type which has its timezone specified via constructor arg.
785
- *
786
- * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
787
- * offset, so that we can test code that depends on local timezone settings without dependency on
788
- * the time zone settings of the machine where the code is running.
789
- *
790
- * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
791
- * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
792
- *
793
- * @example
794
- * !!!! WARNING !!!!!
795
- * This is not a complete Date object so only methods that were implemented can be called safely.
796
- * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
797
- *
798
- * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
799
- * incomplete we might be missing some non-standard methods. This can result in errors like:
800
- * "Date.prototype.foo called on incompatible Object".
801
- *
802
- * ```js
803
- * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
804
- * newYearInBratislava.getTimezoneOffset() => -60;
805
- * newYearInBratislava.getFullYear() => 2010;
806
- * newYearInBratislava.getMonth() => 0;
807
- * newYearInBratislava.getDate() => 1;
808
- * newYearInBratislava.getHours() => 0;
809
- * newYearInBratislava.getMinutes() => 0;
810
- * newYearInBratislava.getSeconds() => 0;
811
- * ```
812
- *
813
- */
814
- angular.mock.TzDate = function(offset, timestamp) {
815
- var self = new Date(0);
816
- if (angular.isString(timestamp)) {
817
- var tsStr = timestamp;
818
-
819
- self.origDate = jsonStringToDate(timestamp);
820
-
821
- timestamp = self.origDate.getTime();
822
- if (isNaN(timestamp)) {
823
- // eslint-disable-next-line no-throw-literal
824
- throw {
825
- name: 'Illegal Argument',
826
- message: 'Arg \'' + tsStr + '\' passed into TzDate constructor is not a valid date string'
827
- };
828
- }
829
- } else {
830
- self.origDate = new Date(timestamp);
831
- }
832
-
833
- var localOffset = new Date(timestamp).getTimezoneOffset();
834
- self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
835
- self.date = new Date(timestamp + self.offsetDiff);
836
-
837
- self.getTime = function() {
838
- return self.date.getTime() - self.offsetDiff;
839
- };
840
-
841
- self.toLocaleDateString = function() {
842
- return self.date.toLocaleDateString();
843
- };
844
-
845
- self.getFullYear = function() {
846
- return self.date.getFullYear();
847
- };
848
-
849
- self.getMonth = function() {
850
- return self.date.getMonth();
851
- };
852
-
853
- self.getDate = function() {
854
- return self.date.getDate();
855
- };
856
-
857
- self.getHours = function() {
858
- return self.date.getHours();
859
- };
860
-
861
- self.getMinutes = function() {
862
- return self.date.getMinutes();
863
- };
864
-
865
- self.getSeconds = function() {
866
- return self.date.getSeconds();
867
- };
868
-
869
- self.getMilliseconds = function() {
870
- return self.date.getMilliseconds();
871
- };
872
-
873
- self.getTimezoneOffset = function() {
874
- return offset * 60;
875
- };
876
-
877
- self.getUTCFullYear = function() {
878
- return self.origDate.getUTCFullYear();
879
- };
880
-
881
- self.getUTCMonth = function() {
882
- return self.origDate.getUTCMonth();
883
- };
884
-
885
- self.getUTCDate = function() {
886
- return self.origDate.getUTCDate();
887
- };
888
-
889
- self.getUTCHours = function() {
890
- return self.origDate.getUTCHours();
891
- };
892
-
893
- self.getUTCMinutes = function() {
894
- return self.origDate.getUTCMinutes();
895
- };
896
-
897
- self.getUTCSeconds = function() {
898
- return self.origDate.getUTCSeconds();
899
- };
900
-
901
- self.getUTCMilliseconds = function() {
902
- return self.origDate.getUTCMilliseconds();
903
- };
904
-
905
- self.getDay = function() {
906
- return self.date.getDay();
907
- };
908
-
909
- // provide this method only on browsers that already have it
910
- if (self.toISOString) {
911
- self.toISOString = function() {
912
- return padNumberInMock(self.origDate.getUTCFullYear(), 4) + '-' +
913
- padNumberInMock(self.origDate.getUTCMonth() + 1, 2) + '-' +
914
- padNumberInMock(self.origDate.getUTCDate(), 2) + 'T' +
915
- padNumberInMock(self.origDate.getUTCHours(), 2) + ':' +
916
- padNumberInMock(self.origDate.getUTCMinutes(), 2) + ':' +
917
- padNumberInMock(self.origDate.getUTCSeconds(), 2) + '.' +
918
- padNumberInMock(self.origDate.getUTCMilliseconds(), 3) + 'Z';
919
- };
920
- }
921
-
922
- //hide all methods not implemented in this mock that the Date prototype exposes
923
- var unimplementedMethods = ['getUTCDay',
924
- 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
925
- 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
926
- 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
927
- 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
928
- 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
929
-
930
- angular.forEach(unimplementedMethods, function(methodName) {
931
- self[methodName] = function() {
932
- throw new Error('Method \'' + methodName + '\' is not implemented in the TzDate mock');
933
- };
934
- });
935
-
936
- return self;
937
- };
938
-
939
- //make "tzDateInstance instanceof Date" return true
940
- angular.mock.TzDate.prototype = Date.prototype;
941
-
942
-
943
- /**
944
- * @ngdoc service
945
- * @name $animate
946
- *
947
- * @description
948
- * Mock implementation of the {@link ng.$animate `$animate`} service. Exposes two additional methods
949
- * for testing animations.
950
- *
951
- * You need to require the `ngAnimateMock` module in your test suite for instance `beforeEach(module('ngAnimateMock'))`
952
- */
953
- angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
954
- .info({ angularVersion: '1.8.4-local+sha.4e1bd4b90' })
955
-
956
- .config(['$provide', function($provide) {
957
-
958
- $provide.factory('$$forceReflow', function() {
959
- function reflowFn() {
960
- reflowFn.totalReflows++;
961
- }
962
- reflowFn.totalReflows = 0;
963
- return reflowFn;
964
- });
965
-
966
- $provide.factory('$$animateAsyncRun', function() {
967
- var queue = [];
968
- var queueFn = function() {
969
- return function(fn) {
970
- queue.push(fn);
971
- };
972
- };
973
- queueFn.flush = function() {
974
- if (queue.length === 0) return false;
975
-
976
- for (var i = 0; i < queue.length; i++) {
977
- queue[i]();
978
- }
979
- queue = [];
980
-
981
- return true;
982
- };
983
- return queueFn;
984
- });
985
-
986
- $provide.decorator('$$animateJs', ['$delegate', function($delegate) {
987
- var runners = [];
988
-
989
- var animateJsConstructor = function() {
990
- var animator = $delegate.apply($delegate, arguments);
991
- // If no javascript animation is found, animator is undefined
992
- if (animator) {
993
- runners.push(animator);
994
- }
995
- return animator;
996
- };
997
-
998
- animateJsConstructor.$closeAndFlush = function() {
999
- runners.forEach(function(runner) {
1000
- runner.end();
1001
- });
1002
- runners = [];
1003
- };
1004
-
1005
- return animateJsConstructor;
1006
- }]);
1007
-
1008
- $provide.decorator('$animateCss', ['$delegate', function($delegate) {
1009
- var runners = [];
1010
-
1011
- var animateCssConstructor = function(element, options) {
1012
- var animator = $delegate(element, options);
1013
- runners.push(animator);
1014
- return animator;
1015
- };
1016
-
1017
- animateCssConstructor.$closeAndFlush = function() {
1018
- runners.forEach(function(runner) {
1019
- runner.end();
1020
- });
1021
- runners = [];
1022
- };
1023
-
1024
- return animateCssConstructor;
1025
- }]);
1026
-
1027
- $provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF', '$animateCss', '$$animateJs',
1028
- '$$forceReflow', '$$animateAsyncRun', '$rootScope',
1029
- function($delegate, $timeout, $browser, $$rAF, $animateCss, $$animateJs,
1030
- $$forceReflow, $$animateAsyncRun, $rootScope) {
1031
- var animate = {
1032
- queue: [],
1033
- cancel: $delegate.cancel,
1034
- on: $delegate.on,
1035
- off: $delegate.off,
1036
- pin: $delegate.pin,
1037
- get reflows() {
1038
- return $$forceReflow.totalReflows;
1039
- },
1040
- enabled: $delegate.enabled,
1041
- /**
1042
- * @ngdoc method
1043
- * @name $animate#closeAndFlush
1044
- * @description
1045
- *
1046
- * This method will close all pending animations (both {@link ngAnimate#javascript-based-animations Javascript}
1047
- * and {@link ngAnimate.$animateCss CSS}) and it will also flush any remaining animation frames and/or callbacks.
1048
- */
1049
- closeAndFlush: function() {
1050
- // we allow the flush command to swallow the errors
1051
- // because depending on whether CSS or JS animations are
1052
- // used, there may not be a RAF flush. The primary flush
1053
- // at the end of this function must throw an exception
1054
- // because it will track if there were pending animations
1055
- this.flush(true);
1056
- $animateCss.$closeAndFlush();
1057
- $$animateJs.$closeAndFlush();
1058
- this.flush();
1059
- },
1060
- /**
1061
- * @ngdoc method
1062
- * @name $animate#flush
1063
- * @description
1064
- *
1065
- * This method is used to flush the pending callbacks and animation frames to either start
1066
- * an animation or conclude an animation. Note that this will not actually close an
1067
- * actively running animation (see {@link ngMock.$animate#closeAndFlush `closeAndFlush()`} for that).
1068
- */
1069
- flush: function(hideErrors) {
1070
- $rootScope.$digest();
1071
-
1072
- var doNextRun, somethingFlushed = false;
1073
- do {
1074
- doNextRun = false;
1075
-
1076
- if ($$rAF.queue.length) {
1077
- $$rAF.flush();
1078
- doNextRun = somethingFlushed = true;
1079
- }
1080
-
1081
- if ($$animateAsyncRun.flush()) {
1082
- doNextRun = somethingFlushed = true;
1083
- }
1084
- } while (doNextRun);
1085
-
1086
- if (!somethingFlushed && !hideErrors) {
1087
- throw new Error('No pending animations ready to be closed or flushed');
1088
- }
1089
-
1090
- $rootScope.$digest();
1091
- }
1092
- };
1093
-
1094
- angular.forEach(
1095
- ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {
1096
- animate[method] = function() {
1097
- animate.queue.push({
1098
- event: method,
1099
- element: arguments[0],
1100
- options: arguments[arguments.length - 1],
1101
- args: arguments
1102
- });
1103
- return $delegate[method].apply($delegate, arguments);
1104
- };
1105
- });
1106
-
1107
- return animate;
1108
- }]);
1109
-
1110
- }]);
1111
-
1112
-
1113
- /**
1114
- * @ngdoc function
1115
- * @name angular.mock.dump
1116
- * @description
1117
- *
1118
- * *NOTE*: This is not an injectable instance, just a globally available function.
1119
- *
1120
- * Method for serializing common AngularJS objects (scope, elements, etc..) into strings.
1121
- * It is useful for logging objects to the console when debugging.
1122
- *
1123
- * @param {*} object - any object to turn into string.
1124
- * @return {string} a serialized string of the argument
1125
- */
1126
- angular.mock.dump = function(object) {
1127
- return serialize(object);
1128
-
1129
- function serialize(object) {
1130
- var out;
1131
-
1132
- if (angular.isElement(object)) {
1133
- object = angular.element(object);
1134
- out = angular.element('<div></div>');
1135
- angular.forEach(object, function(element) {
1136
- out.append(angular.element(element).clone());
1137
- });
1138
- out = out.html();
1139
- } else if (angular.isArray(object)) {
1140
- out = [];
1141
- angular.forEach(object, function(o) {
1142
- out.push(serialize(o));
1143
- });
1144
- out = '[ ' + out.join(', ') + ' ]';
1145
- } else if (angular.isObject(object)) {
1146
- if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
1147
- out = serializeScope(object);
1148
- } else if (object instanceof Error) {
1149
- out = object.stack || ('' + object.name + ': ' + object.message);
1150
- } else {
1151
- // TODO(i): this prevents methods being logged,
1152
- // we should have a better way to serialize objects
1153
- out = angular.toJson(object, true);
1154
- }
1155
- } else {
1156
- out = String(object);
1157
- }
1158
-
1159
- return out;
1160
- }
1161
-
1162
- function serializeScope(scope, offset) {
1163
- offset = offset || ' ';
1164
- var log = [offset + 'Scope(' + scope.$id + '): {'];
1165
- for (var key in scope) {
1166
- if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
1167
- log.push(' ' + key + ': ' + angular.toJson(scope[key]));
1168
- }
1169
- }
1170
- var child = scope.$$childHead;
1171
- while (child) {
1172
- log.push(serializeScope(child, offset + ' '));
1173
- child = child.$$nextSibling;
1174
- }
1175
- log.push('}');
1176
- return log.join('\n' + offset);
1177
- }
1178
- };
1179
-
1180
- /**
1181
- * @ngdoc service
1182
- * @name $httpBackend
1183
- * @description
1184
- * Fake HTTP backend implementation suitable for unit testing applications that use the
1185
- * {@link ng.$http $http service}.
1186
- *
1187
- * <div class="alert alert-info">
1188
- * **Note**: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
1189
- * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
1190
- * </div>
1191
- *
1192
- * During unit testing, we want our unit tests to run quickly and have no external dependencies so
1193
- * we don’t want to send [XHR](https://developer.mozilla.org/en/xmlhttprequest) or
1194
- * [JSONP](http://en.wikipedia.org/wiki/JSONP) requests to a real server. All we really need is
1195
- * to verify whether a certain request has been sent or not, or alternatively just let the
1196
- * application make requests, respond with pre-trained responses and assert that the end result is
1197
- * what we expect it to be.
1198
- *
1199
- * This mock implementation can be used to respond with static or dynamic responses via the
1200
- * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
1201
- *
1202
- * When an AngularJS application needs some data from a server, it calls the $http service, which
1203
- * sends the request to a real server using $httpBackend service. With dependency injection, it is
1204
- * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
1205
- * the requests and respond with some testing data without sending a request to a real server.
1206
- *
1207
- * There are two ways to specify what test data should be returned as http responses by the mock
1208
- * backend when the code under test makes http requests:
1209
- *
1210
- * - `$httpBackend.expect` - specifies a request expectation
1211
- * - `$httpBackend.when` - specifies a backend definition
1212
- *
1213
- *
1214
- * ## Request Expectations vs Backend Definitions
1215
- *
1216
- * Request expectations provide a way to make assertions about requests made by the application and
1217
- * to define responses for those requests. The test will fail if the expected requests are not made
1218
- * or they are made in the wrong order.
1219
- *
1220
- * Backend definitions allow you to define a fake backend for your application which doesn't assert
1221
- * if a particular request was made or not, it just returns a trained response if a request is made.
1222
- * The test will pass whether or not the request gets made during testing.
1223
- *
1224
- *
1225
- * <table class="table">
1226
- * <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
1227
- * <tr>
1228
- * <th>Syntax</th>
1229
- * <td>.expect(...).respond(...)</td>
1230
- * <td>.when(...).respond(...)</td>
1231
- * </tr>
1232
- * <tr>
1233
- * <th>Typical usage</th>
1234
- * <td>strict unit tests</td>
1235
- * <td>loose (black-box) unit testing</td>
1236
- * </tr>
1237
- * <tr>
1238
- * <th>Fulfills multiple requests</th>
1239
- * <td>NO</td>
1240
- * <td>YES</td>
1241
- * </tr>
1242
- * <tr>
1243
- * <th>Order of requests matters</th>
1244
- * <td>YES</td>
1245
- * <td>NO</td>
1246
- * </tr>
1247
- * <tr>
1248
- * <th>Request required</th>
1249
- * <td>YES</td>
1250
- * <td>NO</td>
1251
- * </tr>
1252
- * <tr>
1253
- * <th>Response required</th>
1254
- * <td>optional (see below)</td>
1255
- * <td>YES</td>
1256
- * </tr>
1257
- * </table>
1258
- *
1259
- * In cases where both backend definitions and request expectations are specified during unit
1260
- * testing, the request expectations are evaluated first.
1261
- *
1262
- * If a request expectation has no response specified, the algorithm will search your backend
1263
- * definitions for an appropriate response.
1264
- *
1265
- * If a request didn't match any expectation or if the expectation doesn't have the response
1266
- * defined, the backend definitions are evaluated in sequential order to see if any of them match
1267
- * the request. The response from the first matched definition is returned.
1268
- *
1269
- *
1270
- * ## Flushing HTTP requests
1271
- *
1272
- * The $httpBackend used in production always responds to requests asynchronously. If we preserved
1273
- * this behavior in unit testing, we'd have to create async unit tests, which are hard to write,
1274
- * to follow and to maintain. But neither can the testing mock respond synchronously; that would
1275
- * change the execution of the code under test. For this reason, the mock $httpBackend has a
1276
- * `flush()` method, which allows the test to explicitly flush pending requests. This preserves
1277
- * the async api of the backend, while allowing the test to execute synchronously.
1278
- *
1279
- *
1280
- * ## Unit testing with mock $httpBackend
1281
- * The following code shows how to setup and use the mock backend when unit testing a controller.
1282
- * First we create the controller under test:
1283
- *
1284
- ```js
1285
- // The module code
1286
- angular
1287
- .module('MyApp', [])
1288
- .controller('MyController', MyController);
1289
-
1290
- // The controller code
1291
- function MyController($scope, $http) {
1292
- var authToken;
1293
-
1294
- $http.get('/auth.py').then(function(response) {
1295
- authToken = response.headers('A-Token');
1296
- $scope.user = response.data;
1297
- }).catch(function() {
1298
- $scope.status = 'Failed...';
1299
- });
1300
-
1301
- $scope.saveMessage = function(message) {
1302
- var headers = { 'Authorization': authToken };
1303
- $scope.status = 'Saving...';
1304
-
1305
- $http.post('/add-msg.py', message, { headers: headers } ).then(function(response) {
1306
- $scope.status = '';
1307
- }).catch(function() {
1308
- $scope.status = 'Failed...';
1309
- });
1310
- };
1311
- }
1312
- ```
1313
- *
1314
- * Now we setup the mock backend and create the test specs:
1315
- *
1316
- ```js
1317
- // testing controller
1318
- describe('MyController', function() {
1319
- var $httpBackend, $rootScope, createController, authRequestHandler;
1320
-
1321
- // Set up the module
1322
- beforeEach(module('MyApp'));
1323
-
1324
- beforeEach(inject(function($injector) {
1325
- // Set up the mock http service responses
1326
- $httpBackend = $injector.get('$httpBackend');
1327
- // backend definition common for all tests
1328
- authRequestHandler = $httpBackend.when('GET', '/auth.py')
1329
- .respond({userId: 'userX'}, {'A-Token': 'xxx'});
1330
-
1331
- // Get hold of a scope (i.e. the root scope)
1332
- $rootScope = $injector.get('$rootScope');
1333
- // The $controller service is used to create instances of controllers
1334
- var $controller = $injector.get('$controller');
1335
-
1336
- createController = function() {
1337
- return $controller('MyController', {'$scope' : $rootScope });
1338
- };
1339
- }));
1340
-
1341
-
1342
- afterEach(function() {
1343
- $httpBackend.verifyNoOutstandingExpectation();
1344
- $httpBackend.verifyNoOutstandingRequest();
1345
- });
1346
-
1347
-
1348
- it('should fetch authentication token', function() {
1349
- $httpBackend.expectGET('/auth.py');
1350
- var controller = createController();
1351
- $httpBackend.flush();
1352
- });
1353
-
1354
-
1355
- it('should fail authentication', function() {
1356
-
1357
- // Notice how you can change the response even after it was set
1358
- authRequestHandler.respond(401, '');
1359
-
1360
- $httpBackend.expectGET('/auth.py');
1361
- var controller = createController();
1362
- $httpBackend.flush();
1363
- expect($rootScope.status).toBe('Failed...');
1364
- });
1365
-
1366
-
1367
- it('should send msg to server', function() {
1368
- var controller = createController();
1369
- $httpBackend.flush();
1370
-
1371
- // now you don’t care about the authentication, but
1372
- // the controller will still send the request and
1373
- // $httpBackend will respond without you having to
1374
- // specify the expectation and response for this request
1375
-
1376
- $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
1377
- $rootScope.saveMessage('message content');
1378
- expect($rootScope.status).toBe('Saving...');
1379
- $httpBackend.flush();
1380
- expect($rootScope.status).toBe('');
1381
- });
1382
-
1383
-
1384
- it('should send auth header', function() {
1385
- var controller = createController();
1386
- $httpBackend.flush();
1387
-
1388
- $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
1389
- // check if the header was sent, if it wasn't the expectation won't
1390
- // match the request and the test will fail
1391
- return headers['Authorization'] === 'xxx';
1392
- }).respond(201, '');
1393
-
1394
- $rootScope.saveMessage('whatever');
1395
- $httpBackend.flush();
1396
- });
1397
- });
1398
- ```
1399
- *
1400
- * ## Dynamic responses
1401
- *
1402
- * You define a response to a request by chaining a call to `respond()` onto a definition or expectation.
1403
- * If you provide a **callback** as the first parameter to `respond(callback)` then you can dynamically generate
1404
- * a response based on the properties of the request.
1405
- *
1406
- * The `callback` function should be of the form `function(method, url, data, headers, params)`.
1407
- *
1408
- * ### Query parameters
1409
- *
1410
- * By default, query parameters on request URLs are parsed into the `params` object. So a request URL
1411
- * of `/list?q=searchstr&orderby=-name` would set `params` to be `{q: 'searchstr', orderby: '-name'}`.
1412
- *
1413
- * ### Regex parameter matching
1414
- *
1415
- * If an expectation or definition uses a **regex** to match the URL, you can provide an array of **keys** via a
1416
- * `params` argument. The index of each **key** in the array will match the index of a **group** in the
1417
- * **regex**.
1418
- *
1419
- * The `params` object in the **callback** will now have properties with these keys, which hold the value of the
1420
- * corresponding **group** in the **regex**.
1421
- *
1422
- * This also applies to the `when` and `expect` shortcut methods.
1423
- *
1424
- *
1425
- * ```js
1426
- * $httpBackend.expect('GET', /\/user\/(.+)/, undefined, undefined, ['id'])
1427
- * .respond(function(method, url, data, headers, params) {
1428
- * // for requested url of '/user/1234' params is {id: '1234'}
1429
- * });
1430
- *
1431
- * $httpBackend.whenPATCH(/\/user\/(.+)\/article\/(.+)/, undefined, undefined, ['user', 'article'])
1432
- * .respond(function(method, url, data, headers, params) {
1433
- * // for url of '/user/1234/article/567' params is {user: '1234', article: '567'}
1434
- * });
1435
- * ```
1436
- *
1437
- * ## Matching route requests
1438
- *
1439
- * For extra convenience, `whenRoute` and `expectRoute` shortcuts are available. These methods offer colon
1440
- * delimited matching of the url path, ignoring the query string and trailing slashes. This allows declarations
1441
- * similar to how application routes are configured with `$routeProvider`. Because these methods convert
1442
- * the definition url to regex, declaration order is important. Combined with query parameter parsing,
1443
- * the following is possible:
1444
- *
1445
- ```js
1446
- $httpBackend.whenRoute('GET', '/users/:id')
1447
- .respond(function(method, url, data, headers, params) {
1448
- return [200, MockUserList[Number(params.id)]];
1449
- });
1450
-
1451
- $httpBackend.whenRoute('GET', '/users')
1452
- .respond(function(method, url, data, headers, params) {
1453
- var userList = angular.copy(MockUserList),
1454
- defaultSort = 'lastName',
1455
- count, pages, isPrevious, isNext;
1456
-
1457
- // paged api response '/v1/users?page=2'
1458
- params.page = Number(params.page) || 1;
1459
-
1460
- // query for last names '/v1/users?q=Archer'
1461
- if (params.q) {
1462
- userList = $filter('filter')({lastName: params.q});
1463
- }
1464
-
1465
- pages = Math.ceil(userList.length / pagingLength);
1466
- isPrevious = params.page > 1;
1467
- isNext = params.page < pages;
1468
-
1469
- return [200, {
1470
- count: userList.length,
1471
- previous: isPrevious,
1472
- next: isNext,
1473
- // sort field -> '/v1/users?sortBy=firstName'
1474
- results: $filter('orderBy')(userList, params.sortBy || defaultSort)
1475
- .splice((params.page - 1) * pagingLength, pagingLength)
1476
- }];
1477
- });
1478
- ```
1479
- */
1480
- angular.mock.$httpBackendDecorator =
1481
- ['$rootScope', '$timeout', '$delegate', createHttpBackendMock];
1482
-
1483
- /**
1484
- * General factory function for $httpBackend mock.
1485
- * Returns instance for unit testing (when no arguments specified):
1486
- * - passing through is disabled
1487
- * - auto flushing is disabled
1488
- *
1489
- * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
1490
- * - passing through (delegating request to real backend) is enabled
1491
- * - auto flushing is enabled
1492
- *
1493
- * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
1494
- * @param {Object=} $browser Auto-flushing enabled if specified
1495
- * @return {Object} Instance of $httpBackend mock
1496
- */
1497
- function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1498
- var definitions = [],
1499
- expectations = [],
1500
- matchLatestDefinition = false,
1501
- responses = [],
1502
- responsesPush = angular.bind(responses, responses.push),
1503
- copy = angular.copy,
1504
- // We cache the original backend so that if both ngMock and ngMockE2E override the
1505
- // service the ngMockE2E version can pass through to the real backend
1506
- originalHttpBackend = $delegate.$$originalHttpBackend || $delegate;
1507
-
1508
- function createResponse(status, data, headers, statusText) {
1509
- if (angular.isFunction(status)) return status;
1510
-
1511
- return function() {
1512
- return angular.isNumber(status)
1513
- ? [status, data, headers, statusText, 'complete']
1514
- : [200, status, data, headers, 'complete'];
1515
- };
1516
- }
1517
-
1518
- // TODO(vojta): change params to: method, url, data, headers, callback
1519
- function $httpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {
1520
-
1521
- var xhr = new MockXhr(),
1522
- expectation = expectations[0],
1523
- wasExpected = false;
1524
-
1525
- xhr.$$events = eventHandlers;
1526
- xhr.upload.$$events = uploadEventHandlers;
1527
-
1528
- function prettyPrint(data) {
1529
- return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
1530
- ? data
1531
- : angular.toJson(data);
1532
- }
1533
-
1534
- function wrapResponse(wrapped) {
1535
- if (!$browser && timeout) {
1536
- if (timeout.then) {
1537
- timeout.then(function() {
1538
- handlePrematureEnd(angular.isDefined(timeout.$$timeoutId) ? 'timeout' : 'abort');
1539
- });
1540
- } else {
1541
- $timeout(function() {
1542
- handlePrematureEnd('timeout');
1543
- }, timeout);
1544
- }
1545
- }
1546
-
1547
- handleResponse.description = method + ' ' + url;
1548
- return handleResponse;
1549
-
1550
- function handleResponse() {
1551
- var response = wrapped.response(method, url, data, headers, wrapped.params(url));
1552
- xhr.$$respHeaders = response[2];
1553
- callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
1554
- copy(response[3] || ''), copy(response[4]));
1555
- }
1556
-
1557
- function handlePrematureEnd(reason) {
1558
- for (var i = 0, ii = responses.length; i < ii; i++) {
1559
- if (responses[i] === handleResponse) {
1560
- responses.splice(i, 1);
1561
- callback(-1, undefined, '', undefined, reason);
1562
- break;
1563
- }
1564
- }
1565
- }
1566
- }
1567
-
1568
- function createFatalError(message) {
1569
- var error = new Error(message);
1570
- // In addition to being converted to a rejection, these errors also need to be passed to
1571
- // the $exceptionHandler and be rethrown (so that the test fails).
1572
- error.$$passToExceptionHandler = true;
1573
- return error;
1574
- }
1575
-
1576
- if (expectation && expectation.match(method, url)) {
1577
- if (!expectation.matchData(data)) {
1578
- throw createFatalError('Expected ' + expectation + ' with different data\n' +
1579
- 'EXPECTED: ' + prettyPrint(expectation.data) + '\n' +
1580
- 'GOT: ' + data);
1581
- }
1582
-
1583
- if (!expectation.matchHeaders(headers)) {
1584
- throw createFatalError('Expected ' + expectation + ' with different headers\n' +
1585
- 'EXPECTED: ' + prettyPrint(expectation.headers) + '\n' +
1586
- 'GOT: ' + prettyPrint(headers));
1587
- }
1588
-
1589
- expectations.shift();
1590
-
1591
- if (expectation.response) {
1592
- responses.push(wrapResponse(expectation));
1593
- return;
1594
- }
1595
- wasExpected = true;
1596
- }
1597
-
1598
- var i = matchLatestDefinition ? definitions.length : -1, definition;
1599
-
1600
- while ((definition = definitions[matchLatestDefinition ? --i : ++i])) {
1601
- if (definition.match(method, url, data, headers || {})) {
1602
- if (definition.response) {
1603
- // if $browser specified, we do auto flush all requests
1604
- ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
1605
- } else if (definition.passThrough) {
1606
- originalHttpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers);
1607
- } else throw createFatalError('No response defined !');
1608
- return;
1609
- }
1610
- }
1611
-
1612
- if (wasExpected) {
1613
- throw createFatalError('No response defined !');
1614
- }
1615
-
1616
- throw createFatalError('Unexpected request: ' + method + ' ' + url + '\n' +
1617
- (expectation ? 'Expected ' + expectation : 'No more request expected'));
1618
- }
1619
-
1620
- /**
1621
- * @ngdoc method
1622
- * @name $httpBackend#when
1623
- * @description
1624
- * Creates a new backend definition.
1625
- *
1626
- * @param {string} method HTTP method.
1627
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1628
- * and returns true if the url matches the current definition.
1629
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1630
- * data string and returns true if the data is as expected.
1631
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1632
- * object and returns true if the headers match the current definition.
1633
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1634
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1635
- * request is handled. You can save this object for later use and invoke `respond` again in
1636
- * order to change how a matched request is handled.
1637
- *
1638
- * - respond –
1639
- * ```js
1640
- * {function([status,] data[, headers, statusText])
1641
- * | function(function(method, url, data, headers, params)}
1642
- * ```
1643
- * – The respond method takes a set of static data to be returned or a function that can
1644
- * return an array containing response status (number), response data (Array|Object|string),
1645
- * response headers (Object), HTTP status text (string), and XMLHttpRequest status (string:
1646
- * `complete`, `error`, `timeout` or `abort`). The respond method returns the `requestHandler`
1647
- * object for possible overrides.
1648
- */
1649
- $httpBackend.when = function(method, url, data, headers, keys) {
1650
-
1651
- assertArgDefined(arguments, 1, 'url');
1652
-
1653
- var definition = new MockHttpExpectation(method, url, data, headers, keys),
1654
- chain = {
1655
- respond: function(status, data, headers, statusText) {
1656
- definition.passThrough = undefined;
1657
- definition.response = createResponse(status, data, headers, statusText);
1658
- return chain;
1659
- }
1660
- };
1661
-
1662
- if ($browser) {
1663
- chain.passThrough = function() {
1664
- definition.response = undefined;
1665
- definition.passThrough = true;
1666
- return chain;
1667
- };
1668
- }
1669
-
1670
- definitions.push(definition);
1671
- return chain;
1672
- };
1673
-
1674
- /**
1675
- * @ngdoc method
1676
- * @name $httpBackend#matchLatestDefinitionEnabled
1677
- * @description
1678
- * This method can be used to change which mocked responses `$httpBackend` returns, when defining
1679
- * them with {@link ngMock.$httpBackend#when $httpBackend.when()} (and shortcut methods).
1680
- * By default, `$httpBackend` returns the first definition that matches. When setting
1681
- * `$http.matchLatestDefinitionEnabled(true)`, it will use the last response that matches, i.e. the
1682
- * one that was added last.
1683
- *
1684
- * ```js
1685
- * hb.when('GET', '/url1').respond(200, 'content', {});
1686
- * hb.when('GET', '/url1').respond(201, 'another', {});
1687
- * hb('GET', '/url1'); // receives "content"
1688
- *
1689
- * $http.matchLatestDefinitionEnabled(true)
1690
- * hb('GET', '/url1'); // receives "another"
1691
- *
1692
- * hb.when('GET', '/url1').respond(201, 'onemore', {});
1693
- * hb('GET', '/url1'); // receives "onemore"
1694
- * ```
1695
- *
1696
- * This is useful if a you have a default response that is overriden inside specific tests.
1697
- *
1698
- * Note that different from config methods on providers, `matchLatestDefinitionEnabled()` can be changed
1699
- * even when the application is already running.
1700
- *
1701
- * @param {Boolean=} value value to set, either `true` or `false`. Default is `false`.
1702
- * If omitted, it will return the current value.
1703
- * @return {$httpBackend|Boolean} self when used as a setter, and the current value when used
1704
- * as a getter
1705
- */
1706
- $httpBackend.matchLatestDefinitionEnabled = function(value) {
1707
- if (angular.isDefined(value)) {
1708
- matchLatestDefinition = value;
1709
- return this;
1710
- } else {
1711
- return matchLatestDefinition;
1712
- }
1713
- };
1714
-
1715
- /**
1716
- * @ngdoc method
1717
- * @name $httpBackend#whenGET
1718
- * @description
1719
- * Creates a new backend definition for GET requests. For more info see `when()`.
1720
- *
1721
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1722
- * and returns true if the url matches the current definition.
1723
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1724
- * object and returns true if the headers match the current definition.
1725
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1726
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1727
- * request is handled. You can save this object for later use and invoke `respond` again in
1728
- * order to change how a matched request is handled.
1729
- */
1730
-
1731
- /**
1732
- * @ngdoc method
1733
- * @name $httpBackend#whenHEAD
1734
- * @description
1735
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
1736
- *
1737
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1738
- * and returns true if the url matches the current definition.
1739
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1740
- * object and returns true if the headers match the current definition.
1741
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1742
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1743
- * request is handled. You can save this object for later use and invoke `respond` again in
1744
- * order to change how a matched request is handled.
1745
- */
1746
-
1747
- /**
1748
- * @ngdoc method
1749
- * @name $httpBackend#whenDELETE
1750
- * @description
1751
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
1752
- *
1753
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1754
- * and returns true if the url matches the current definition.
1755
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1756
- * object and returns true if the headers match the current definition.
1757
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1758
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1759
- * request is handled. You can save this object for later use and invoke `respond` again in
1760
- * order to change how a matched request is handled.
1761
- */
1762
-
1763
- /**
1764
- * @ngdoc method
1765
- * @name $httpBackend#whenPOST
1766
- * @description
1767
- * Creates a new backend definition for POST requests. For more info see `when()`.
1768
- *
1769
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1770
- * and returns true if the url matches the current definition.
1771
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1772
- * data string and returns true if the data is as expected.
1773
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1774
- * object and returns true if the headers match the current definition.
1775
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1776
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1777
- * request is handled. You can save this object for later use and invoke `respond` again in
1778
- * order to change how a matched request is handled.
1779
- */
1780
-
1781
- /**
1782
- * @ngdoc method
1783
- * @name $httpBackend#whenPUT
1784
- * @description
1785
- * Creates a new backend definition for PUT requests. For more info see `when()`.
1786
- *
1787
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1788
- * and returns true if the url matches the current definition.
1789
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1790
- * data string and returns true if the data is as expected.
1791
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1792
- * object and returns true if the headers match the current definition.
1793
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1794
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1795
- * request is handled. You can save this object for later use and invoke `respond` again in
1796
- * order to change how a matched request is handled.
1797
- */
1798
-
1799
- /**
1800
- * @ngdoc method
1801
- * @name $httpBackend#whenJSONP
1802
- * @description
1803
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
1804
- *
1805
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1806
- * and returns true if the url matches the current definition.
1807
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1808
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1809
- * request is handled. You can save this object for later use and invoke `respond` again in
1810
- * order to change how a matched request is handled.
1811
- */
1812
- createShortMethods('when');
1813
-
1814
- /**
1815
- * @ngdoc method
1816
- * @name $httpBackend#whenRoute
1817
- * @description
1818
- * Creates a new backend definition that compares only with the requested route.
1819
- *
1820
- * @param {string} method HTTP method.
1821
- * @param {string} url HTTP url string that supports colon param matching.
1822
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1823
- * request is handled. You can save this object for later use and invoke `respond` again in
1824
- * order to change how a matched request is handled.
1825
- * See {@link ngMock.$httpBackend#when `when`} for more info.
1826
- */
1827
- $httpBackend.whenRoute = function(method, url) {
1828
- var parsed = parseRouteUrl(url);
1829
- return $httpBackend.when(method, parsed.regexp, undefined, undefined, parsed.keys);
1830
- };
1831
-
1832
- /**
1833
- * @ngdoc method
1834
- * @name $httpBackend#expect
1835
- * @description
1836
- * Creates a new request expectation.
1837
- *
1838
- * @param {string} method HTTP method.
1839
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1840
- * and returns true if the url matches the current definition.
1841
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1842
- * receives data string and returns true if the data is as expected, or Object if request body
1843
- * is in JSON format.
1844
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1845
- * object and returns true if the headers match the current expectation.
1846
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1847
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1848
- * request is handled. You can save this object for later use and invoke `respond` again in
1849
- * order to change how a matched request is handled.
1850
- *
1851
- * - respond –
1852
- * ```js
1853
- * {function([status,] data[, headers, statusText])
1854
- * | function(function(method, url, data, headers, params)}
1855
- * ```
1856
- * – The respond method takes a set of static data to be returned or a function that can
1857
- * return an array containing response status (number), response data (Array|Object|string),
1858
- * response headers (Object), HTTP status text (string), and XMLHttpRequest status (string:
1859
- * `complete`, `error`, `timeout` or `abort`). The respond method returns the `requestHandler`
1860
- * object for possible overrides.
1861
- */
1862
- $httpBackend.expect = function(method, url, data, headers, keys) {
1863
-
1864
- assertArgDefined(arguments, 1, 'url');
1865
-
1866
- var expectation = new MockHttpExpectation(method, url, data, headers, keys),
1867
- chain = {
1868
- respond: function(status, data, headers, statusText) {
1869
- expectation.response = createResponse(status, data, headers, statusText);
1870
- return chain;
1871
- }
1872
- };
1873
-
1874
- expectations.push(expectation);
1875
- return chain;
1876
- };
1877
-
1878
- /**
1879
- * @ngdoc method
1880
- * @name $httpBackend#expectGET
1881
- * @description
1882
- * Creates a new request expectation for GET requests. For more info see `expect()`.
1883
- *
1884
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1885
- * and returns true if the url matches the current expectation.
1886
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1887
- * object and returns true if the headers match the current expectation.
1888
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1889
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1890
- * request is handled. You can save this object for later use and invoke `respond` again in
1891
- * order to change how a matched request is handled. See #expect for more info.
1892
- */
1893
-
1894
- /**
1895
- * @ngdoc method
1896
- * @name $httpBackend#expectHEAD
1897
- * @description
1898
- * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1899
- *
1900
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1901
- * and returns true if the url matches the current expectation.
1902
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1903
- * object and returns true if the headers match the current expectation.
1904
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1905
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1906
- * request is handled. You can save this object for later use and invoke `respond` again in
1907
- * order to change how a matched request is handled.
1908
- */
1909
-
1910
- /**
1911
- * @ngdoc method
1912
- * @name $httpBackend#expectDELETE
1913
- * @description
1914
- * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1915
- *
1916
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1917
- * and returns true if the url matches the current expectation.
1918
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1919
- * object and returns true if the headers match the current expectation.
1920
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1921
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1922
- * request is handled. You can save this object for later use and invoke `respond` again in
1923
- * order to change how a matched request is handled.
1924
- */
1925
-
1926
- /**
1927
- * @ngdoc method
1928
- * @name $httpBackend#expectPOST
1929
- * @description
1930
- * Creates a new request expectation for POST requests. For more info see `expect()`.
1931
- *
1932
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1933
- * and returns true if the url matches the current expectation.
1934
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1935
- * receives data string and returns true if the data is as expected, or Object if request body
1936
- * is in JSON format.
1937
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1938
- * object and returns true if the headers match the current expectation.
1939
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1940
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1941
- * request is handled. You can save this object for later use and invoke `respond` again in
1942
- * order to change how a matched request is handled.
1943
- */
1944
-
1945
- /**
1946
- * @ngdoc method
1947
- * @name $httpBackend#expectPUT
1948
- * @description
1949
- * Creates a new request expectation for PUT requests. For more info see `expect()`.
1950
- *
1951
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1952
- * and returns true if the url matches the current expectation.
1953
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1954
- * receives data string and returns true if the data is as expected, or Object if request body
1955
- * is in JSON format.
1956
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1957
- * object and returns true if the headers match the current expectation.
1958
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1959
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1960
- * request is handled. You can save this object for later use and invoke `respond` again in
1961
- * order to change how a matched request is handled.
1962
- */
1963
-
1964
- /**
1965
- * @ngdoc method
1966
- * @name $httpBackend#expectPATCH
1967
- * @description
1968
- * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1969
- *
1970
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
1971
- * and returns true if the url matches the current expectation.
1972
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1973
- * receives data string and returns true if the data is as expected, or Object if request body
1974
- * is in JSON format.
1975
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1976
- * object and returns true if the headers match the current expectation.
1977
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1978
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1979
- * request is handled. You can save this object for later use and invoke `respond` again in
1980
- * order to change how a matched request is handled.
1981
- */
1982
-
1983
- /**
1984
- * @ngdoc method
1985
- * @name $httpBackend#expectJSONP
1986
- * @description
1987
- * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1988
- *
1989
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives an url
1990
- * and returns true if the url matches the current expectation.
1991
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
1992
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1993
- * request is handled. You can save this object for later use and invoke `respond` again in
1994
- * order to change how a matched request is handled.
1995
- */
1996
- createShortMethods('expect');
1997
-
1998
- /**
1999
- * @ngdoc method
2000
- * @name $httpBackend#expectRoute
2001
- * @description
2002
- * Creates a new request expectation that compares only with the requested route.
2003
- *
2004
- * @param {string} method HTTP method.
2005
- * @param {string} url HTTP url string that supports colon param matching.
2006
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
2007
- * request is handled. You can save this object for later use and invoke `respond` again in
2008
- * order to change how a matched request is handled.
2009
- * See {@link ngMock.$httpBackend#expect `expect`} for more info.
2010
- */
2011
- $httpBackend.expectRoute = function(method, url) {
2012
- var parsed = parseRouteUrl(url);
2013
- return $httpBackend.expect(method, parsed.regexp, undefined, undefined, parsed.keys);
2014
- };
2015
-
2016
-
2017
- /**
2018
- * @ngdoc method
2019
- * @name $httpBackend#flush
2020
- * @description
2021
- * Flushes pending requests using the trained responses. Requests are flushed in the order they
2022
- * were made, but it is also possible to skip one or more requests (for example to have them
2023
- * flushed later). This is useful for simulating scenarios where responses arrive from the server
2024
- * in any order.
2025
- *
2026
- * If there are no pending requests to flush when the method is called, an exception is thrown (as
2027
- * this is typically a sign of programming error).
2028
- *
2029
- * @param {number=} count - Number of responses to flush. If undefined/null, all pending requests
2030
- * (starting after `skip`) will be flushed.
2031
- * @param {number=} [skip=0] - Number of pending requests to skip. For example, a value of `5`
2032
- * would skip the first 5 pending requests and start flushing from the 6th onwards.
2033
- */
2034
- $httpBackend.flush = function(count, skip, digest) {
2035
- if (digest !== false) $rootScope.$digest();
2036
-
2037
- skip = skip || 0;
2038
- if (skip >= responses.length) throw new Error('No pending request to flush !');
2039
-
2040
- if (angular.isDefined(count) && count !== null) {
2041
- while (count--) {
2042
- var part = responses.splice(skip, 1);
2043
- if (!part.length) throw new Error('No more pending request to flush !');
2044
- part[0]();
2045
- }
2046
- } else {
2047
- while (responses.length > skip) {
2048
- responses.splice(skip, 1)[0]();
2049
- }
2050
- }
2051
- $httpBackend.verifyNoOutstandingExpectation(digest);
2052
- };
2053
-
2054
-
2055
- /**
2056
- * @ngdoc method
2057
- * @name $httpBackend#verifyNoOutstandingExpectation
2058
- * @description
2059
- * Verifies that all of the requests defined via the `expect` api were made. If any of the
2060
- * requests were not made, verifyNoOutstandingExpectation throws an exception.
2061
- *
2062
- * Typically, you would call this method following each test case that asserts requests using an
2063
- * "afterEach" clause.
2064
- *
2065
- * ```js
2066
- * afterEach($httpBackend.verifyNoOutstandingExpectation);
2067
- * ```
2068
- */
2069
- $httpBackend.verifyNoOutstandingExpectation = function(digest) {
2070
- if (digest !== false) $rootScope.$digest();
2071
- if (expectations.length) {
2072
- throw new Error('Unsatisfied requests: ' + expectations.join(', '));
2073
- }
2074
- };
2075
-
2076
-
2077
- /**
2078
- * @ngdoc method
2079
- * @name $httpBackend#verifyNoOutstandingRequest
2080
- * @description
2081
- * Verifies that there are no outstanding requests that need to be flushed.
2082
- *
2083
- * Typically, you would call this method following each test case that asserts requests using an
2084
- * "afterEach" clause.
2085
- *
2086
- * ```js
2087
- * afterEach($httpBackend.verifyNoOutstandingRequest);
2088
- * ```
2089
- */
2090
- $httpBackend.verifyNoOutstandingRequest = function(digest) {
2091
- if (digest !== false) $rootScope.$digest();
2092
- if (responses.length) {
2093
- var unflushedDescriptions = responses.map(function(res) { return res.description; });
2094
- throw new Error('Unflushed requests: ' + responses.length + '\n ' +
2095
- unflushedDescriptions.join('\n '));
2096
- }
2097
- };
2098
-
2099
-
2100
- /**
2101
- * @ngdoc method
2102
- * @name $httpBackend#resetExpectations
2103
- * @description
2104
- * Resets all request expectations, but preserves all backend definitions. Typically, you would
2105
- * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
2106
- * $httpBackend mock.
2107
- */
2108
- $httpBackend.resetExpectations = function() {
2109
- expectations.length = 0;
2110
- responses.length = 0;
2111
- };
2112
-
2113
- $httpBackend.$$originalHttpBackend = originalHttpBackend;
2114
-
2115
- return $httpBackend;
2116
-
2117
-
2118
- function createShortMethods(prefix) {
2119
- angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
2120
- $httpBackend[prefix + method] = function(url, headers, keys) {
2121
- assertArgDefined(arguments, 0, 'url');
2122
-
2123
- // Change url to `null` if `undefined` to stop it throwing an exception further down
2124
- if (angular.isUndefined(url)) url = null;
2125
-
2126
- return $httpBackend[prefix](method, url, undefined, headers, keys);
2127
- };
2128
- });
2129
-
2130
- angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
2131
- $httpBackend[prefix + method] = function(url, data, headers, keys) {
2132
- assertArgDefined(arguments, 0, 'url');
2133
-
2134
- // Change url to `null` if `undefined` to stop it throwing an exception further down
2135
- if (angular.isUndefined(url)) url = null;
2136
-
2137
- return $httpBackend[prefix](method, url, data, headers, keys);
2138
- };
2139
- });
2140
- }
2141
-
2142
- function parseRouteUrl(url) {
2143
- var strippedUrl = stripQueryAndHash(url);
2144
- var parseOptions = {caseInsensitiveMatch: true, ignoreTrailingSlashes: true};
2145
- return routeToRegExp(strippedUrl, parseOptions);
2146
- }
2147
- }
2148
-
2149
- function assertArgDefined(args, index, name) {
2150
- if (args.length > index && angular.isUndefined(args[index])) {
2151
- throw new Error('Undefined argument `' + name + '`; the argument is provided but not defined');
2152
- }
2153
- }
2154
-
2155
- function stripQueryAndHash(url) {
2156
- return url.replace(/[?#].*$/, '');
2157
- }
2158
-
2159
- function MockHttpExpectation(expectedMethod, expectedUrl, expectedData, expectedHeaders,
2160
- expectedKeys) {
2161
-
2162
- this.data = expectedData;
2163
- this.headers = expectedHeaders;
2164
-
2165
- this.match = function(method, url, data, headers) {
2166
- if (expectedMethod !== method) return false;
2167
- if (!this.matchUrl(url)) return false;
2168
- if (angular.isDefined(data) && !this.matchData(data)) return false;
2169
- if (angular.isDefined(headers) && !this.matchHeaders(headers)) return false;
2170
- return true;
2171
- };
2172
-
2173
- this.matchUrl = function(url) {
2174
- if (!expectedUrl) return true;
2175
- if (angular.isFunction(expectedUrl.test)) return expectedUrl.test(url);
2176
- if (angular.isFunction(expectedUrl)) return expectedUrl(url);
2177
- return (expectedUrl === url || compareUrlWithQuery(url));
2178
- };
2179
-
2180
- this.matchHeaders = function(headers) {
2181
- if (angular.isUndefined(expectedHeaders)) return true;
2182
- if (angular.isFunction(expectedHeaders)) return expectedHeaders(headers);
2183
- return angular.equals(expectedHeaders, headers);
2184
- };
2185
-
2186
- this.matchData = function(data) {
2187
- if (angular.isUndefined(expectedData)) return true;
2188
- if (expectedData && angular.isFunction(expectedData.test)) return expectedData.test(data);
2189
- if (expectedData && angular.isFunction(expectedData)) return expectedData(data);
2190
- if (expectedData && !angular.isString(expectedData)) {
2191
- return angular.equals(angular.fromJson(angular.toJson(expectedData)), angular.fromJson(data));
2192
- }
2193
- // eslint-disable-next-line eqeqeq
2194
- return expectedData == data;
2195
- };
2196
-
2197
- this.toString = function() {
2198
- return expectedMethod + ' ' + expectedUrl;
2199
- };
2200
-
2201
- this.params = function(url) {
2202
- var queryStr = url.indexOf('?') === -1 ? '' : url.substring(url.indexOf('?') + 1);
2203
- var strippedUrl = stripQueryAndHash(url);
2204
-
2205
- return angular.extend(extractParamsFromQuery(queryStr), extractParamsFromPath(strippedUrl));
2206
- };
2207
-
2208
- function compareUrlWithQuery(url) {
2209
- var urlWithQueryRe = /^([^?]*)\?(.*)$/;
2210
-
2211
- var expectedMatch = urlWithQueryRe.exec(expectedUrl);
2212
- var actualMatch = urlWithQueryRe.exec(url);
2213
-
2214
- return !!(expectedMatch && actualMatch) &&
2215
- (expectedMatch[1] === actualMatch[1]) &&
2216
- (normalizeQuery(expectedMatch[2]) === normalizeQuery(actualMatch[2]));
2217
- }
2218
-
2219
- function normalizeQuery(queryStr) {
2220
- return queryStr.split('&').sort().join('&');
2221
- }
2222
-
2223
- function extractParamsFromPath(strippedUrl) {
2224
- var keyObj = {};
2225
-
2226
- if (!expectedUrl || !angular.isFunction(expectedUrl.test) ||
2227
- !expectedKeys || !expectedKeys.length) return keyObj;
2228
-
2229
- var match = expectedUrl.exec(strippedUrl);
2230
- if (!match) return keyObj;
2231
-
2232
- for (var i = 1, len = match.length; i < len; ++i) {
2233
- var key = expectedKeys[i - 1];
2234
- var val = match[i];
2235
- if (key && val) {
2236
- keyObj[key.name || key] = val;
2237
- }
2238
- }
2239
-
2240
- return keyObj;
2241
- }
2242
-
2243
- function extractParamsFromQuery(queryStr) {
2244
- var obj = {},
2245
- keyValuePairs = queryStr.split('&').
2246
- filter(angular.identity). // Ignore empty segments.
2247
- map(function(keyValue) { return keyValue.replace(/\+/g, '%20').split('='); });
2248
-
2249
- angular.forEach(keyValuePairs, function(pair) {
2250
- var key = tryDecodeURIComponent(pair[0]);
2251
- if (angular.isDefined(key)) {
2252
- var val = angular.isDefined(pair[1]) ? tryDecodeURIComponent(pair[1]) : true;
2253
- if (!hasOwnProperty.call(obj, key)) {
2254
- obj[key] = val;
2255
- } else if (angular.isArray(obj[key])) {
2256
- obj[key].push(val);
2257
- } else {
2258
- obj[key] = [obj[key], val];
2259
- }
2260
- }
2261
- });
2262
-
2263
- return obj;
2264
- }
2265
-
2266
- function tryDecodeURIComponent(value) {
2267
- try {
2268
- return decodeURIComponent(value);
2269
- } catch (e) {
2270
- // Ignore any invalid uri component
2271
- }
2272
- }
2273
- }
2274
-
2275
- function createMockXhr() {
2276
- return new MockXhr();
2277
- }
2278
-
2279
- function MockXhr() {
2280
-
2281
- // hack for testing $http, $httpBackend
2282
- MockXhr.$$lastInstance = this;
2283
-
2284
- this.open = function(method, url, async) {
2285
- this.$$method = method;
2286
- this.$$url = url;
2287
- this.$$async = async;
2288
- this.$$reqHeaders = {};
2289
- this.$$respHeaders = {};
2290
- };
2291
-
2292
- this.send = function(data) {
2293
- this.$$data = data;
2294
- };
2295
-
2296
- this.setRequestHeader = function(key, value) {
2297
- this.$$reqHeaders[key] = value;
2298
- };
2299
-
2300
- this.getResponseHeader = function(name) {
2301
- // the lookup must be case insensitive,
2302
- // that's why we try two quick lookups first and full scan last
2303
- var header = this.$$respHeaders[name];
2304
- if (header) return header;
2305
-
2306
- name = angular.$$lowercase(name);
2307
- header = this.$$respHeaders[name];
2308
- if (header) return header;
2309
-
2310
- header = undefined;
2311
- angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
2312
- if (!header && angular.$$lowercase(headerName) === name) header = headerVal;
2313
- });
2314
- return header;
2315
- };
2316
-
2317
- this.getAllResponseHeaders = function() {
2318
- var lines = [];
2319
-
2320
- angular.forEach(this.$$respHeaders, function(value, key) {
2321
- lines.push(key + ': ' + value);
2322
- });
2323
- return lines.join('\n');
2324
- };
2325
-
2326
- this.abort = function() {
2327
- if (isFunction(this.onabort)) {
2328
- this.onabort();
2329
- }
2330
- };
2331
-
2332
- // This section simulates the events on a real XHR object (and the upload object)
2333
- // When we are testing $httpBackend (inside the AngularJS project) we make partial use of this
2334
- // but store the events directly ourselves on `$$events`, instead of going through the `addEventListener`
2335
- this.$$events = {};
2336
- this.addEventListener = function(name, listener) {
2337
- if (angular.isUndefined(this.$$events[name])) this.$$events[name] = [];
2338
- this.$$events[name].push(listener);
2339
- };
2340
-
2341
- this.upload = {
2342
- $$events: {},
2343
- addEventListener: this.addEventListener
2344
- };
2345
- }
2346
-
2347
-
2348
- /**
2349
- * @ngdoc service
2350
- * @name $timeout
2351
- * @description
2352
- *
2353
- * This service is just a simple decorator for {@link ng.$timeout $timeout} service
2354
- * that adds a "flush" and "verifyNoPendingTasks" methods.
2355
- */
2356
-
2357
- angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) {
2358
-
2359
- /**
2360
- * @ngdoc method
2361
- * @name $timeout#flush
2362
- *
2363
- * @deprecated
2364
- * sinceVersion="1.7.3"
2365
- *
2366
- * This method flushes all types of tasks (not only timeouts), which is unintuitive.
2367
- * It is recommended to use {@link ngMock.$flushPendingTasks} instead.
2368
- *
2369
- * @description
2370
- *
2371
- * Flushes the queue of pending tasks.
2372
- *
2373
- * _This method is essentially an alias of {@link ngMock.$flushPendingTasks}._
2374
- *
2375
- * <div class="alert alert-warning">
2376
- * For historical reasons, this method will also flush non-`$timeout` pending tasks, such as
2377
- * {@link $q} promises and tasks scheduled via
2378
- * {@link ng.$rootScope.Scope#$applyAsync $applyAsync} and
2379
- * {@link ng.$rootScope.Scope#$evalAsync $evalAsync}.
2380
- * </div>
2381
- *
2382
- * @param {number=} delay maximum timeout amount to flush up until
2383
- */
2384
- $delegate.flush = function(delay) {
2385
- // For historical reasons, `$timeout.flush()` flushes all types of pending tasks.
2386
- // Keep the same behavior for backwards compatibility (and because it doesn't make sense to
2387
- // selectively flush scheduled events out of order).
2388
- $browser.defer.flush(delay);
2389
- };
2390
-
2391
- /**
2392
- * @ngdoc method
2393
- * @name $timeout#verifyNoPendingTasks
2394
- *
2395
- * @deprecated
2396
- * sinceVersion="1.7.3"
2397
- *
2398
- * This method takes all types of tasks (not only timeouts) into account, which is unintuitive.
2399
- * It is recommended to use {@link ngMock.$verifyNoPendingTasks} instead, which additionally
2400
- * allows checking for timeouts only (with `$verifyNoPendingTasks('$timeout')`).
2401
- *
2402
- * @description
2403
- *
2404
- * Verifies that there are no pending tasks that need to be flushed. It throws an error if there
2405
- * are still pending tasks.
2406
- *
2407
- * _This method is essentially an alias of {@link ngMock.$verifyNoPendingTasks} (called with no
2408
- * arguments)._
2409
- *
2410
- * <div class="alert alert-warning">
2411
- * <p>
2412
- * For historical reasons, this method will also verify non-`$timeout` pending tasks, such as
2413
- * pending {@link $http} requests, in-progress {@link $route} transitions, unresolved
2414
- * {@link $q} promises and tasks scheduled via
2415
- * {@link ng.$rootScope.Scope#$applyAsync $applyAsync} and
2416
- * {@link ng.$rootScope.Scope#$evalAsync $evalAsync}.
2417
- * </p>
2418
- * <p>
2419
- * It is recommended to use {@link ngMock.$verifyNoPendingTasks} instead, which additionally
2420
- * supports verifying a specific type of tasks. For example, you can verify there are no
2421
- * pending timeouts with `$verifyNoPendingTasks('$timeout')`.
2422
- * </p>
2423
- * </div>
2424
- */
2425
- $delegate.verifyNoPendingTasks = function() {
2426
- // For historical reasons, `$timeout.verifyNoPendingTasks()` takes all types of pending tasks
2427
- // into account. Keep the same behavior for backwards compatibility.
2428
- var pendingTasks = $browser.defer.getPendingTasks();
2429
-
2430
- if (pendingTasks.length) {
2431
- var formattedTasks = $browser.defer.formatPendingTasks(pendingTasks).join('\n ');
2432
- var hasPendingTimeout = pendingTasks.some(function(task) { return task.type === '$timeout'; });
2433
- var extraMessage = hasPendingTimeout ? '' : '\n\nNone of the pending tasks are timeouts. ' +
2434
- 'If you only want to verify pending timeouts, use ' +
2435
- '`$verifyNoPendingTasks(\'$timeout\')` instead.';
2436
-
2437
- throw new Error('Deferred tasks to flush (' + pendingTasks.length + '):\n ' +
2438
- formattedTasks + extraMessage);
2439
- }
2440
- };
2441
-
2442
- return $delegate;
2443
- }];
2444
-
2445
- angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
2446
- var rafFn = function(fn) {
2447
- var index = rafFn.queue.length;
2448
- rafFn.queue.push(fn);
2449
- return function() {
2450
- rafFn.queue.splice(index, 1);
2451
- };
2452
- };
2453
-
2454
- rafFn.queue = [];
2455
- rafFn.supported = $delegate.supported;
2456
-
2457
- rafFn.flush = function() {
2458
- if (rafFn.queue.length === 0) {
2459
- throw new Error('No rAF callbacks present');
2460
- }
2461
-
2462
- var length = rafFn.queue.length;
2463
- for (var i = 0; i < length; i++) {
2464
- rafFn.queue[i]();
2465
- }
2466
-
2467
- rafFn.queue = rafFn.queue.slice(i);
2468
- };
2469
-
2470
- return rafFn;
2471
- }];
2472
-
2473
- /**
2474
- *
2475
- */
2476
- var originalRootElement;
2477
- angular.mock.$RootElementProvider = function() {
2478
- this.$get = ['$injector', function($injector) {
2479
- originalRootElement = angular.element('<div ng-app></div>').data('$injector', $injector);
2480
- return originalRootElement;
2481
- }];
2482
- };
2483
-
2484
- /**
2485
- * @ngdoc service
2486
- * @name $controller
2487
- * @description
2488
- * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing
2489
- * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}.
2490
- *
2491
- * ## Example
2492
- *
2493
- * ```js
2494
- *
2495
- * // Directive definition ...
2496
- *
2497
- * myMod.directive('myDirective', {
2498
- * controller: 'MyDirectiveController',
2499
- * bindToController: {
2500
- * name: '@'
2501
- * }
2502
- * });
2503
- *
2504
- *
2505
- * // Controller definition ...
2506
- *
2507
- * myMod.controller('MyDirectiveController', ['$log', function($log) {
2508
- * this.log = function() {
2509
- * $log.info(this.name);
2510
- * };
2511
- * }]);
2512
- *
2513
- *
2514
- * // In a test ...
2515
- *
2516
- * describe('myDirectiveController', function() {
2517
- * describe('log()', function() {
2518
- * it('should write the bound name to the log', inject(function($controller, $log) {
2519
- * var ctrl = $controller('MyDirectiveController', { /* no locals &#42;/ }, { name: 'Clark Kent' });
2520
- * ctrl.log();
2521
- *
2522
- * expect(ctrl.name).toEqual('Clark Kent');
2523
- * expect($log.info.logs).toEqual(['Clark Kent']);
2524
- * }));
2525
- * });
2526
- * });
2527
- *
2528
- * ```
2529
- *
2530
- * @param {Function|string} constructor If called with a function then it's considered to be the
2531
- * controller constructor function. Otherwise it's considered to be a string which is used
2532
- * to retrieve the controller constructor using the following steps:
2533
- *
2534
- * * check if a controller with given name is registered via `$controllerProvider`
2535
- * * check if evaluating the string on the current scope returns a constructor
2536
- *
2537
- * The string can use the `controller as property` syntax, where the controller instance is published
2538
- * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
2539
- * to work correctly.
2540
- *
2541
- * @param {Object} locals Injection locals for Controller.
2542
- * @param {Object=} bindings Properties to add to the controller instance. This is used to simulate
2543
- * the `bindToController` feature and simplify certain kinds of tests.
2544
- * @return {Object} Instance of given controller.
2545
- */
2546
- function createControllerDecorator() {
2547
- angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
2548
- return function(expression, locals, later, ident) {
2549
- if (later && typeof later === 'object') {
2550
- var instantiate = $delegate(expression, locals, true, ident);
2551
- var instance = instantiate();
2552
- angular.extend(instance, later);
2553
- return instance;
2554
- }
2555
- return $delegate(expression, locals, later, ident);
2556
- };
2557
- }];
2558
-
2559
- return angular.mock.$ControllerDecorator;
2560
- }
2561
-
2562
- /**
2563
- * @ngdoc service
2564
- * @name $componentController
2565
- * @description
2566
- * A service that can be used to create instances of component controllers. Useful for unit-testing.
2567
- *
2568
- * Be aware that the controller will be instantiated and attached to the scope as specified in
2569
- * the component definition object. If you do not provide a `$scope` object in the `locals` param
2570
- * then the helper will create a new isolated scope as a child of `$rootScope`.
2571
- *
2572
- * If you are using `$element` or `$attrs` in the controller, make sure to provide them as `locals`.
2573
- * The `$element` must be a jqLite-wrapped DOM element, and `$attrs` should be an object that
2574
- * has all properties / functions that you are using in the controller. If this is getting too complex,
2575
- * you should compile the component instead and access the component's controller via the
2576
- * {@link angular.element#methods `controller`} function.
2577
- *
2578
- * See also the section on {@link guide/component#unit-testing-component-controllers unit-testing component controllers}
2579
- * in the guide.
2580
- *
2581
- * @param {string} componentName the name of the component whose controller we want to instantiate
2582
- * @param {Object} locals Injection locals for Controller.
2583
- * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
2584
- * to simulate the `bindToController` feature and simplify certain kinds of tests.
2585
- * @param {string=} ident Override the property name to use when attaching the controller to the scope.
2586
- * @return {Object} Instance of requested controller.
2587
- */
2588
- angular.mock.$ComponentControllerProvider = ['$compileProvider',
2589
- function ComponentControllerProvider($compileProvider) {
2590
- this.$get = ['$controller','$injector', '$rootScope', function($controller, $injector, $rootScope) {
2591
- return function $componentController(componentName, locals, bindings, ident) {
2592
- // get all directives associated to the component name
2593
- var directives = $injector.get(componentName + 'Directive');
2594
- // look for those directives that are components
2595
- var candidateDirectives = directives.filter(function(directiveInfo) {
2596
- // components have controller, controllerAs and restrict:'E'
2597
- return directiveInfo.controller && directiveInfo.controllerAs && directiveInfo.restrict === 'E';
2598
- });
2599
- // check if valid directives found
2600
- if (candidateDirectives.length === 0) {
2601
- throw new Error('No component found');
2602
- }
2603
- if (candidateDirectives.length > 1) {
2604
- throw new Error('Too many components found');
2605
- }
2606
- // get the info of the component
2607
- var directiveInfo = candidateDirectives[0];
2608
- // create a scope if needed
2609
- locals = locals || {};
2610
- locals.$scope = locals.$scope || $rootScope.$new(true);
2611
- return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
2612
- };
2613
- }];
2614
- }];
2615
-
2616
-
2617
- /**
2618
- * @ngdoc module
2619
- * @name ngMock
2620
- * @packageName angular-mocks
2621
- * @description
2622
- *
2623
- * The `ngMock` module provides support to inject and mock AngularJS services into unit tests.
2624
- * In addition, ngMock also extends various core AngularJS services such that they can be
2625
- * inspected and controlled in a synchronous manner within test code.
2626
- *
2627
- * @installation
2628
- *
2629
- * First, download the file:
2630
- * * [Google CDN](https://developers.google.com/speed/libraries/devguide#angularjs) e.g.
2631
- * `"//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-mocks.js"`
2632
- * * [NPM](https://www.npmjs.com/) e.g. `npm install angular-mocks@X.Y.Z`
2633
- * * [Yarn](https://yarnpkg.com) e.g. `yarn add angular-mocks@X.Y.Z`
2634
- * * [Bower](http://bower.io) e.g. `bower install angular-mocks#X.Y.Z`
2635
- * * [code.angularjs.org](https://code.angularjs.org/) (discouraged for production use) e.g.
2636
- * `"//code.angularjs.org/X.Y.Z/angular-mocks.js"`
2637
- *
2638
- * where X.Y.Z is the AngularJS version you are running.
2639
- *
2640
- * Then, configure your test runner to load `angular-mocks.js` after `angular.js`.
2641
- * This example uses <a href="http://karma-runner.github.io/">Karma</a>:
2642
- *
2643
- * ```
2644
- * config.set({
2645
- * files: [
2646
- * 'build/angular.js', // and other module files you need
2647
- * 'build/angular-mocks.js',
2648
- * '<path/to/application/files>',
2649
- * '<path/to/spec/files>'
2650
- * ]
2651
- * });
2652
- * ```
2653
- *
2654
- * Including the `angular-mocks.js` file automatically adds the `ngMock` module, so your tests
2655
- * are ready to go!
2656
- */
2657
- angular.module('ngMock', ['ng']).provider({
2658
- $browser: angular.mock.$BrowserProvider,
2659
- $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
2660
- $log: angular.mock.$LogProvider,
2661
- $interval: angular.mock.$IntervalProvider,
2662
- $rootElement: angular.mock.$RootElementProvider,
2663
- $componentController: angular.mock.$ComponentControllerProvider,
2664
- $flushPendingTasks: angular.mock.$FlushPendingTasksProvider,
2665
- $verifyNoPendingTasks: angular.mock.$VerifyNoPendingTasksProvider
2666
- }).config(['$provide', '$compileProvider', function($provide, $compileProvider) {
2667
- $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
2668
- $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
2669
- $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
2670
- $provide.decorator('$controller', createControllerDecorator($compileProvider));
2671
- $provide.decorator('$httpBackend', angular.mock.$httpBackendDecorator);
2672
- }]).info({ angularVersion: '1.8.4-local+sha.4e1bd4b90' });
2673
-
2674
- /**
2675
- * @ngdoc module
2676
- * @name ngMockE2E
2677
- * @module ngMockE2E
2678
- * @packageName angular-mocks
2679
- * @description
2680
- *
2681
- * The `ngMockE2E` is an AngularJS module which contains mocks suitable for end-to-end testing.
2682
- * Currently there is only one mock present in this module -
2683
- * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
2684
- */
2685
- angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
2686
- $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
2687
- }]).info({ angularVersion: '1.8.4-local+sha.4e1bd4b90' });
2688
-
2689
- /**
2690
- * @ngdoc service
2691
- * @name $httpBackend
2692
- * @module ngMockE2E
2693
- * @description
2694
- * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
2695
- * applications that use the {@link ng.$http $http service}.
2696
- *
2697
- * <div class="alert alert-info">
2698
- * **Note**: For fake http backend implementation suitable for unit testing please see
2699
- * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
2700
- * </div>
2701
- *
2702
- * This implementation can be used to respond with static or dynamic responses via the `when` api
2703
- * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
2704
- * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
2705
- * templates from a webserver).
2706
- *
2707
- * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
2708
- * is being developed with the real backend api replaced with a mock, it is often desirable for
2709
- * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
2710
- * templates or static files from the webserver). To configure the backend with this behavior
2711
- * use the `passThrough` request handler of `when` instead of `respond`.
2712
- *
2713
- * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
2714
- * testing. For this reason the e2e $httpBackend flushes mocked out requests
2715
- * automatically, closely simulating the behavior of the XMLHttpRequest object.
2716
- *
2717
- * To setup the application to run with this http backend, you have to create a module that depends
2718
- * on the `ngMockE2E` and your application modules and defines the fake backend:
2719
- *
2720
- * ```js
2721
- * var myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
2722
- * myAppDev.run(function($httpBackend) {
2723
- * var phones = [{name: 'phone1'}, {name: 'phone2'}];
2724
- *
2725
- * // returns the current list of phones
2726
- * $httpBackend.whenGET('/phones').respond(phones);
2727
- *
2728
- * // adds a new phone to the phones array
2729
- * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
2730
- * var phone = angular.fromJson(data);
2731
- * phones.push(phone);
2732
- * return [200, phone, {}];
2733
- * });
2734
- * $httpBackend.whenGET(/^\/templates\//).passThrough(); // Requests for templates are handled by the real server
2735
- * //...
2736
- * });
2737
- * ```
2738
- *
2739
- * Afterwards, bootstrap your app with this new module.
2740
- *
2741
- * @example
2742
- * <example name="httpbackend-e2e-testing" module="myAppE2E" deps="angular-mocks.js">
2743
- * <file name="app.js">
2744
- * var myApp = angular.module('myApp', []);
2745
- *
2746
- * myApp.controller('MainCtrl', function MainCtrl($http) {
2747
- * var ctrl = this;
2748
- *
2749
- * ctrl.phones = [];
2750
- * ctrl.newPhone = {
2751
- * name: ''
2752
- * };
2753
- *
2754
- * ctrl.getPhones = function() {
2755
- * $http.get('/phones').then(function(response) {
2756
- * ctrl.phones = response.data;
2757
- * });
2758
- * };
2759
- *
2760
- * ctrl.addPhone = function(phone) {
2761
- * $http.post('/phones', phone).then(function() {
2762
- * ctrl.newPhone = {name: ''};
2763
- * return ctrl.getPhones();
2764
- * });
2765
- * };
2766
- *
2767
- * ctrl.getPhones();
2768
- * });
2769
- * </file>
2770
- * <file name="e2e.js">
2771
- * var myAppDev = angular.module('myAppE2E', ['myApp', 'ngMockE2E']);
2772
- *
2773
- * myAppDev.run(function($httpBackend) {
2774
- * var phones = [{name: 'phone1'}, {name: 'phone2'}];
2775
- *
2776
- * // returns the current list of phones
2777
- * $httpBackend.whenGET('/phones').respond(phones);
2778
- *
2779
- * // adds a new phone to the phones array
2780
- * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
2781
- * var phone = angular.fromJson(data);
2782
- * phones.push(phone);
2783
- * return [200, phone, {}];
2784
- * });
2785
- * });
2786
- * </file>
2787
- * <file name="index.html">
2788
- * <div ng-controller="MainCtrl as $ctrl">
2789
- * <form name="newPhoneForm" ng-submit="$ctrl.addPhone($ctrl.newPhone)">
2790
- * <input type="text" ng-model="$ctrl.newPhone.name">
2791
- * <input type="submit" value="Add Phone">
2792
- * </form>
2793
- * <h1>Phones</h1>
2794
- * <ul>
2795
- * <li ng-repeat="phone in $ctrl.phones">{{phone.name}}</li>
2796
- * </ul>
2797
- * </div>
2798
- * </file>
2799
- * </example>
2800
- *
2801
- *
2802
- */
2803
-
2804
- /**
2805
- * @ngdoc method
2806
- * @name $httpBackend#when
2807
- * @module ngMockE2E
2808
- * @description
2809
- * Creates a new backend definition.
2810
- *
2811
- * @param {string} method HTTP method.
2812
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2813
- * and returns true if the url matches the current definition.
2814
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
2815
- * data string and returns true if the data is as expected.
2816
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
2817
- * object and returns true if the headers match the current definition.
2818
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2819
- * {@link ngMock.$httpBackend $httpBackend mock}.
2820
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2821
- * control how a matched request is handled. You can save this object for later use and invoke
2822
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2823
- *
2824
- * - respond –
2825
- * ```
2826
- * { function([status,] data[, headers, statusText])
2827
- * | function(function(method, url, data, headers, params)}
2828
- * ```
2829
- * – The respond method takes a set of static data to be returned or a function that can return
2830
- * an array containing response status (number), response data (Array|Object|string), response
2831
- * headers (Object), and the text for the status (string).
2832
- * - passThrough – `{function()}` – Any request matching a backend definition with
2833
- * `passThrough` handler will be passed through to the real backend (an XHR request will be made
2834
- * to the server.)
2835
- * - Both methods return the `requestHandler` object for possible overrides.
2836
- */
2837
-
2838
- /**
2839
- * @ngdoc method
2840
- * @name $httpBackend#whenGET
2841
- * @module ngMockE2E
2842
- * @description
2843
- * Creates a new backend definition for GET requests. For more info see `when()`.
2844
- *
2845
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2846
- * and returns true if the url matches the current definition.
2847
- * @param {(Object|function(Object))=} headers HTTP headers.
2848
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2849
- * {@link ngMock.$httpBackend $httpBackend mock}.
2850
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2851
- * control how a matched request is handled. You can save this object for later use and invoke
2852
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2853
- */
2854
-
2855
- /**
2856
- * @ngdoc method
2857
- * @name $httpBackend#whenHEAD
2858
- * @module ngMockE2E
2859
- * @description
2860
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
2861
- *
2862
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2863
- * and returns true if the url matches the current definition.
2864
- * @param {(Object|function(Object))=} headers HTTP headers.
2865
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2866
- * {@link ngMock.$httpBackend $httpBackend mock}.
2867
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2868
- * control how a matched request is handled. You can save this object for later use and invoke
2869
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2870
- */
2871
-
2872
- /**
2873
- * @ngdoc method
2874
- * @name $httpBackend#whenDELETE
2875
- * @module ngMockE2E
2876
- * @description
2877
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
2878
- *
2879
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2880
- * and returns true if the url matches the current definition.
2881
- * @param {(Object|function(Object))=} headers HTTP headers.
2882
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2883
- * {@link ngMock.$httpBackend $httpBackend mock}.
2884
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2885
- * control how a matched request is handled. You can save this object for later use and invoke
2886
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2887
- */
2888
-
2889
- /**
2890
- * @ngdoc method
2891
- * @name $httpBackend#whenPOST
2892
- * @module ngMockE2E
2893
- * @description
2894
- * Creates a new backend definition for POST requests. For more info see `when()`.
2895
- *
2896
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2897
- * and returns true if the url matches the current definition.
2898
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
2899
- * data string and returns true if the data is as expected.
2900
- * @param {(Object|function(Object))=} headers HTTP headers.
2901
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2902
- * {@link ngMock.$httpBackend $httpBackend mock}.
2903
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2904
- * control how a matched request is handled. You can save this object for later use and invoke
2905
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2906
- */
2907
-
2908
- /**
2909
- * @ngdoc method
2910
- * @name $httpBackend#whenPUT
2911
- * @module ngMockE2E
2912
- * @description
2913
- * Creates a new backend definition for PUT requests. For more info see `when()`.
2914
- *
2915
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2916
- * and returns true if the url matches the current definition.
2917
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
2918
- * data string and returns true if the data is as expected.
2919
- * @param {(Object|function(Object))=} headers HTTP headers.
2920
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2921
- * {@link ngMock.$httpBackend $httpBackend mock}.
2922
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2923
- * control how a matched request is handled. You can save this object for later use and invoke
2924
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2925
- */
2926
-
2927
- /**
2928
- * @ngdoc method
2929
- * @name $httpBackend#whenPATCH
2930
- * @module ngMockE2E
2931
- * @description
2932
- * Creates a new backend definition for PATCH requests. For more info see `when()`.
2933
- *
2934
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2935
- * and returns true if the url matches the current definition.
2936
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
2937
- * data string and returns true if the data is as expected.
2938
- * @param {(Object|function(Object))=} headers HTTP headers.
2939
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2940
- * {@link ngMock.$httpBackend $httpBackend mock}.
2941
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2942
- * control how a matched request is handled. You can save this object for later use and invoke
2943
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2944
- */
2945
-
2946
- /**
2947
- * @ngdoc method
2948
- * @name $httpBackend#whenJSONP
2949
- * @module ngMockE2E
2950
- * @description
2951
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
2952
- *
2953
- * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
2954
- * and returns true if the url matches the current definition.
2955
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
2956
- * {@link ngMock.$httpBackend $httpBackend mock}.
2957
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2958
- * control how a matched request is handled. You can save this object for later use and invoke
2959
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2960
- */
2961
- /**
2962
- * @ngdoc method
2963
- * @name $httpBackend#whenRoute
2964
- * @module ngMockE2E
2965
- * @description
2966
- * Creates a new backend definition that compares only with the requested route.
2967
- *
2968
- * @param {string} method HTTP method.
2969
- * @param {string} url HTTP url string that supports colon param matching.
2970
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2971
- * control how a matched request is handled. You can save this object for later use and invoke
2972
- * `respond` or `passThrough` again in order to change how a matched request is handled.
2973
- */
2974
- /**
2975
- * @ngdoc method
2976
- * @name $httpBackend#matchLatestDefinitionEnabled
2977
- * @module ngMockE2E
2978
- * @description
2979
- * This method can be used to change which mocked responses `$httpBackend` returns, when defining
2980
- * them with {@link ngMock.$httpBackend#when $httpBackend.when()} (and shortcut methods).
2981
- * By default, `$httpBackend` returns the first definition that matches. When setting
2982
- * `$http.matchLatestDefinitionEnabled(true)`, it will use the last response that matches, i.e. the
2983
- * one that was added last.
2984
- *
2985
- * ```js
2986
- * hb.when('GET', '/url1').respond(200, 'content', {});
2987
- * hb.when('GET', '/url1').respond(201, 'another', {});
2988
- * hb('GET', '/url1'); // receives "content"
2989
- *
2990
- * $http.matchLatestDefinitionEnabled(true)
2991
- * hb('GET', '/url1'); // receives "another"
2992
- *
2993
- * hb.when('GET', '/url1').respond(201, 'onemore', {});
2994
- * hb('GET', '/url1'); // receives "onemore"
2995
- * ```
2996
- *
2997
- * This is useful if a you have a default response that is overriden inside specific tests.
2998
- *
2999
- * Note that different from config methods on providers, `matchLatestDefinitionEnabled()` can be changed
3000
- * even when the application is already running.
3001
- *
3002
- * @param {Boolean=} value value to set, either `true` or `false`. Default is `false`.
3003
- * If omitted, it will return the current value.
3004
- * @return {$httpBackend|Boolean} self when used as a setter, and the current value when used
3005
- * as a getter
3006
- */
3007
- angular.mock.e2e = {};
3008
- angular.mock.e2e.$httpBackendDecorator =
3009
- ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];
3010
-
3011
-
3012
- /**
3013
- * @ngdoc type
3014
- * @name $rootScope.Scope
3015
- * @module ngMock
3016
- * @description
3017
- * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These
3018
- * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when
3019
- * `ngMock` module is loaded.
3020
- *
3021
- * In addition to all the regular `Scope` methods, the following helper methods are available:
3022
- */
3023
- angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
3024
-
3025
- var $rootScopePrototype = Object.getPrototypeOf($delegate);
3026
-
3027
- $rootScopePrototype.$countChildScopes = countChildScopes;
3028
- $rootScopePrototype.$countWatchers = countWatchers;
3029
-
3030
- return $delegate;
3031
-
3032
- // ------------------------------------------------------------------------------------------ //
3033
-
3034
- /**
3035
- * @ngdoc method
3036
- * @name $rootScope.Scope#$countChildScopes
3037
- * @module ngMock
3038
- * @this $rootScope.Scope
3039
- * @description
3040
- * Counts all the direct and indirect child scopes of the current scope.
3041
- *
3042
- * The current scope is excluded from the count. The count includes all isolate child scopes.
3043
- *
3044
- * @returns {number} Total number of child scopes.
3045
- */
3046
- function countChildScopes() {
3047
- var count = 0; // exclude the current scope
3048
- var pendingChildHeads = [this.$$childHead];
3049
- var currentScope;
3050
-
3051
- while (pendingChildHeads.length) {
3052
- currentScope = pendingChildHeads.shift();
3053
-
3054
- while (currentScope) {
3055
- count += 1;
3056
- pendingChildHeads.push(currentScope.$$childHead);
3057
- currentScope = currentScope.$$nextSibling;
3058
- }
3059
- }
3060
-
3061
- return count;
3062
- }
3063
-
3064
-
3065
- /**
3066
- * @ngdoc method
3067
- * @name $rootScope.Scope#$countWatchers
3068
- * @this $rootScope.Scope
3069
- * @module ngMock
3070
- * @description
3071
- * Counts all the watchers of direct and indirect child scopes of the current scope.
3072
- *
3073
- * The watchers of the current scope are included in the count and so are all the watchers of
3074
- * isolate child scopes.
3075
- *
3076
- * @returns {number} Total number of watchers.
3077
- */
3078
- function countWatchers() {
3079
- var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope
3080
- var pendingChildHeads = [this.$$childHead];
3081
- var currentScope;
3082
-
3083
- while (pendingChildHeads.length) {
3084
- currentScope = pendingChildHeads.shift();
3085
-
3086
- while (currentScope) {
3087
- count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
3088
- pendingChildHeads.push(currentScope.$$childHead);
3089
- currentScope = currentScope.$$nextSibling;
3090
- }
3091
- }
3092
-
3093
- return count;
3094
- }
3095
- }];
3096
-
3097
-
3098
- (function(jasmineOrMocha) {
3099
-
3100
- if (!jasmineOrMocha) {
3101
- return;
3102
- }
3103
-
3104
- var currentSpec = null,
3105
- injectorState = new InjectorState(),
3106
- annotatedFunctions = [],
3107
- wasInjectorCreated = function() {
3108
- return !!currentSpec;
3109
- };
3110
-
3111
- angular.mock.$$annotate = angular.injector.$$annotate;
3112
- angular.injector.$$annotate = function(fn) {
3113
- if (typeof fn === 'function' && !fn.$inject) {
3114
- annotatedFunctions.push(fn);
3115
- }
3116
- return angular.mock.$$annotate.apply(this, arguments);
3117
- };
3118
-
3119
- /**
3120
- * @ngdoc function
3121
- * @name angular.mock.module
3122
- * @description
3123
- *
3124
- * *NOTE*: This function is also published on window for easy access.<br>
3125
- * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
3126
- *
3127
- * This function registers a module configuration code. It collects the configuration information
3128
- * which will be used when the injector is created by {@link angular.mock.inject inject}.
3129
- *
3130
- * See {@link angular.mock.inject inject} for usage example
3131
- *
3132
- * @param {...(string|Function|Object)} fns any number of modules which are represented as string
3133
- * aliases or as anonymous module initialization functions. The modules are used to
3134
- * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
3135
- * object literal is passed each key-value pair will be registered on the module via
3136
- * {@link auto.$provide $provide}.value, the key being the string name (or token) to associate
3137
- * with the value on the injector.
3138
- */
3139
- var module = window.module = angular.mock.module = function() {
3140
- var moduleFns = Array.prototype.slice.call(arguments, 0);
3141
- return wasInjectorCreated() ? workFn() : workFn;
3142
- /////////////////////
3143
- function workFn() {
3144
- if (currentSpec.$injector) {
3145
- throw new Error('Injector already created, can not register a module!');
3146
- } else {
3147
- var fn, modules = currentSpec.$modules || (currentSpec.$modules = []);
3148
- angular.forEach(moduleFns, function(module) {
3149
- if (angular.isObject(module) && !angular.isArray(module)) {
3150
- fn = ['$provide', function($provide) {
3151
- angular.forEach(module, function(value, key) {
3152
- $provide.value(key, value);
3153
- });
3154
- }];
3155
- } else {
3156
- fn = module;
3157
- }
3158
- if (currentSpec.$providerInjector) {
3159
- currentSpec.$providerInjector.invoke(fn);
3160
- } else {
3161
- modules.push(fn);
3162
- }
3163
- });
3164
- }
3165
- }
3166
- };
3167
-
3168
- module.$$beforeAllHook = (window.before || window.beforeAll);
3169
- module.$$afterAllHook = (window.after || window.afterAll);
3170
-
3171
- // purely for testing ngMock itself
3172
- module.$$currentSpec = function(to) {
3173
- if (arguments.length === 0) return to;
3174
- currentSpec = to;
3175
- };
3176
-
3177
- /**
3178
- * @ngdoc function
3179
- * @name angular.mock.module.sharedInjector
3180
- * @description
3181
- *
3182
- * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
3183
- *
3184
- * This function ensures a single injector will be used for all tests in a given describe context.
3185
- * This contrasts with the default behaviour where a new injector is created per test case.
3186
- *
3187
- * Use sharedInjector when you want to take advantage of Jasmine's `beforeAll()`, or mocha's
3188
- * `before()` methods. Call `module.sharedInjector()` before you setup any other hooks that
3189
- * will create (i.e call `module()`) or use (i.e call `inject()`) the injector.
3190
- *
3191
- * You cannot call `sharedInjector()` from within a context already using `sharedInjector()`.
3192
- *
3193
- * ## Example
3194
- *
3195
- * Typically beforeAll is used to make many assertions about a single operation. This can
3196
- * cut down test run-time as the test setup doesn't need to be re-run, and enabling focussed
3197
- * tests each with a single assertion.
3198
- *
3199
- * ```js
3200
- * describe("Deep Thought", function() {
3201
- *
3202
- * module.sharedInjector();
3203
- *
3204
- * beforeAll(module("UltimateQuestion"));
3205
- *
3206
- * beforeAll(inject(function(DeepThought) {
3207
- * expect(DeepThought.answer).toBeUndefined();
3208
- * DeepThought.generateAnswer();
3209
- * }));
3210
- *
3211
- * it("has calculated the answer correctly", inject(function(DeepThought) {
3212
- * // Because of sharedInjector, we have access to the instance of the DeepThought service
3213
- * // that was provided to the beforeAll() hook. Therefore we can test the generated answer
3214
- * expect(DeepThought.answer).toBe(42);
3215
- * }));
3216
- *
3217
- * it("has calculated the answer within the expected time", inject(function(DeepThought) {
3218
- * expect(DeepThought.runTimeMillennia).toBeLessThan(8000);
3219
- * }));
3220
- *
3221
- * it("has double checked the answer", inject(function(DeepThought) {
3222
- * expect(DeepThought.absolutelySureItIsTheRightAnswer).toBe(true);
3223
- * }));
3224
- *
3225
- * });
3226
- *
3227
- * ```
3228
- */
3229
- module.sharedInjector = function() {
3230
- if (!(module.$$beforeAllHook && module.$$afterAllHook)) {
3231
- throw Error('sharedInjector() cannot be used unless your test runner defines beforeAll/afterAll');
3232
- }
3233
-
3234
- var initialized = false;
3235
-
3236
- module.$$beforeAllHook(/** @this */ function() {
3237
- if (injectorState.shared) {
3238
- injectorState.sharedError = Error('sharedInjector() cannot be called inside a context that has already called sharedInjector()');
3239
- throw injectorState.sharedError;
3240
- }
3241
- initialized = true;
3242
- currentSpec = this;
3243
- injectorState.shared = true;
3244
- });
3245
-
3246
- module.$$afterAllHook(function() {
3247
- if (initialized) {
3248
- injectorState = new InjectorState();
3249
- module.$$cleanup();
3250
- } else {
3251
- injectorState.sharedError = null;
3252
- }
3253
- });
3254
- };
3255
-
3256
- module.$$beforeEach = function() {
3257
- if (injectorState.shared && currentSpec && currentSpec !== this) {
3258
- var state = currentSpec;
3259
- currentSpec = this;
3260
- angular.forEach(['$injector','$modules','$providerInjector', '$injectorStrict'], function(k) {
3261
- currentSpec[k] = state[k];
3262
- state[k] = null;
3263
- });
3264
- } else {
3265
- currentSpec = this;
3266
- originalRootElement = null;
3267
- annotatedFunctions = [];
3268
- }
3269
- };
3270
-
3271
- module.$$afterEach = function() {
3272
- if (injectorState.cleanupAfterEach()) {
3273
- module.$$cleanup();
3274
- }
3275
- };
3276
-
3277
- module.$$cleanup = function() {
3278
- var injector = currentSpec.$injector;
3279
-
3280
- annotatedFunctions.forEach(function(fn) {
3281
- delete fn.$inject;
3282
- });
3283
-
3284
- currentSpec.$injector = null;
3285
- currentSpec.$modules = null;
3286
- currentSpec.$providerInjector = null;
3287
- currentSpec = null;
3288
-
3289
- if (injector) {
3290
- // Ensure `$rootElement` is instantiated, before checking `originalRootElement`
3291
- var $rootElement = injector.get('$rootElement');
3292
- var rootNode = $rootElement && $rootElement[0];
3293
- var cleanUpNodes = !originalRootElement ? [] : [originalRootElement[0]];
3294
- if (rootNode && (!originalRootElement || rootNode !== originalRootElement[0])) {
3295
- cleanUpNodes.push(rootNode);
3296
- }
3297
- angular.element.cleanData(cleanUpNodes);
3298
-
3299
- // Ensure `$destroy()` is available, before calling it
3300
- // (a mocked `$rootScope` might not implement it (or not even be an object at all))
3301
- var $rootScope = injector.get('$rootScope');
3302
- if ($rootScope && $rootScope.$destroy) $rootScope.$destroy();
3303
- }
3304
-
3305
- // clean up jquery's fragment cache
3306
- angular.forEach(angular.element.fragments, function(val, key) {
3307
- delete angular.element.fragments[key];
3308
- });
3309
-
3310
- MockXhr.$$lastInstance = null;
3311
-
3312
- angular.forEach(angular.callbacks, function(val, key) {
3313
- delete angular.callbacks[key];
3314
- });
3315
- angular.callbacks.$$counter = 0;
3316
- };
3317
-
3318
- (window.beforeEach || window.setup)(module.$$beforeEach);
3319
- (window.afterEach || window.teardown)(module.$$afterEach);
3320
-
3321
- /**
3322
- * @ngdoc function
3323
- * @name angular.mock.inject
3324
- * @description
3325
- *
3326
- * *NOTE*: This function is also published on window for easy access.<br>
3327
- * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
3328
- *
3329
- * The inject function wraps a function into an injectable function. The inject() creates new
3330
- * instance of {@link auto.$injector $injector} per test, which is then used for
3331
- * resolving references.
3332
- *
3333
- *
3334
- * ## Resolving References (Underscore Wrapping)
3335
- * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
3336
- * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
3337
- * that is declared in the scope of the `describe()` block. Since we would, most likely, want
3338
- * the variable to have the same name of the reference we have a problem, since the parameter
3339
- * to the `inject()` function would hide the outer variable.
3340
- *
3341
- * To help with this, the injected parameters can, optionally, be enclosed with underscores.
3342
- * These are ignored by the injector when the reference name is resolved.
3343
- *
3344
- * For example, the parameter `_myService_` would be resolved as the reference `myService`.
3345
- * Since it is available in the function body as `_myService_`, we can then assign it to a variable
3346
- * defined in an outer scope.
3347
- *
3348
- * ```
3349
- * // Defined out reference variable outside
3350
- * var myService;
3351
- *
3352
- * // Wrap the parameter in underscores
3353
- * beforeEach( inject( function(_myService_){
3354
- * myService = _myService_;
3355
- * }));
3356
- *
3357
- * // Use myService in a series of tests.
3358
- * it('makes use of myService', function() {
3359
- * myService.doStuff();
3360
- * });
3361
- *
3362
- * ```
3363
- *
3364
- * See also {@link angular.mock.module angular.mock.module}
3365
- *
3366
- * ## Example
3367
- * Example of what a typical jasmine tests looks like with the inject method.
3368
- * ```js
3369
- *
3370
- * angular.module('myApplicationModule', [])
3371
- * .value('mode', 'app')
3372
- * .value('version', 'v1.0.1');
3373
- *
3374
- *
3375
- * describe('MyApp', function() {
3376
- *
3377
- * // You need to load modules that you want to test,
3378
- * // it loads only the "ng" module by default.
3379
- * beforeEach(module('myApplicationModule'));
3380
- *
3381
- *
3382
- * // inject() is used to inject arguments of all given functions
3383
- * it('should provide a version', inject(function(mode, version) {
3384
- * expect(version).toEqual('v1.0.1');
3385
- * expect(mode).toEqual('app');
3386
- * }));
3387
- *
3388
- *
3389
- * // The inject and module method can also be used inside of the it or beforeEach
3390
- * it('should override a version and test the new version is injected', function() {
3391
- * // module() takes functions or strings (module aliases)
3392
- * module(function($provide) {
3393
- * $provide.value('version', 'overridden'); // override version here
3394
- * });
3395
- *
3396
- * inject(function(version) {
3397
- * expect(version).toEqual('overridden');
3398
- * });
3399
- * });
3400
- * });
3401
- *
3402
- * ```
3403
- *
3404
- * @param {...Function} fns any number of functions which will be injected using the injector.
3405
- */
3406
-
3407
-
3408
-
3409
- var ErrorAddingDeclarationLocationStack = function ErrorAddingDeclarationLocationStack(e, errorForStack) {
3410
- this.message = e.message;
3411
- this.name = e.name;
3412
- if (e.line) this.line = e.line;
3413
- if (e.sourceId) this.sourceId = e.sourceId;
3414
- if (e.stack && errorForStack)
3415
- this.stack = e.stack + '\n' + errorForStack.stack;
3416
- if (e.stackArray) this.stackArray = e.stackArray;
3417
- };
3418
- ErrorAddingDeclarationLocationStack.prototype = Error.prototype;
3419
-
3420
- window.inject = angular.mock.inject = function() {
3421
- var blockFns = Array.prototype.slice.call(arguments, 0);
3422
- var errorForStack = new Error('Declaration Location');
3423
- // IE10+ and PhanthomJS do not set stack trace information, until the error is thrown
3424
- if (!errorForStack.stack) {
3425
- try {
3426
- throw errorForStack;
3427
- } catch (e) { /* empty */ }
3428
- }
3429
- return wasInjectorCreated() ? WorkFn.call(currentSpec) : WorkFn;
3430
- /////////////////////
3431
- function WorkFn() {
3432
- var modules = currentSpec.$modules || [];
3433
- var strictDi = !!currentSpec.$injectorStrict;
3434
- modules.unshift(['$injector', function($injector) {
3435
- currentSpec.$providerInjector = $injector;
3436
- }]);
3437
- modules.unshift('ngMock');
3438
- modules.unshift('ng');
3439
- var injector = currentSpec.$injector;
3440
- if (!injector) {
3441
- if (strictDi) {
3442
- // If strictDi is enabled, annotate the providerInjector blocks
3443
- angular.forEach(modules, function(moduleFn) {
3444
- if (typeof moduleFn === 'function') {
3445
- angular.injector.$$annotate(moduleFn);
3446
- }
3447
- });
3448
- }
3449
- injector = currentSpec.$injector = angular.injector(modules, strictDi);
3450
- currentSpec.$injectorStrict = strictDi;
3451
- }
3452
- for (var i = 0, ii = blockFns.length; i < ii; i++) {
3453
- if (currentSpec.$injectorStrict) {
3454
- // If the injector is strict / strictDi, and the spec wants to inject using automatic
3455
- // annotation, then annotate the function here.
3456
- injector.annotate(blockFns[i]);
3457
- }
3458
- try {
3459
- injector.invoke(blockFns[i] || angular.noop, this);
3460
- } catch (e) {
3461
- if (e.stack && errorForStack) {
3462
- throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
3463
- }
3464
- throw e;
3465
- } finally {
3466
- errorForStack = null;
3467
- }
3468
- }
3469
- }
3470
- };
3471
-
3472
-
3473
- angular.mock.inject.strictDi = function(value) {
3474
- value = arguments.length ? !!value : true;
3475
- return wasInjectorCreated() ? workFn() : workFn;
3476
-
3477
- function workFn() {
3478
- if (value !== currentSpec.$injectorStrict) {
3479
- if (currentSpec.$injector) {
3480
- throw new Error('Injector already created, can not modify strict annotations');
3481
- } else {
3482
- currentSpec.$injectorStrict = value;
3483
- }
3484
- }
3485
- }
3486
- };
3487
-
3488
- function InjectorState() {
3489
- this.shared = false;
3490
- this.sharedError = null;
3491
-
3492
- this.cleanupAfterEach = function() {
3493
- return !this.shared || this.sharedError;
3494
- };
3495
- }
3496
- })(window.jasmine || window.mocha);
3497
-
3498
- 'use strict';
3499
-
3500
- (function() {
3501
- /**
3502
- * @ngdoc function
3503
- * @name browserTrigger
3504
- * @description
3505
- *
3506
- * This is a global (window) function that is only available when the {@link ngMock} module is
3507
- * included.
3508
- *
3509
- * It can be used to trigger a native browser event on an element, which is useful for unit testing.
3510
- *
3511
- *
3512
- * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement
3513
- * @param {string=} eventType Optional event type. If none is specified, the function tries
3514
- * to determine the right event type for the element, e.g. `change` for
3515
- * `input[text]`.
3516
- * @param {Object=} eventData An optional object which contains additional event data that is used
3517
- * when creating the event:
3518
- *
3519
- * - `bubbles`: [Event.bubbles](https://developer.mozilla.org/docs/Web/API/Event/bubbles).
3520
- * Not applicable to all events.
3521
- *
3522
- * - `cancelable`: [Event.cancelable](https://developer.mozilla.org/docs/Web/API/Event/cancelable).
3523
- * Not applicable to all events.
3524
- *
3525
- * - `charcode`: [charCode](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/charcode)
3526
- * for keyboard events (keydown, keypress, and keyup).
3527
- *
3528
- * - `data`: [data](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent/data) for
3529
- * [CompositionEvents](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent).
3530
- *
3531
- * - `elapsedTime`: the elapsedTime for
3532
- * [TransitionEvent](https://developer.mozilla.org/docs/Web/API/TransitionEvent)
3533
- * and [AnimationEvent](https://developer.mozilla.org/docs/Web/API/AnimationEvent).
3534
- *
3535
- * - `keycode`: [keyCode](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/keycode)
3536
- * for keyboard events (keydown, keypress, and keyup).
3537
- *
3538
- * - `keys`: an array of possible modifier keys (ctrl, alt, shift, meta) for
3539
- * [MouseEvent](https://developer.mozilla.org/docs/Web/API/MouseEvent) and
3540
- * keyboard events (keydown, keypress, and keyup).
3541
- *
3542
- * - `relatedTarget`: the
3543
- * [relatedTarget](https://developer.mozilla.org/docs/Web/API/MouseEvent/relatedTarget)
3544
- * for [MouseEvent](https://developer.mozilla.org/docs/Web/API/MouseEvent).
3545
- *
3546
- * - `which`: [which](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/which)
3547
- * for keyboard events (keydown, keypress, and keyup).
3548
- *
3549
- * - `x`: x-coordinates for [MouseEvent](https://developer.mozilla.org/docs/Web/API/MouseEvent)
3550
- * and [TouchEvent](https://developer.mozilla.org/docs/Web/API/TouchEvent).
3551
- *
3552
- * - `y`: y-coordinates for [MouseEvent](https://developer.mozilla.org/docs/Web/API/MouseEvent)
3553
- * and [TouchEvent](https://developer.mozilla.org/docs/Web/API/TouchEvent).
3554
- *
3555
- */
3556
- window.browserTrigger = function browserTrigger(element, eventType, eventData) {
3557
- if (element && !element.nodeName) element = element[0];
3558
- if (!element) return;
3559
-
3560
- eventData = eventData || {};
3561
- var relatedTarget = eventData.relatedTarget || element;
3562
- var keys = eventData.keys;
3563
- var x = eventData.x;
3564
- var y = eventData.y;
3565
-
3566
- var inputType = (element.type) ? element.type.toLowerCase() : null,
3567
- nodeName = element.nodeName.toLowerCase();
3568
- if (!eventType) {
3569
- eventType = {
3570
- 'text': 'change',
3571
- 'textarea': 'change',
3572
- 'hidden': 'change',
3573
- 'password': 'change',
3574
- 'button': 'click',
3575
- 'submit': 'click',
3576
- 'reset': 'click',
3577
- 'image': 'click',
3578
- 'checkbox': 'click',
3579
- 'radio': 'click',
3580
- 'select-one': 'change',
3581
- 'select-multiple': 'change',
3582
- '_default_': 'click'
3583
- }[inputType || '_default_'];
3584
- }
3585
-
3586
- if (nodeName === 'option') {
3587
- element.parentNode.value = element.value;
3588
- element = element.parentNode;
3589
- eventType = 'change';
3590
- }
3591
-
3592
- keys = keys || [];
3593
- function pressed(key) {
3594
- return keys.indexOf(key) !== -1;
3595
- }
3596
-
3597
- var evnt;
3598
- if (/transitionend/.test(eventType)) {
3599
- if (window.WebKitTransitionEvent) {
3600
- evnt = new window.WebKitTransitionEvent(eventType, eventData);
3601
- evnt.initEvent(eventType, eventData.bubbles, true);
3602
- } else {
3603
- try {
3604
- evnt = new window.TransitionEvent(eventType, eventData);
3605
- } catch (e) {
3606
- evnt = window.document.createEvent('TransitionEvent');
3607
- evnt.initTransitionEvent(eventType, eventData.bubbles, null, null, eventData.elapsedTime || 0);
3608
- }
3609
- }
3610
- } else if (/animationend/.test(eventType)) {
3611
- if (window.WebKitAnimationEvent) {
3612
- evnt = new window.WebKitAnimationEvent(eventType, eventData);
3613
- evnt.initEvent(eventType, eventData.bubbles, true);
3614
- } else {
3615
- try {
3616
- evnt = new window.AnimationEvent(eventType, eventData);
3617
- } catch (e) {
3618
- evnt = window.document.createEvent('AnimationEvent');
3619
- evnt.initAnimationEvent(eventType, eventData.bubbles, null, null, eventData.elapsedTime || 0);
3620
- }
3621
- }
3622
- } else if (/touch/.test(eventType) && supportsTouchEvents()) {
3623
- evnt = createTouchEvent(element, eventType, x, y);
3624
- } else if (/key/.test(eventType)) {
3625
- evnt = window.document.createEvent('Events');
3626
- evnt.initEvent(eventType, eventData.bubbles, eventData.cancelable);
3627
- evnt.view = window;
3628
- evnt.ctrlKey = pressed('ctrl');
3629
- evnt.altKey = pressed('alt');
3630
- evnt.shiftKey = pressed('shift');
3631
- evnt.metaKey = pressed('meta');
3632
- evnt.keyCode = eventData.keyCode;
3633
- evnt.charCode = eventData.charCode;
3634
- evnt.which = eventData.which;
3635
- } else if (/composition/.test(eventType)) {
3636
- try {
3637
- evnt = new window.CompositionEvent(eventType, {
3638
- data: eventData.data
3639
- });
3640
- } catch (e) {
3641
- // Support: IE9+
3642
- evnt = window.document.createEvent('CompositionEvent', {});
3643
- evnt.initCompositionEvent(
3644
- eventType,
3645
- eventData.bubbles,
3646
- eventData.cancelable,
3647
- window,
3648
- eventData.data,
3649
- null
3650
- );
3651
- }
3652
-
3653
- } else {
3654
- evnt = window.document.createEvent('MouseEvents');
3655
- x = x || 0;
3656
- y = y || 0;
3657
- evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'),
3658
- pressed('alt'), pressed('shift'), pressed('meta'), 0, relatedTarget);
3659
- }
3660
-
3661
- /* we're unable to change the timeStamp value directly so this
3662
- * is only here to allow for testing where the timeStamp value is
3663
- * read */
3664
- evnt.$manualTimeStamp = eventData.timeStamp;
3665
-
3666
- if (!evnt) return;
3667
-
3668
- if (!eventData.bubbles || supportsEventBubblingInDetachedTree() || isAttachedToDocument(element)) {
3669
- return element.dispatchEvent(evnt);
3670
- } else {
3671
- triggerForPath(element, evnt);
3672
- }
3673
- };
3674
-
3675
- function supportsTouchEvents() {
3676
- if ('_cached' in supportsTouchEvents) {
3677
- return supportsTouchEvents._cached;
3678
- }
3679
- if (!window.document.createTouch || !window.document.createTouchList) {
3680
- supportsTouchEvents._cached = false;
3681
- return false;
3682
- }
3683
- try {
3684
- window.document.createEvent('TouchEvent');
3685
- } catch (e) {
3686
- supportsTouchEvents._cached = false;
3687
- return false;
3688
- }
3689
- supportsTouchEvents._cached = true;
3690
- return true;
3691
- }
3692
-
3693
- function createTouchEvent(element, eventType, x, y) {
3694
- var evnt = new window.Event(eventType);
3695
- x = x || 0;
3696
- y = y || 0;
3697
-
3698
- var touch = window.document.createTouch(window, element, Date.now(), x, y, x, y);
3699
- var touches = window.document.createTouchList(touch);
3700
-
3701
- evnt.touches = touches;
3702
-
3703
- return evnt;
3704
- }
3705
-
3706
- function supportsEventBubblingInDetachedTree() {
3707
- if ('_cached' in supportsEventBubblingInDetachedTree) {
3708
- return supportsEventBubblingInDetachedTree._cached;
3709
- }
3710
- supportsEventBubblingInDetachedTree._cached = false;
3711
- var doc = window.document;
3712
- if (doc) {
3713
- var parent = doc.createElement('div'),
3714
- child = parent.cloneNode();
3715
- parent.appendChild(child);
3716
- parent.addEventListener('e', function() {
3717
- supportsEventBubblingInDetachedTree._cached = true;
3718
- });
3719
- var evnt = window.document.createEvent('Events');
3720
- evnt.initEvent('e', true, true);
3721
- child.dispatchEvent(evnt);
3722
- }
3723
- return supportsEventBubblingInDetachedTree._cached;
3724
- }
3725
-
3726
- function triggerForPath(element, evnt) {
3727
- var stop = false;
3728
-
3729
- var _stopPropagation = evnt.stopPropagation;
3730
- evnt.stopPropagation = function() {
3731
- stop = true;
3732
- _stopPropagation.apply(evnt, arguments);
3733
- };
3734
- patchEventTargetForBubbling(evnt, element);
3735
- do {
3736
- element.dispatchEvent(evnt);
3737
- // eslint-disable-next-line no-unmodified-loop-condition
3738
- } while (!stop && (element = element.parentNode));
3739
- }
3740
-
3741
- function patchEventTargetForBubbling(event, target) {
3742
- event._target = target;
3743
- Object.defineProperty(event, 'target', {get: function() { return this._target;}});
3744
- }
3745
-
3746
- function isAttachedToDocument(element) {
3747
- while ((element = element.parentNode)) {
3748
- if (element === window) {
3749
- return true;
3750
- }
3751
- }
3752
- return false;
3753
- }
3754
- })();
3755
-
3756
-
3757
- })(window, window.angular);