rails_karma 0.1.0

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