angularjs-rails-resource 1.0.0.pre.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bower.json +1 -1
- data/lib/angularjs-rails-resource/version.rb +1 -1
- data/package.json +1 -1
- data/test/lib/angular/angular-cookies.js +24 -6
- data/test/lib/angular/angular-loader.js +138 -32
- data/test/lib/angular/angular-mocks.js +666 -396
- data/test/lib/angular/angular-route.js +911 -0
- data/test/lib/angular/angular-sanitize.js +212 -148
- data/test/lib/angular/angular-scenario.js +17060 -12378
- data/test/lib/angular/angular.js +10869 -6644
- metadata +6 -14
- data/test/lib/angular/angular-bootstrap-prettify.js +0 -1838
- data/test/lib/angular/angular-bootstrap.js +0 -167
- data/test/lib/angular/angular-locale_en-us.js +0 -4
- data/test/lib/angular/angular-mobile.js +0 -267
- data/test/lib/angular/angular-resource.js +0 -521
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3bf9757cba16ef593b4a0b823c29d61f47910d5
|
4
|
+
data.tar.gz: 62a2d930c231b2e6a54dbeb718dca18eb4c2ff9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 610c9c4762c53128e74996a87d27c83d59ce9a186d093f614092673d084c9cf441e5cb6107a08e8599b5ae384f900e577c8c9c3ee9d39b714f75f6d2524e055e
|
7
|
+
data.tar.gz: 59ca8304a0d22e07a7fc00bbf1552fdb28d6da859207dc74276762838441b1f43ef97cc3e3e53777dc2d842d7b22652c673d685e615325527241dcdbd05b1914
|
data/bower.json
CHANGED
data/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "angularjs-rails-resource",
|
3
3
|
"description" : "A resource factory inspired by $resource from AngularJS",
|
4
|
-
"version": "1.0.0
|
4
|
+
"version": "1.0.0",
|
5
5
|
"main" : "dist/angularjs-rails-resource.min.js",
|
6
6
|
"homepage" : "https://github.com/FineLinePrototyping/angularjs-rails-resource.git",
|
7
7
|
"author" : "",
|
@@ -1,14 +1,25 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.2.6
|
3
|
+
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
6
|
-
(function(window, angular, undefined) {
|
7
|
-
'use strict';
|
6
|
+
(function(window, angular, undefined) {'use strict';
|
8
7
|
|
9
8
|
/**
|
10
9
|
* @ngdoc overview
|
11
10
|
* @name ngCookies
|
11
|
+
* @description
|
12
|
+
*
|
13
|
+
* # ngCookies
|
14
|
+
*
|
15
|
+
* The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
|
16
|
+
*
|
17
|
+
* {@installModule cookies}
|
18
|
+
*
|
19
|
+
* <div doc-module-components="ngCookies"></div>
|
20
|
+
*
|
21
|
+
* See {@link ngCookies.$cookies `$cookies`} and
|
22
|
+
* {@link ngCookies.$cookieStore `$cookieStore`} for usage.
|
12
23
|
*/
|
13
24
|
|
14
25
|
|
@@ -24,6 +35,8 @@ angular.module('ngCookies', ['ng']).
|
|
24
35
|
* Only a simple Object is exposed and by adding or removing properties to/from
|
25
36
|
* this object, new cookies are created/deleted at the end of current $eval.
|
26
37
|
*
|
38
|
+
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
39
|
+
*
|
27
40
|
* @example
|
28
41
|
<doc:example>
|
29
42
|
<doc:source>
|
@@ -68,7 +81,8 @@ angular.module('ngCookies', ['ng']).
|
|
68
81
|
|
69
82
|
|
70
83
|
/**
|
71
|
-
* Pushes all the cookies from the service to the browser and verifies if all cookies were
|
84
|
+
* Pushes all the cookies from the service to the browser and verifies if all cookies were
|
85
|
+
* stored.
|
72
86
|
*/
|
73
87
|
function push() {
|
74
88
|
var name,
|
@@ -128,6 +142,9 @@ angular.module('ngCookies', ['ng']).
|
|
128
142
|
* Provides a key-value (string-object) storage, that is backed by session cookies.
|
129
143
|
* Objects put or retrieved from this storage are automatically serialized or
|
130
144
|
* deserialized by angular's toJson/fromJson.
|
145
|
+
*
|
146
|
+
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
147
|
+
*
|
131
148
|
* @example
|
132
149
|
*/
|
133
150
|
factory('$cookieStore', ['$cookies', function($cookies) {
|
@@ -145,7 +162,8 @@ angular.module('ngCookies', ['ng']).
|
|
145
162
|
* @returns {Object} Deserialized cookie value.
|
146
163
|
*/
|
147
164
|
get: function(key) {
|
148
|
-
|
165
|
+
var value = $cookies[key];
|
166
|
+
return value ? angular.fromJson(value) : value;
|
149
167
|
},
|
150
168
|
|
151
169
|
/**
|
@@ -1,10 +1,84 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.2.6
|
3
|
+
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
6
6
|
|
7
|
-
(
|
7
|
+
(function() {'use strict';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @description
|
11
|
+
*
|
12
|
+
* This object provides a utility for producing rich Error messages within
|
13
|
+
* Angular. It can be called as follows:
|
14
|
+
*
|
15
|
+
* var exampleMinErr = minErr('example');
|
16
|
+
* throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
|
17
|
+
*
|
18
|
+
* The above creates an instance of minErr in the example namespace. The
|
19
|
+
* resulting error will have a namespaced error code of example.one. The
|
20
|
+
* resulting error will replace {0} with the value of foo, and {1} with the
|
21
|
+
* value of bar. The object is not restricted in the number of arguments it can
|
22
|
+
* take.
|
23
|
+
*
|
24
|
+
* If fewer arguments are specified than necessary for interpolation, the extra
|
25
|
+
* interpolation markers will be preserved in the final string.
|
26
|
+
*
|
27
|
+
* Since data will be parsed statically during a build step, some restrictions
|
28
|
+
* are applied with respect to how minErr instances are created and called.
|
29
|
+
* Instances should have names of the form namespaceMinErr for a minErr created
|
30
|
+
* using minErr('namespace') . Error codes, namespaces and template strings
|
31
|
+
* should all be static strings, not variables or general expressions.
|
32
|
+
*
|
33
|
+
* @param {string} module The namespace to use for the new minErr instance.
|
34
|
+
* @returns {function(string, string, ...): Error} instance
|
35
|
+
*/
|
36
|
+
|
37
|
+
function minErr(module) {
|
38
|
+
return function () {
|
39
|
+
var code = arguments[0],
|
40
|
+
prefix = '[' + (module ? module + ':' : '') + code + '] ',
|
41
|
+
template = arguments[1],
|
42
|
+
templateArgs = arguments,
|
43
|
+
stringify = function (obj) {
|
44
|
+
if (typeof obj === 'function') {
|
45
|
+
return obj.toString().replace(/ \{[\s\S]*$/, '');
|
46
|
+
} else if (typeof obj === 'undefined') {
|
47
|
+
return 'undefined';
|
48
|
+
} else if (typeof obj !== 'string') {
|
49
|
+
return JSON.stringify(obj);
|
50
|
+
}
|
51
|
+
return obj;
|
52
|
+
},
|
53
|
+
message, i;
|
54
|
+
|
55
|
+
message = prefix + template.replace(/\{\d+\}/g, function (match) {
|
56
|
+
var index = +match.slice(1, -1), arg;
|
57
|
+
|
58
|
+
if (index + 2 < templateArgs.length) {
|
59
|
+
arg = templateArgs[index + 2];
|
60
|
+
if (typeof arg === 'function') {
|
61
|
+
return arg.toString().replace(/ ?\{[\s\S]*$/, '');
|
62
|
+
} else if (typeof arg === 'undefined') {
|
63
|
+
return 'undefined';
|
64
|
+
} else if (typeof arg !== 'string') {
|
65
|
+
return toJson(arg);
|
66
|
+
}
|
67
|
+
return arg;
|
68
|
+
}
|
69
|
+
return match;
|
70
|
+
});
|
71
|
+
|
72
|
+
message = message + '\nhttp://errors.angularjs.org/1.2.6/' +
|
73
|
+
(module ? module + '/' : '') + code;
|
74
|
+
for (i = 2; i < arguments.length; i++) {
|
75
|
+
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
|
76
|
+
encodeURIComponent(stringify(arguments[i]));
|
77
|
+
}
|
78
|
+
|
79
|
+
return new Error(message);
|
80
|
+
};
|
81
|
+
}
|
8
82
|
|
9
83
|
/**
|
10
84
|
* @ngdoc interface
|
@@ -16,11 +90,19 @@
|
|
16
90
|
|
17
91
|
function setupModuleLoader(window) {
|
18
92
|
|
93
|
+
var $injectorMinErr = minErr('$injector');
|
94
|
+
var ngMinErr = minErr('ng');
|
95
|
+
|
19
96
|
function ensure(obj, name, factory) {
|
20
97
|
return obj[name] || (obj[name] = factory());
|
21
98
|
}
|
22
99
|
|
23
|
-
|
100
|
+
var angular = ensure(window, 'angular', Object);
|
101
|
+
|
102
|
+
// We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
|
103
|
+
angular.$$minErr = angular.$$minErr || minErr;
|
104
|
+
|
105
|
+
return ensure(angular, 'module', function() {
|
24
106
|
/** @type {Object.<string, angular.Module>} */
|
25
107
|
var modules = {};
|
26
108
|
|
@@ -29,15 +111,19 @@ function setupModuleLoader(window) {
|
|
29
111
|
* @name angular.module
|
30
112
|
* @description
|
31
113
|
*
|
32
|
-
* The `angular.module` is a global place for creating and
|
33
|
-
* modules
|
114
|
+
* The `angular.module` is a global place for creating, registering and retrieving Angular
|
115
|
+
* modules.
|
116
|
+
* All modules (angular core or 3rd party) that should be available to an application must be
|
34
117
|
* registered using this mechanism.
|
35
118
|
*
|
119
|
+
* When passed two or more arguments, a new module is created. If passed only one argument, an
|
120
|
+
* existing module (the name passed as the first argument to `module`) is retrieved.
|
121
|
+
*
|
36
122
|
*
|
37
123
|
* # Module
|
38
124
|
*
|
39
|
-
* A module is a
|
40
|
-
* is used to configure the {@link AUTO.$injector $injector}.
|
125
|
+
* A module is a collection of services, directives, filters, and configuration information.
|
126
|
+
* `angular.module` is used to configure the {@link AUTO.$injector $injector}.
|
41
127
|
*
|
42
128
|
* <pre>
|
43
129
|
* // Create a new module
|
@@ -48,7 +134,6 @@ function setupModuleLoader(window) {
|
|
48
134
|
*
|
49
135
|
* // configure existing services inside initialization blocks.
|
50
136
|
* myModule.config(function($locationProvider) {
|
51
|
-
'use strict';
|
52
137
|
* // Configure existing providers
|
53
138
|
* $locationProvider.hashPrefix('!');
|
54
139
|
* });
|
@@ -65,19 +150,28 @@ function setupModuleLoader(window) {
|
|
65
150
|
* {@link angular.bootstrap} to simplify this process for you.
|
66
151
|
*
|
67
152
|
* @param {!string} name The name of the module to create or retrieve.
|
68
|
-
* @param {Array.<string>=} requires If specified then new module is being created. If
|
69
|
-
* the module is being retrieved for further configuration.
|
153
|
+
* @param {Array.<string>=} requires If specified then new module is being created. If
|
154
|
+
* unspecified then the the module is being retrieved for further configuration.
|
70
155
|
* @param {Function} configFn Optional configuration function for the module. Same as
|
71
|
-
* {@link angular.Module#
|
156
|
+
* {@link angular.Module#methods_config Module#config()}.
|
72
157
|
* @returns {module} new module with the {@link angular.Module} api.
|
73
158
|
*/
|
74
159
|
return function module(name, requires, configFn) {
|
160
|
+
var assertNotHasOwnProperty = function(name, context) {
|
161
|
+
if (name === 'hasOwnProperty') {
|
162
|
+
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
assertNotHasOwnProperty(name, 'module');
|
75
167
|
if (requires && modules.hasOwnProperty(name)) {
|
76
168
|
modules[name] = null;
|
77
169
|
}
|
78
170
|
return ensure(modules, name, function() {
|
79
171
|
if (!requires) {
|
80
|
-
throw
|
172
|
+
throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
|
173
|
+
"the module name or forgot to load it. If registering a module ensure that you " +
|
174
|
+
"specify the dependencies as the second argument.", name);
|
81
175
|
}
|
82
176
|
|
83
177
|
/** @type {!Array.<Array.<*>>} */
|
@@ -100,7 +194,8 @@ function setupModuleLoader(window) {
|
|
100
194
|
* @propertyOf angular.Module
|
101
195
|
* @returns {Array.<string>} List of module names which must be loaded before this module.
|
102
196
|
* @description
|
103
|
-
* Holds the list of modules which the injector will load before the current module is
|
197
|
+
* Holds the list of modules which the injector will load before the current module is
|
198
|
+
* loaded.
|
104
199
|
*/
|
105
200
|
requires: requires,
|
106
201
|
|
@@ -119,7 +214,8 @@ function setupModuleLoader(window) {
|
|
119
214
|
* @name angular.Module#provider
|
120
215
|
* @methodOf angular.Module
|
121
216
|
* @param {string} name service name
|
122
|
-
* @param {Function} providerType Construction function for creating new instance of the
|
217
|
+
* @param {Function} providerType Construction function for creating new instance of the
|
218
|
+
* service.
|
123
219
|
* @description
|
124
220
|
* See {@link AUTO.$provide#provider $provide.provider()}.
|
125
221
|
*/
|
@@ -175,27 +271,34 @@ function setupModuleLoader(window) {
|
|
175
271
|
* @name angular.Module#animation
|
176
272
|
* @methodOf angular.Module
|
177
273
|
* @param {string} name animation name
|
178
|
-
* @param {Function} animationFactory Factory function for creating new instance of an
|
274
|
+
* @param {Function} animationFactory Factory function for creating new instance of an
|
275
|
+
* animation.
|
179
276
|
* @description
|
180
277
|
*
|
181
|
-
*
|
182
|
-
*
|
278
|
+
* **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
|
279
|
+
*
|
280
|
+
*
|
281
|
+
* Defines an animation hook that can be later used with
|
282
|
+
* {@link ngAnimate.$animate $animate} service and directives that use this service.
|
283
|
+
*
|
183
284
|
* <pre>
|
184
|
-
* module.animation('animation-name', function($inject1, $inject2) {
|
285
|
+
* module.animation('.animation-name', function($inject1, $inject2) {
|
185
286
|
* return {
|
186
|
-
*
|
187
|
-
*
|
188
|
-
*
|
189
|
-
*
|
190
|
-
*
|
287
|
+
* eventName : function(element, done) {
|
288
|
+
* //code to run the animation
|
289
|
+
* //once complete, then run done()
|
290
|
+
* return function cancellationFunction(element) {
|
291
|
+
* //code to cancel the animation
|
292
|
+
* }
|
293
|
+
* }
|
191
294
|
* }
|
192
295
|
* })
|
193
296
|
* </pre>
|
194
297
|
*
|
195
|
-
* See {@link
|
196
|
-
* {@link
|
298
|
+
* See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
|
299
|
+
* {@link ngAnimate ngAnimate module} for more information.
|
197
300
|
*/
|
198
|
-
animation: invokeLater('$
|
301
|
+
animation: invokeLater('$animateProvider', 'register'),
|
199
302
|
|
200
303
|
/**
|
201
304
|
* @ngdoc method
|
@@ -212,7 +315,8 @@ function setupModuleLoader(window) {
|
|
212
315
|
* @ngdoc method
|
213
316
|
* @name angular.Module#controller
|
214
317
|
* @methodOf angular.Module
|
215
|
-
* @param {string} name Controller name
|
318
|
+
* @param {string|Object} name Controller name, or an object map of controllers where the
|
319
|
+
* keys are the names and the values are the constructors.
|
216
320
|
* @param {Function} constructor Controller constructor function.
|
217
321
|
* @description
|
218
322
|
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
|
@@ -223,11 +327,12 @@ function setupModuleLoader(window) {
|
|
223
327
|
* @ngdoc method
|
224
328
|
* @name angular.Module#directive
|
225
329
|
* @methodOf angular.Module
|
226
|
-
* @param {string} name
|
330
|
+
* @param {string|Object} name Directive name, or an object map of directives where the
|
331
|
+
* keys are the names and the values are the factories.
|
227
332
|
* @param {Function} directiveFactory Factory function for creating new instance of
|
228
333
|
* directives.
|
229
334
|
* @description
|
230
|
-
* See {@link ng.$compileProvider#
|
335
|
+
* See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}.
|
231
336
|
*/
|
232
337
|
directive: invokeLater('$compileProvider', 'directive'),
|
233
338
|
|
@@ -274,7 +379,7 @@ function setupModuleLoader(window) {
|
|
274
379
|
return function() {
|
275
380
|
invokeQueue[insertMethod || 'push']([provider, method, arguments]);
|
276
381
|
return moduleInstance;
|
277
|
-
}
|
382
|
+
};
|
278
383
|
}
|
279
384
|
});
|
280
385
|
};
|
@@ -282,7 +387,8 @@ function setupModuleLoader(window) {
|
|
282
387
|
|
283
388
|
}
|
284
389
|
|
285
|
-
|
390
|
+
setupModuleLoader(window);
|
391
|
+
})(window);
|
286
392
|
|
287
393
|
/**
|
288
394
|
* Closure compiler type information
|
@@ -1,10 +1,11 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.2.6
|
3
|
+
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
|
-
*
|
6
|
-
* TODO(vojta): wrap whole file into closure during build
|
7
5
|
*/
|
6
|
+
(function(window, angular, undefined) {
|
7
|
+
|
8
|
+
'use strict';
|
8
9
|
|
9
10
|
/**
|
10
11
|
* @ngdoc overview
|
@@ -29,7 +30,7 @@ angular.mock = {};
|
|
29
30
|
* that there are several helper methods available which can be used in tests.
|
30
31
|
*/
|
31
32
|
angular.mock.$BrowserProvider = function() {
|
32
|
-
this.$get = function(){
|
33
|
+
this.$get = function() {
|
33
34
|
return new angular.mock.$Browser();
|
34
35
|
};
|
35
36
|
};
|
@@ -75,6 +76,13 @@ angular.mock.$Browser = function() {
|
|
75
76
|
};
|
76
77
|
|
77
78
|
|
79
|
+
/**
|
80
|
+
* @name ngMock.$browser#defer.now
|
81
|
+
* @propertyOf ngMock.$browser
|
82
|
+
*
|
83
|
+
* @description
|
84
|
+
* Current milliseconds mock time.
|
85
|
+
*/
|
78
86
|
self.defer.now = 0;
|
79
87
|
|
80
88
|
|
@@ -110,7 +118,7 @@ angular.mock.$Browser = function() {
|
|
110
118
|
if (self.deferredFns.length) {
|
111
119
|
self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
|
112
120
|
} else {
|
113
|
-
throw Error('No deferred tasks to be flushed');
|
121
|
+
throw new Error('No deferred tasks to be flushed');
|
114
122
|
}
|
115
123
|
}
|
116
124
|
|
@@ -118,13 +126,6 @@ angular.mock.$Browser = function() {
|
|
118
126
|
self.deferredFns.shift().fn();
|
119
127
|
}
|
120
128
|
};
|
121
|
-
/**
|
122
|
-
* @name ngMock.$browser#defer.now
|
123
|
-
* @propertyOf ngMock.$browser
|
124
|
-
*
|
125
|
-
* @description
|
126
|
-
* Current milliseconds mock time.
|
127
|
-
*/
|
128
129
|
|
129
130
|
self.$$baseHref = '';
|
130
131
|
self.baseHref = function() {
|
@@ -162,7 +163,7 @@ angular.mock.$Browser.prototype = {
|
|
162
163
|
|
163
164
|
cookies: function(name, value) {
|
164
165
|
if (name) {
|
165
|
-
if (value
|
166
|
+
if (angular.isUndefined(value)) {
|
166
167
|
delete this.cookieHash[name];
|
167
168
|
} else {
|
168
169
|
if (angular.isString(value) && //strings only
|
@@ -190,8 +191,8 @@ angular.mock.$Browser.prototype = {
|
|
190
191
|
* @name ngMock.$exceptionHandlerProvider
|
191
192
|
*
|
192
193
|
* @description
|
193
|
-
* Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
|
194
|
-
* into the `$exceptionHandler`.
|
194
|
+
* Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
|
195
|
+
* passed into the `$exceptionHandler`.
|
195
196
|
*/
|
196
197
|
|
197
198
|
/**
|
@@ -241,13 +242,13 @@ angular.mock.$ExceptionHandlerProvider = function() {
|
|
241
242
|
*
|
242
243
|
* @param {string} mode Mode of operation, defaults to `rethrow`.
|
243
244
|
*
|
244
|
-
* - `rethrow`: If any errors are
|
245
|
+
* - `rethrow`: If any errors are passed into the handler in tests, it typically
|
245
246
|
* means that there is a bug in the application or test, so this mock will
|
246
247
|
* make these tests fail.
|
247
|
-
* - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
|
248
|
-
* array of errors in `$exceptionHandler.errors`, to allow later
|
249
|
-
* See {@link ngMock.$log#assertEmpty assertEmpty()} and
|
250
|
-
*
|
248
|
+
* - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
|
249
|
+
* mode stores an array of errors in `$exceptionHandler.errors`, to allow later
|
250
|
+
* assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
|
251
|
+
* {@link ngMock.$log#reset reset()}
|
251
252
|
*/
|
252
253
|
this.mode = function(mode) {
|
253
254
|
switch(mode) {
|
@@ -270,7 +271,7 @@ angular.mock.$ExceptionHandlerProvider = function() {
|
|
270
271
|
handler.errors = errors;
|
271
272
|
break;
|
272
273
|
default:
|
273
|
-
throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
|
274
|
+
throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
|
274
275
|
}
|
275
276
|
};
|
276
277
|
|
@@ -293,18 +294,32 @@ angular.mock.$ExceptionHandlerProvider = function() {
|
|
293
294
|
*
|
294
295
|
*/
|
295
296
|
angular.mock.$LogProvider = function() {
|
297
|
+
var debug = true;
|
296
298
|
|
297
299
|
function concat(array1, array2, index) {
|
298
300
|
return array1.concat(Array.prototype.slice.call(array2, index));
|
299
301
|
}
|
300
302
|
|
303
|
+
this.debugEnabled = function(flag) {
|
304
|
+
if (angular.isDefined(flag)) {
|
305
|
+
debug = flag;
|
306
|
+
return this;
|
307
|
+
} else {
|
308
|
+
return debug;
|
309
|
+
}
|
310
|
+
};
|
301
311
|
|
302
312
|
this.$get = function () {
|
303
313
|
var $log = {
|
304
314
|
log: function() { $log.log.logs.push(concat([], arguments, 0)); },
|
305
315
|
warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
|
306
316
|
info: function() { $log.info.logs.push(concat([], arguments, 0)); },
|
307
|
-
error: function() { $log.error.logs.push(concat([], arguments, 0)); }
|
317
|
+
error: function() { $log.error.logs.push(concat([], arguments, 0)); },
|
318
|
+
debug: function() {
|
319
|
+
if (debug) {
|
320
|
+
$log.debug.logs.push(concat([], arguments, 0));
|
321
|
+
}
|
322
|
+
}
|
308
323
|
};
|
309
324
|
|
310
325
|
/**
|
@@ -322,36 +337,75 @@ angular.mock.$LogProvider = function() {
|
|
322
337
|
* @propertyOf ngMock.$log
|
323
338
|
*
|
324
339
|
* @description
|
325
|
-
* Array of logged
|
340
|
+
* Array of messages logged using {@link ngMock.$log#log}.
|
341
|
+
*
|
342
|
+
* @example
|
343
|
+
* <pre>
|
344
|
+
* $log.log('Some Log');
|
345
|
+
* var first = $log.log.logs.unshift();
|
346
|
+
* </pre>
|
326
347
|
*/
|
327
348
|
$log.log.logs = [];
|
328
349
|
/**
|
329
350
|
* @ngdoc property
|
330
|
-
* @name ngMock.$log#
|
351
|
+
* @name ngMock.$log#info.logs
|
331
352
|
* @propertyOf ngMock.$log
|
332
353
|
*
|
333
354
|
* @description
|
334
|
-
* Array of logged
|
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>
|
335
362
|
*/
|
336
|
-
$log.
|
363
|
+
$log.info.logs = [];
|
337
364
|
/**
|
338
365
|
* @ngdoc property
|
339
|
-
* @name ngMock.$log#
|
366
|
+
* @name ngMock.$log#warn.logs
|
340
367
|
* @propertyOf ngMock.$log
|
341
368
|
*
|
342
369
|
* @description
|
343
|
-
* Array of logged
|
370
|
+
* Array of messages logged using {@link ngMock.$log#warn}.
|
371
|
+
*
|
372
|
+
* @example
|
373
|
+
* <pre>
|
374
|
+
* $log.warn('Some Warning');
|
375
|
+
* var first = $log.warn.logs.unshift();
|
376
|
+
* </pre>
|
344
377
|
*/
|
345
|
-
$log.
|
378
|
+
$log.warn.logs = [];
|
346
379
|
/**
|
347
380
|
* @ngdoc property
|
348
381
|
* @name ngMock.$log#error.logs
|
349
382
|
* @propertyOf ngMock.$log
|
350
383
|
*
|
351
384
|
* @description
|
352
|
-
* Array of logged
|
385
|
+
* Array of messages logged using {@link ngMock.$log#error}.
|
386
|
+
*
|
387
|
+
* @example
|
388
|
+
* <pre>
|
389
|
+
* $log.log('Some Error');
|
390
|
+
* var first = $log.error.logs.unshift();
|
391
|
+
* </pre>
|
353
392
|
*/
|
354
393
|
$log.error.logs = [];
|
394
|
+
/**
|
395
|
+
* @ngdoc property
|
396
|
+
* @name ngMock.$log#debug.logs
|
397
|
+
* @propertyOf ngMock.$log
|
398
|
+
*
|
399
|
+
* @description
|
400
|
+
* Array of messages logged using {@link ngMock.$log#debug}.
|
401
|
+
*
|
402
|
+
* @example
|
403
|
+
* <pre>
|
404
|
+
* $log.debug('Some Error');
|
405
|
+
* var first = $log.debug.logs.unshift();
|
406
|
+
* </pre>
|
407
|
+
*/
|
408
|
+
$log.debug.logs = [];
|
355
409
|
};
|
356
410
|
|
357
411
|
/**
|
@@ -360,20 +414,22 @@ angular.mock.$LogProvider = function() {
|
|
360
414
|
* @methodOf ngMock.$log
|
361
415
|
*
|
362
416
|
* @description
|
363
|
-
* Assert that the all of the logging methods have no logged messages. If messages present, an
|
417
|
+
* Assert that the all of the logging methods have no logged messages. If messages present, an
|
418
|
+
* exception is thrown.
|
364
419
|
*/
|
365
420
|
$log.assertEmpty = function() {
|
366
421
|
var errors = [];
|
367
|
-
angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
|
422
|
+
angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
|
368
423
|
angular.forEach($log[logLevel].logs, function(log) {
|
369
424
|
angular.forEach(log, function (logItem) {
|
370
|
-
errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
|
425
|
+
errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
|
426
|
+
(logItem.stack || ''));
|
371
427
|
});
|
372
428
|
});
|
373
429
|
});
|
374
430
|
if (errors.length) {
|
375
|
-
errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or
|
376
|
-
"log message was not checked and removed:");
|
431
|
+
errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+
|
432
|
+
"an expected log message was not checked and removed:");
|
377
433
|
errors.push('');
|
378
434
|
throw new Error(errors.join('\n---------\n'));
|
379
435
|
}
|
@@ -385,260 +441,371 @@ angular.mock.$LogProvider = function() {
|
|
385
441
|
};
|
386
442
|
|
387
443
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
var neg = '';
|
414
|
-
if (num < 0) {
|
415
|
-
neg = '-';
|
416
|
-
num = -num;
|
417
|
-
}
|
418
|
-
num = '' + num;
|
419
|
-
while(num.length < digits) num = '0' + num;
|
420
|
-
if (trim)
|
421
|
-
num = num.substr(num.length - digits);
|
422
|
-
return neg + num;
|
423
|
-
}
|
424
|
-
|
425
|
-
|
426
|
-
/**
|
427
|
-
* @ngdoc object
|
428
|
-
* @name angular.mock.TzDate
|
429
|
-
* @description
|
430
|
-
*
|
431
|
-
* *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
|
432
|
-
*
|
433
|
-
* Mock of the Date type which has its timezone specified via constructor arg.
|
434
|
-
*
|
435
|
-
* The main purpose is to create Date-like instances with timezone fixed to the specified timezone
|
436
|
-
* offset, so that we can test code that depends on local timezone settings without dependency on
|
437
|
-
* the time zone settings of the machine where the code is running.
|
438
|
-
*
|
439
|
-
* @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
|
440
|
-
* @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
|
441
|
-
*
|
442
|
-
* @example
|
443
|
-
* !!!! WARNING !!!!!
|
444
|
-
* This is not a complete Date object so only methods that were implemented can be called safely.
|
445
|
-
* To make matters worse, TzDate instances inherit stuff from Date via a prototype.
|
446
|
-
*
|
447
|
-
* We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
|
448
|
-
* incomplete we might be missing some non-standard methods. This can result in errors like:
|
449
|
-
* "Date.prototype.foo called on incompatible Object".
|
450
|
-
*
|
451
|
-
* <pre>
|
452
|
-
* var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
|
453
|
-
* newYearInBratislava.getTimezoneOffset() => -60;
|
454
|
-
* newYearInBratislava.getFullYear() => 2010;
|
455
|
-
* newYearInBratislava.getMonth() => 0;
|
456
|
-
* newYearInBratislava.getDate() => 1;
|
457
|
-
* newYearInBratislava.getHours() => 0;
|
458
|
-
* newYearInBratislava.getMinutes() => 0;
|
459
|
-
* newYearInBratislava.getSeconds() => 0;
|
460
|
-
* </pre>
|
461
|
-
*
|
462
|
-
*/
|
463
|
-
angular.mock.TzDate = function (offset, timestamp) {
|
464
|
-
var self = new Date(0);
|
465
|
-
if (angular.isString(timestamp)) {
|
466
|
-
var tsStr = timestamp;
|
467
|
-
|
468
|
-
self.origDate = jsonStringToDate(timestamp);
|
469
|
-
|
470
|
-
timestamp = self.origDate.getTime();
|
471
|
-
if (isNaN(timestamp))
|
472
|
-
throw {
|
473
|
-
name: "Illegal Argument",
|
474
|
-
message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
|
475
|
-
};
|
476
|
-
} else {
|
477
|
-
self.origDate = new Date(timestamp);
|
478
|
-
}
|
479
|
-
|
480
|
-
var localOffset = new Date(timestamp).getTimezoneOffset();
|
481
|
-
self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
|
482
|
-
self.date = new Date(timestamp + self.offsetDiff);
|
444
|
+
/**
|
445
|
+
* @ngdoc service
|
446
|
+
* @name ngMock.$interval
|
447
|
+
*
|
448
|
+
* @description
|
449
|
+
* Mock implementation of the $interval service.
|
450
|
+
*
|
451
|
+
* Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to
|
452
|
+
* move forward by `millis` milliseconds and trigger any functions scheduled to run in that
|
453
|
+
* time.
|
454
|
+
*
|
455
|
+
* @param {function()} fn A function that should be called repeatedly.
|
456
|
+
* @param {number} delay Number of milliseconds between each function call.
|
457
|
+
* @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
|
458
|
+
* indefinitely.
|
459
|
+
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
460
|
+
* will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
|
461
|
+
* @returns {promise} A promise which will be notified on each iteration.
|
462
|
+
*/
|
463
|
+
angular.mock.$IntervalProvider = function() {
|
464
|
+
this.$get = ['$rootScope', '$q',
|
465
|
+
function($rootScope, $q) {
|
466
|
+
var repeatFns = [],
|
467
|
+
nextRepeatId = 0,
|
468
|
+
now = 0;
|
483
469
|
|
484
|
-
|
485
|
-
|
486
|
-
|
470
|
+
var $interval = function(fn, delay, count, invokeApply) {
|
471
|
+
var deferred = $q.defer(),
|
472
|
+
promise = deferred.promise,
|
473
|
+
iteration = 0,
|
474
|
+
skipApply = (angular.isDefined(invokeApply) && !invokeApply);
|
487
475
|
|
488
|
-
|
489
|
-
|
490
|
-
};
|
476
|
+
count = (angular.isDefined(count)) ? count : 0,
|
477
|
+
promise.then(null, null, fn);
|
491
478
|
|
492
|
-
|
493
|
-
return self.date.getFullYear();
|
494
|
-
};
|
479
|
+
promise.$$intervalId = nextRepeatId;
|
495
480
|
|
496
|
-
|
497
|
-
|
498
|
-
};
|
481
|
+
function tick() {
|
482
|
+
deferred.notify(iteration++);
|
499
483
|
|
500
|
-
|
501
|
-
|
502
|
-
|
484
|
+
if (count > 0 && iteration >= count) {
|
485
|
+
var fnIndex;
|
486
|
+
deferred.resolve(iteration);
|
503
487
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
self.getMinutes = function() {
|
509
|
-
return self.date.getMinutes();
|
510
|
-
};
|
488
|
+
angular.forEach(repeatFns, function(fn, index) {
|
489
|
+
if (fn.id === promise.$$intervalId) fnIndex = index;
|
490
|
+
});
|
511
491
|
|
512
|
-
|
513
|
-
|
514
|
-
|
492
|
+
if (fnIndex !== undefined) {
|
493
|
+
repeatFns.splice(fnIndex, 1);
|
494
|
+
}
|
495
|
+
}
|
515
496
|
|
516
|
-
|
517
|
-
|
518
|
-
};
|
497
|
+
if (!skipApply) $rootScope.$apply();
|
498
|
+
}
|
519
499
|
|
520
|
-
|
521
|
-
|
522
|
-
|
500
|
+
repeatFns.push({
|
501
|
+
nextTime:(now + delay),
|
502
|
+
delay: delay,
|
503
|
+
fn: tick,
|
504
|
+
id: nextRepeatId,
|
505
|
+
deferred: deferred
|
506
|
+
});
|
507
|
+
repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
|
523
508
|
|
524
|
-
|
525
|
-
return
|
509
|
+
nextRepeatId++;
|
510
|
+
return promise;
|
526
511
|
};
|
527
512
|
|
528
|
-
|
529
|
-
|
530
|
-
};
|
513
|
+
$interval.cancel = function(promise) {
|
514
|
+
var fnIndex;
|
531
515
|
|
532
|
-
|
533
|
-
|
534
|
-
|
516
|
+
angular.forEach(repeatFns, function(fn, index) {
|
517
|
+
if (fn.id === promise.$$intervalId) fnIndex = index;
|
518
|
+
});
|
535
519
|
|
536
|
-
|
537
|
-
|
538
|
-
|
520
|
+
if (fnIndex !== undefined) {
|
521
|
+
repeatFns[fnIndex].deferred.reject('canceled');
|
522
|
+
repeatFns.splice(fnIndex, 1);
|
523
|
+
return true;
|
524
|
+
}
|
539
525
|
|
540
|
-
|
541
|
-
return self.origDate.getUTCMinutes();
|
526
|
+
return false;
|
542
527
|
};
|
543
528
|
|
544
|
-
|
545
|
-
|
529
|
+
/**
|
530
|
+
* @ngdoc method
|
531
|
+
* @name ngMock.$interval#flush
|
532
|
+
* @methodOf ngMock.$interval
|
533
|
+
* @description
|
534
|
+
*
|
535
|
+
* Runs interval tasks scheduled to be run in the next `millis` milliseconds.
|
536
|
+
*
|
537
|
+
* @param {number=} millis maximum timeout amount to flush up until.
|
538
|
+
*
|
539
|
+
* @return {number} The amount of time moved forward.
|
540
|
+
*/
|
541
|
+
$interval.flush = function(millis) {
|
542
|
+
now += millis;
|
543
|
+
while (repeatFns.length && repeatFns[0].nextTime <= now) {
|
544
|
+
var task = repeatFns[0];
|
545
|
+
task.fn();
|
546
|
+
task.nextTime += task.delay;
|
547
|
+
repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
|
548
|
+
}
|
549
|
+
return millis;
|
546
550
|
};
|
547
551
|
|
548
|
-
|
549
|
-
|
550
|
-
|
552
|
+
return $interval;
|
553
|
+
}];
|
554
|
+
};
|
551
555
|
|
552
|
-
self.getDay = function() {
|
553
|
-
return self.date.getDay();
|
554
|
-
};
|
555
556
|
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
557
|
+
/* jshint -W101 */
|
558
|
+
/* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
|
559
|
+
* This directive should go inside the anonymous function but a bug in JSHint means that it would
|
560
|
+
* not be enacted early enough to prevent the warning.
|
561
|
+
*/
|
562
|
+
var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
|
563
|
+
|
564
|
+
function jsonStringToDate(string) {
|
565
|
+
var match;
|
566
|
+
if (match = string.match(R_ISO8061_STR)) {
|
567
|
+
var date = new Date(0),
|
568
|
+
tzHour = 0,
|
569
|
+
tzMin = 0;
|
570
|
+
if (match[9]) {
|
571
|
+
tzHour = int(match[9] + match[10]);
|
572
|
+
tzMin = int(match[9] + match[11]);
|
567
573
|
}
|
574
|
+
date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
|
575
|
+
date.setUTCHours(int(match[4]||0) - tzHour,
|
576
|
+
int(match[5]||0) - tzMin,
|
577
|
+
int(match[6]||0),
|
578
|
+
int(match[7]||0));
|
579
|
+
return date;
|
580
|
+
}
|
581
|
+
return string;
|
582
|
+
}
|
568
583
|
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
|
573
|
-
'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
|
574
|
-
'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
|
575
|
-
'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
|
576
|
-
|
577
|
-
angular.forEach(unimplementedMethods, function(methodName) {
|
578
|
-
self[methodName] = function() {
|
579
|
-
throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
|
580
|
-
};
|
581
|
-
});
|
584
|
+
function int(str) {
|
585
|
+
return parseInt(str, 10);
|
586
|
+
}
|
582
587
|
|
583
|
-
|
584
|
-
|
588
|
+
function padNumber(num, digits, trim) {
|
589
|
+
var neg = '';
|
590
|
+
if (num < 0) {
|
591
|
+
neg = '-';
|
592
|
+
num = -num;
|
593
|
+
}
|
594
|
+
num = '' + num;
|
595
|
+
while(num.length < digits) num = '0' + num;
|
596
|
+
if (trim)
|
597
|
+
num = num.substr(num.length - digits);
|
598
|
+
return neg + num;
|
599
|
+
}
|
585
600
|
|
586
|
-
//make "tzDateInstance instanceof Date" return true
|
587
|
-
angular.mock.TzDate.prototype = Date.prototype;
|
588
|
-
})();
|
589
601
|
|
590
602
|
/**
|
591
|
-
* @ngdoc
|
592
|
-
* @name angular.mock.
|
603
|
+
* @ngdoc object
|
604
|
+
* @name angular.mock.TzDate
|
593
605
|
* @description
|
594
606
|
*
|
595
|
-
*
|
596
|
-
*
|
607
|
+
* *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
|
608
|
+
*
|
609
|
+
* Mock of the Date type which has its timezone specified via constructor arg.
|
610
|
+
*
|
611
|
+
* The main purpose is to create Date-like instances with timezone fixed to the specified timezone
|
612
|
+
* offset, so that we can test code that depends on local timezone settings without dependency on
|
613
|
+
* the time zone settings of the machine where the code is running.
|
614
|
+
*
|
615
|
+
* @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
|
616
|
+
* @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
|
597
617
|
*
|
598
618
|
* @example
|
619
|
+
* !!!! WARNING !!!!!
|
620
|
+
* This is not a complete Date object so only methods that were implemented can be called safely.
|
621
|
+
* To make matters worse, TzDate instances inherit stuff from Date via a prototype.
|
622
|
+
*
|
623
|
+
* We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
|
624
|
+
* incomplete we might be missing some non-standard methods. This can result in errors like:
|
625
|
+
* "Date.prototype.foo called on incompatible Object".
|
599
626
|
*
|
600
627
|
* <pre>
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
window.setTimeout.expect(10).process();
|
610
|
-
expect(val).toEqual(123);
|
611
|
-
});
|
628
|
+
* var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
|
629
|
+
* newYearInBratislava.getTimezoneOffset() => -60;
|
630
|
+
* newYearInBratislava.getFullYear() => 2010;
|
631
|
+
* newYearInBratislava.getMonth() => 0;
|
632
|
+
* newYearInBratislava.getDate() => 1;
|
633
|
+
* newYearInBratislava.getHours() => 0;
|
634
|
+
* newYearInBratislava.getMinutes() => 0;
|
635
|
+
* newYearInBratislava.getSeconds() => 0;
|
612
636
|
* </pre>
|
613
637
|
*
|
614
638
|
*/
|
615
|
-
angular.mock.
|
616
|
-
var
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
mockWindow.setTimeout.expect = function(delay) {
|
628
|
-
if (setTimeoutQueue.length > 0) {
|
629
|
-
return {
|
630
|
-
process: function() {
|
631
|
-
setTimeoutQueue.shift().fn();
|
632
|
-
}
|
639
|
+
angular.mock.TzDate = function (offset, timestamp) {
|
640
|
+
var self = new Date(0);
|
641
|
+
if (angular.isString(timestamp)) {
|
642
|
+
var tsStr = timestamp;
|
643
|
+
|
644
|
+
self.origDate = jsonStringToDate(timestamp);
|
645
|
+
|
646
|
+
timestamp = self.origDate.getTime();
|
647
|
+
if (isNaN(timestamp))
|
648
|
+
throw {
|
649
|
+
name: "Illegal Argument",
|
650
|
+
message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
|
633
651
|
};
|
634
|
-
|
635
|
-
|
636
|
-
|
652
|
+
} else {
|
653
|
+
self.origDate = new Date(timestamp);
|
654
|
+
}
|
655
|
+
|
656
|
+
var localOffset = new Date(timestamp).getTimezoneOffset();
|
657
|
+
self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
|
658
|
+
self.date = new Date(timestamp + self.offsetDiff);
|
659
|
+
|
660
|
+
self.getTime = function() {
|
661
|
+
return self.date.getTime() - self.offsetDiff;
|
662
|
+
};
|
663
|
+
|
664
|
+
self.toLocaleDateString = function() {
|
665
|
+
return self.date.toLocaleDateString();
|
666
|
+
};
|
667
|
+
|
668
|
+
self.getFullYear = function() {
|
669
|
+
return self.date.getFullYear();
|
670
|
+
};
|
671
|
+
|
672
|
+
self.getMonth = function() {
|
673
|
+
return self.date.getMonth();
|
674
|
+
};
|
675
|
+
|
676
|
+
self.getDate = function() {
|
677
|
+
return self.date.getDate();
|
678
|
+
};
|
679
|
+
|
680
|
+
self.getHours = function() {
|
681
|
+
return self.date.getHours();
|
682
|
+
};
|
683
|
+
|
684
|
+
self.getMinutes = function() {
|
685
|
+
return self.date.getMinutes();
|
686
|
+
};
|
687
|
+
|
688
|
+
self.getSeconds = function() {
|
689
|
+
return self.date.getSeconds();
|
690
|
+
};
|
691
|
+
|
692
|
+
self.getMilliseconds = function() {
|
693
|
+
return self.date.getMilliseconds();
|
694
|
+
};
|
695
|
+
|
696
|
+
self.getTimezoneOffset = function() {
|
697
|
+
return offset * 60;
|
698
|
+
};
|
699
|
+
|
700
|
+
self.getUTCFullYear = function() {
|
701
|
+
return self.origDate.getUTCFullYear();
|
702
|
+
};
|
703
|
+
|
704
|
+
self.getUTCMonth = function() {
|
705
|
+
return self.origDate.getUTCMonth();
|
706
|
+
};
|
707
|
+
|
708
|
+
self.getUTCDate = function() {
|
709
|
+
return self.origDate.getUTCDate();
|
710
|
+
};
|
711
|
+
|
712
|
+
self.getUTCHours = function() {
|
713
|
+
return self.origDate.getUTCHours();
|
637
714
|
};
|
638
715
|
|
639
|
-
|
716
|
+
self.getUTCMinutes = function() {
|
717
|
+
return self.origDate.getUTCMinutes();
|
718
|
+
};
|
719
|
+
|
720
|
+
self.getUTCSeconds = function() {
|
721
|
+
return self.origDate.getUTCSeconds();
|
722
|
+
};
|
723
|
+
|
724
|
+
self.getUTCMilliseconds = function() {
|
725
|
+
return self.origDate.getUTCMilliseconds();
|
726
|
+
};
|
727
|
+
|
728
|
+
self.getDay = function() {
|
729
|
+
return self.date.getDay();
|
730
|
+
};
|
731
|
+
|
732
|
+
// provide this method only on browsers that already have it
|
733
|
+
if (self.toISOString) {
|
734
|
+
self.toISOString = function() {
|
735
|
+
return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
|
736
|
+
padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
|
737
|
+
padNumber(self.origDate.getUTCDate(), 2) + 'T' +
|
738
|
+
padNumber(self.origDate.getUTCHours(), 2) + ':' +
|
739
|
+
padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
|
740
|
+
padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
|
741
|
+
padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
|
742
|
+
};
|
743
|
+
}
|
744
|
+
|
745
|
+
//hide all methods not implemented in this mock that the Date prototype exposes
|
746
|
+
var unimplementedMethods = ['getUTCDay',
|
747
|
+
'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
|
748
|
+
'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
|
749
|
+
'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
|
750
|
+
'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
|
751
|
+
'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
|
752
|
+
|
753
|
+
angular.forEach(unimplementedMethods, function(methodName) {
|
754
|
+
self[methodName] = function() {
|
755
|
+
throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
|
756
|
+
};
|
757
|
+
});
|
758
|
+
|
759
|
+
return self;
|
640
760
|
};
|
641
761
|
|
762
|
+
//make "tzDateInstance instanceof Date" return true
|
763
|
+
angular.mock.TzDate.prototype = Date.prototype;
|
764
|
+
/* jshint +W101 */
|
765
|
+
|
766
|
+
angular.mock.animate = angular.module('mock.animate', ['ng'])
|
767
|
+
|
768
|
+
.config(['$provide', function($provide) {
|
769
|
+
|
770
|
+
$provide.decorator('$animate', function($delegate) {
|
771
|
+
var animate = {
|
772
|
+
queue : [],
|
773
|
+
enabled : $delegate.enabled,
|
774
|
+
flushNext : function(name) {
|
775
|
+
var tick = animate.queue.shift();
|
776
|
+
|
777
|
+
if (!tick) throw new Error('No animation to be flushed');
|
778
|
+
if(tick.method !== name) {
|
779
|
+
throw new Error('The next animation is not "' + name +
|
780
|
+
'", but is "' + tick.method + '"');
|
781
|
+
}
|
782
|
+
tick.fn();
|
783
|
+
return tick;
|
784
|
+
}
|
785
|
+
};
|
786
|
+
|
787
|
+
angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) {
|
788
|
+
animate[method] = function() {
|
789
|
+
var params = arguments;
|
790
|
+
animate.queue.push({
|
791
|
+
method : method,
|
792
|
+
params : params,
|
793
|
+
element : angular.isElement(params[0]) && params[0],
|
794
|
+
parent : angular.isElement(params[1]) && params[1],
|
795
|
+
after : angular.isElement(params[2]) && params[2],
|
796
|
+
fn : function() {
|
797
|
+
$delegate[method].apply($delegate, params);
|
798
|
+
}
|
799
|
+
});
|
800
|
+
};
|
801
|
+
});
|
802
|
+
|
803
|
+
return animate;
|
804
|
+
});
|
805
|
+
|
806
|
+
}]);
|
807
|
+
|
808
|
+
|
642
809
|
/**
|
643
810
|
* @ngdoc function
|
644
811
|
* @name angular.mock.dump
|
@@ -646,9 +813,11 @@ angular.mock.createMockWindow = function() {
|
|
646
813
|
*
|
647
814
|
* *NOTE*: this is not an injectable instance, just a globally available function.
|
648
815
|
*
|
649
|
-
* Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
|
816
|
+
* Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
|
817
|
+
* debugging.
|
650
818
|
*
|
651
|
-
* This method is also available on window, where it can be used to display objects on debug
|
819
|
+
* This method is also available on window, where it can be used to display objects on debug
|
820
|
+
* console.
|
652
821
|
*
|
653
822
|
* @param {*} object - any object to turn into string.
|
654
823
|
* @return {string} a serialized string of the argument
|
@@ -678,6 +847,8 @@ angular.mock.dump = function(object) {
|
|
678
847
|
} else if (object instanceof Error) {
|
679
848
|
out = object.stack || ('' + object.name + ': ' + object.message);
|
680
849
|
} else {
|
850
|
+
// TODO(i): this prevents methods being logged,
|
851
|
+
// we should have a better way to serialize objects
|
681
852
|
out = angular.toJson(object, true);
|
682
853
|
}
|
683
854
|
} else {
|
@@ -691,7 +862,7 @@ angular.mock.dump = function(object) {
|
|
691
862
|
offset = offset || ' ';
|
692
863
|
var log = [offset + 'Scope(' + scope.$id + '): {'];
|
693
864
|
for ( var key in scope ) {
|
694
|
-
if (
|
865
|
+
if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
|
695
866
|
log.push(' ' + key + ': ' + angular.toJson(scope[key]));
|
696
867
|
}
|
697
868
|
}
|
@@ -709,10 +880,10 @@ angular.mock.dump = function(object) {
|
|
709
880
|
* @ngdoc object
|
710
881
|
* @name ngMock.$httpBackend
|
711
882
|
* @description
|
712
|
-
* Fake HTTP backend implementation suitable for unit testing
|
883
|
+
* Fake HTTP backend implementation suitable for unit testing applications that use the
|
713
884
|
* {@link ng.$http $http service}.
|
714
885
|
*
|
715
|
-
* *Note*: For fake
|
886
|
+
* *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
|
716
887
|
* development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
|
717
888
|
*
|
718
889
|
* During unit testing, we want our unit tests to run quickly and have no external dependencies so
|
@@ -805,75 +976,100 @@ angular.mock.dump = function(object) {
|
|
805
976
|
*
|
806
977
|
*
|
807
978
|
* # Unit testing with mock $httpBackend
|
979
|
+
* The following code shows how to setup and use the mock backend in unit testing a controller.
|
980
|
+
* First we create the controller under test
|
808
981
|
*
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
982
|
+
<pre>
|
983
|
+
// The controller code
|
984
|
+
function MyController($scope, $http) {
|
985
|
+
var authToken;
|
986
|
+
|
987
|
+
$http.get('/auth.py').success(function(data, status, headers) {
|
988
|
+
authToken = headers('A-Token');
|
989
|
+
$scope.user = data;
|
990
|
+
});
|
991
|
+
|
992
|
+
$scope.saveMessage = function(message) {
|
993
|
+
var headers = { 'Authorization': authToken };
|
994
|
+
$scope.status = 'Saving...';
|
995
|
+
|
996
|
+
$http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
|
997
|
+
$scope.status = '';
|
998
|
+
}).error(function() {
|
999
|
+
$scope.status = 'ERROR!';
|
1000
|
+
});
|
1001
|
+
};
|
1002
|
+
}
|
1003
|
+
</pre>
|
1004
|
+
*
|
1005
|
+
* Now we setup the mock backend and create the test specs.
|
1006
|
+
*
|
1007
|
+
<pre>
|
1008
|
+
// testing controller
|
1009
|
+
describe('MyController', function() {
|
1010
|
+
var $httpBackend, $rootScope, createController;
|
1011
|
+
|
1012
|
+
beforeEach(inject(function($injector) {
|
1013
|
+
// Set up the mock http service responses
|
1014
|
+
$httpBackend = $injector.get('$httpBackend');
|
1015
|
+
// backend definition common for all tests
|
1016
|
+
$httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
|
825
1017
|
|
826
|
-
|
827
|
-
|
1018
|
+
// Get hold of a scope (i.e. the root scope)
|
1019
|
+
$rootScope = $injector.get('$rootScope');
|
1020
|
+
// The $controller service is used to create instances of controllers
|
1021
|
+
var $controller = $injector.get('$controller');
|
828
1022
|
|
829
|
-
|
830
|
-
|
1023
|
+
createController = function() {
|
1024
|
+
return $controller('MyController', {'$scope' : $rootScope });
|
1025
|
+
};
|
1026
|
+
}));
|
831
1027
|
|
832
|
-
|
833
|
-
|
834
|
-
|
1028
|
+
|
1029
|
+
afterEach(function() {
|
1030
|
+
$httpBackend.verifyNoOutstandingExpectation();
|
1031
|
+
$httpBackend.verifyNoOutstandingRequest();
|
1032
|
+
});
|
835
1033
|
|
836
1034
|
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
1035
|
+
it('should fetch authentication token', function() {
|
1036
|
+
$httpBackend.expectGET('/auth.py');
|
1037
|
+
var controller = createController();
|
1038
|
+
$httpBackend.flush();
|
1039
|
+
});
|
841
1040
|
|
842
1041
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
$httpBackend.flush();
|
847
|
-
});
|
1042
|
+
it('should send msg to server', function() {
|
1043
|
+
var controller = createController();
|
1044
|
+
$httpBackend.flush();
|
848
1045
|
|
1046
|
+
// now you don’t care about the authentication, but
|
1047
|
+
// the controller will still send the request and
|
1048
|
+
// $httpBackend will respond without you having to
|
1049
|
+
// specify the expectation and response for this request
|
849
1050
|
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
1051
|
+
$httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
|
1052
|
+
$rootScope.saveMessage('message content');
|
1053
|
+
expect($rootScope.status).toBe('Saving...');
|
1054
|
+
$httpBackend.flush();
|
1055
|
+
expect($rootScope.status).toBe('');
|
1056
|
+
});
|
856
1057
|
|
857
|
-
var controller = scope.$new(MyController);
|
858
|
-
$httpBackend.flush();
|
859
|
-
controller.saveMessage('message content');
|
860
|
-
expect(controller.status).toBe('Saving...');
|
861
|
-
$httpBackend.flush();
|
862
|
-
expect(controller.status).toBe('');
|
863
|
-
});
|
864
1058
|
|
1059
|
+
it('should send auth header', function() {
|
1060
|
+
var controller = createController();
|
1061
|
+
$httpBackend.flush();
|
865
1062
|
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
}).respond(201, '');
|
1063
|
+
$httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
|
1064
|
+
// check if the header was send, if it wasn't the expectation won't
|
1065
|
+
// match the request and the test will fail
|
1066
|
+
return headers['Authorization'] == 'xxx';
|
1067
|
+
}).respond(201, '');
|
872
1068
|
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
1069
|
+
$rootScope.saveMessage('whatever');
|
1070
|
+
$httpBackend.flush();
|
1071
|
+
});
|
1072
|
+
});
|
877
1073
|
</pre>
|
878
1074
|
*/
|
879
1075
|
angular.mock.$HttpBackendProvider = function() {
|
@@ -898,7 +1094,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
898
1094
|
var definitions = [],
|
899
1095
|
expectations = [],
|
900
1096
|
responses = [],
|
901
|
-
responsesPush = angular.bind(responses, responses.push)
|
1097
|
+
responsesPush = angular.bind(responses, responses.push),
|
1098
|
+
copy = angular.copy;
|
902
1099
|
|
903
1100
|
function createResponse(status, data, headers) {
|
904
1101
|
if (angular.isFunction(status)) return status;
|
@@ -911,7 +1108,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
911
1108
|
}
|
912
1109
|
|
913
1110
|
// TODO(vojta): change params to: method, url, data, headers, callback
|
914
|
-
function $httpBackend(method, url, data, callback, headers) {
|
1111
|
+
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
|
915
1112
|
var xhr = new MockXhr(),
|
916
1113
|
expectation = expectations[0],
|
917
1114
|
wasExpected = false;
|
@@ -922,24 +1119,42 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
922
1119
|
: angular.toJson(data);
|
923
1120
|
}
|
924
1121
|
|
1122
|
+
function wrapResponse(wrapped) {
|
1123
|
+
if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
|
1124
|
+
|
1125
|
+
return handleResponse;
|
1126
|
+
|
1127
|
+
function handleResponse() {
|
1128
|
+
var response = wrapped.response(method, url, data, headers);
|
1129
|
+
xhr.$$respHeaders = response[2];
|
1130
|
+
callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
function handleTimeout() {
|
1134
|
+
for (var i = 0, ii = responses.length; i < ii; i++) {
|
1135
|
+
if (responses[i] === handleResponse) {
|
1136
|
+
responses.splice(i, 1);
|
1137
|
+
callback(-1, undefined, '');
|
1138
|
+
break;
|
1139
|
+
}
|
1140
|
+
}
|
1141
|
+
}
|
1142
|
+
}
|
1143
|
+
|
925
1144
|
if (expectation && expectation.match(method, url)) {
|
926
1145
|
if (!expectation.matchData(data))
|
927
|
-
throw Error('Expected ' + expectation + ' with different data\n' +
|
1146
|
+
throw new Error('Expected ' + expectation + ' with different data\n' +
|
928
1147
|
'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
|
929
1148
|
|
930
1149
|
if (!expectation.matchHeaders(headers))
|
931
|
-
throw Error('Expected ' + expectation + ' with different headers\n' +
|
932
|
-
|
933
|
-
|
1150
|
+
throw new Error('Expected ' + expectation + ' with different headers\n' +
|
1151
|
+
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
|
1152
|
+
prettyPrint(headers));
|
934
1153
|
|
935
1154
|
expectations.shift();
|
936
1155
|
|
937
1156
|
if (expectation.response) {
|
938
|
-
responses.push(
|
939
|
-
var response = expectation.response(method, url, data, headers);
|
940
|
-
xhr.$$respHeaders = response[2];
|
941
|
-
callback(response[0], response[1], xhr.getAllResponseHeaders());
|
942
|
-
});
|
1157
|
+
responses.push(wrapResponse(expectation));
|
943
1158
|
return;
|
944
1159
|
}
|
945
1160
|
wasExpected = true;
|
@@ -950,21 +1165,17 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
950
1165
|
if (definition.match(method, url, data, headers || {})) {
|
951
1166
|
if (definition.response) {
|
952
1167
|
// if $browser specified, we do auto flush all requests
|
953
|
-
($browser ? $browser.defer : responsesPush)(
|
954
|
-
var response = definition.response(method, url, data, headers);
|
955
|
-
xhr.$$respHeaders = response[2];
|
956
|
-
callback(response[0], response[1], xhr.getAllResponseHeaders());
|
957
|
-
});
|
1168
|
+
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
|
958
1169
|
} else if (definition.passThrough) {
|
959
|
-
$delegate(method, url, data, callback, headers);
|
960
|
-
} else throw Error('No response defined !');
|
1170
|
+
$delegate(method, url, data, callback, headers, timeout, withCredentials);
|
1171
|
+
} else throw new Error('No response defined !');
|
961
1172
|
return;
|
962
1173
|
}
|
963
1174
|
}
|
964
1175
|
throw wasExpected ?
|
965
|
-
Error('No response defined !') :
|
966
|
-
Error('Unexpected request: ' + method + ' ' + url + '\n' +
|
967
|
-
|
1176
|
+
new Error('No response defined !') :
|
1177
|
+
new Error('Unexpected request: ' + method + ' ' + url + '\n' +
|
1178
|
+
(expectation ? 'Expected ' + expectation : 'No more request expected'));
|
968
1179
|
}
|
969
1180
|
|
970
1181
|
/**
|
@@ -976,13 +1187,15 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
976
1187
|
*
|
977
1188
|
* @param {string} method HTTP method.
|
978
1189
|
* @param {string|RegExp} url HTTP url.
|
979
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1190
|
+
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
1191
|
+
* data string and returns true if the data is as expected.
|
980
1192
|
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
981
1193
|
* object and returns true if the headers match the current definition.
|
982
|
-
* @returns {requestHandler} Returns an object with `respond` method that
|
1194
|
+
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
983
1195
|
* request is handled.
|
984
1196
|
*
|
985
|
-
* - respond –
|
1197
|
+
* - respond –
|
1198
|
+
* `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
|
986
1199
|
* – The respond method takes a set of static data to be returned or a function that can return
|
987
1200
|
* an array containing response status (number), response data (string) and response headers
|
988
1201
|
* (Object).
|
@@ -1052,7 +1265,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1052
1265
|
* Creates a new backend definition for POST requests. For more info see `when()`.
|
1053
1266
|
*
|
1054
1267
|
* @param {string|RegExp} url HTTP url.
|
1055
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1268
|
+
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
1269
|
+
* data string and returns true if the data is as expected.
|
1056
1270
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
1057
1271
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1058
1272
|
* request is handled.
|
@@ -1066,7 +1280,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1066
1280
|
* Creates a new backend definition for PUT requests. For more info see `when()`.
|
1067
1281
|
*
|
1068
1282
|
* @param {string|RegExp} url HTTP url.
|
1069
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1283
|
+
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
1284
|
+
* data string and returns true if the data is as expected.
|
1070
1285
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
1071
1286
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1072
1287
|
* request is handled.
|
@@ -1095,13 +1310,16 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1095
1310
|
*
|
1096
1311
|
* @param {string} method HTTP method.
|
1097
1312
|
* @param {string|RegExp} url HTTP url.
|
1098
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1313
|
+
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
1314
|
+
* receives data string and returns true if the data is as expected, or Object if request body
|
1315
|
+
* is in JSON format.
|
1099
1316
|
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
1100
1317
|
* object and returns true if the headers match the current expectation.
|
1101
1318
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1102
1319
|
* request is handled.
|
1103
1320
|
*
|
1104
|
-
* - respond –
|
1321
|
+
* - respond –
|
1322
|
+
* `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
|
1105
1323
|
* – The respond method takes a set of static data to be returned or a function that can return
|
1106
1324
|
* an array containing response status (number), response data (string) and response headers
|
1107
1325
|
* (Object).
|
@@ -1164,7 +1382,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1164
1382
|
* Creates a new request expectation for POST requests. For more info see `expect()`.
|
1165
1383
|
*
|
1166
1384
|
* @param {string|RegExp} url HTTP url.
|
1167
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1385
|
+
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
1386
|
+
* receives data string and returns true if the data is as expected, or Object if request body
|
1387
|
+
* is in JSON format.
|
1168
1388
|
* @param {Object=} headers HTTP headers.
|
1169
1389
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1170
1390
|
* request is handled.
|
@@ -1178,7 +1398,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1178
1398
|
* Creates a new request expectation for PUT requests. For more info see `expect()`.
|
1179
1399
|
*
|
1180
1400
|
* @param {string|RegExp} url HTTP url.
|
1181
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1401
|
+
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
1402
|
+
* receives data string and returns true if the data is as expected, or Object if request body
|
1403
|
+
* is in JSON format.
|
1182
1404
|
* @param {Object=} headers HTTP headers.
|
1183
1405
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1184
1406
|
* request is handled.
|
@@ -1192,7 +1414,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1192
1414
|
* Creates a new request expectation for PATCH requests. For more info see `expect()`.
|
1193
1415
|
*
|
1194
1416
|
* @param {string|RegExp} url HTTP url.
|
1195
|
-
* @param {(string|RegExp)=} data HTTP request body
|
1417
|
+
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
1418
|
+
* receives data string and returns true if the data is as expected, or Object if request body
|
1419
|
+
* is in JSON format.
|
1196
1420
|
* @param {Object=} headers HTTP headers.
|
1197
1421
|
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
|
1198
1422
|
* request is handled.
|
@@ -1225,11 +1449,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1225
1449
|
*/
|
1226
1450
|
$httpBackend.flush = function(count) {
|
1227
1451
|
$rootScope.$digest();
|
1228
|
-
if (!responses.length) throw Error('No pending request to flush !');
|
1452
|
+
if (!responses.length) throw new Error('No pending request to flush !');
|
1229
1453
|
|
1230
1454
|
if (angular.isDefined(count)) {
|
1231
1455
|
while (count--) {
|
1232
|
-
if (!responses.length) throw Error('No more pending request to flush !');
|
1456
|
+
if (!responses.length) throw new Error('No more pending request to flush !');
|
1233
1457
|
responses.shift()();
|
1234
1458
|
}
|
1235
1459
|
} else {
|
@@ -1253,13 +1477,13 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1253
1477
|
* "afterEach" clause.
|
1254
1478
|
*
|
1255
1479
|
* <pre>
|
1256
|
-
* afterEach($httpBackend.
|
1480
|
+
* afterEach($httpBackend.verifyNoOutstandingExpectation);
|
1257
1481
|
* </pre>
|
1258
1482
|
*/
|
1259
1483
|
$httpBackend.verifyNoOutstandingExpectation = function() {
|
1260
1484
|
$rootScope.$digest();
|
1261
1485
|
if (expectations.length) {
|
1262
|
-
throw Error('Unsatisfied requests: ' + expectations.join(', '));
|
1486
|
+
throw new Error('Unsatisfied requests: ' + expectations.join(', '));
|
1263
1487
|
}
|
1264
1488
|
};
|
1265
1489
|
|
@@ -1280,7 +1504,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1280
1504
|
*/
|
1281
1505
|
$httpBackend.verifyNoOutstandingRequest = function() {
|
1282
1506
|
if (responses.length) {
|
1283
|
-
throw Error('Unflushed requests: ' + responses.length);
|
1507
|
+
throw new Error('Unflushed requests: ' + responses.length);
|
1284
1508
|
}
|
1285
1509
|
};
|
1286
1510
|
|
@@ -1305,14 +1529,14 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
|
1305
1529
|
function createShortMethods(prefix) {
|
1306
1530
|
angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
|
1307
1531
|
$httpBackend[prefix + method] = function(url, headers) {
|
1308
|
-
return $httpBackend[prefix](method, url, undefined, headers)
|
1309
|
-
}
|
1532
|
+
return $httpBackend[prefix](method, url, undefined, headers);
|
1533
|
+
};
|
1310
1534
|
});
|
1311
1535
|
|
1312
1536
|
angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
|
1313
1537
|
$httpBackend[prefix + method] = function(url, data, headers) {
|
1314
|
-
return $httpBackend[prefix](method, url, data, headers)
|
1315
|
-
}
|
1538
|
+
return $httpBackend[prefix](method, url, data, headers);
|
1539
|
+
};
|
1316
1540
|
});
|
1317
1541
|
}
|
1318
1542
|
}
|
@@ -1345,7 +1569,8 @@ function MockHttpExpectation(method, url, data, headers) {
|
|
1345
1569
|
this.matchData = function(d) {
|
1346
1570
|
if (angular.isUndefined(data)) return true;
|
1347
1571
|
if (data && angular.isFunction(data.test)) return data.test(d);
|
1348
|
-
if (data &&
|
1572
|
+
if (data && angular.isFunction(data)) return data(d);
|
1573
|
+
if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d));
|
1349
1574
|
return data == d;
|
1350
1575
|
};
|
1351
1576
|
|
@@ -1376,7 +1601,8 @@ function MockXhr() {
|
|
1376
1601
|
};
|
1377
1602
|
|
1378
1603
|
this.getResponseHeader = function(name) {
|
1379
|
-
// the lookup must be case insensitive,
|
1604
|
+
// the lookup must be case insensitive,
|
1605
|
+
// that's why we try two quick lookups first and full scan last
|
1380
1606
|
var header = this.$$respHeaders[name];
|
1381
1607
|
if (header) return header;
|
1382
1608
|
|
@@ -1411,7 +1637,7 @@ function MockXhr() {
|
|
1411
1637
|
*
|
1412
1638
|
* This service is just a simple decorator for {@link ng.$timeout $timeout} service
|
1413
1639
|
* that adds a "flush" and "verifyNoPendingTasks" methods.
|
1414
|
-
*/
|
1640
|
+
*/
|
1415
1641
|
|
1416
1642
|
angular.mock.$TimeoutDecorator = function($delegate, $browser) {
|
1417
1643
|
|
@@ -1422,9 +1648,11 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
|
|
1422
1648
|
* @description
|
1423
1649
|
*
|
1424
1650
|
* Flushes the queue of pending tasks.
|
1651
|
+
*
|
1652
|
+
* @param {number=} delay maximum timeout amount to flush up until
|
1425
1653
|
*/
|
1426
|
-
$delegate.flush = function() {
|
1427
|
-
$browser.defer.flush();
|
1654
|
+
$delegate.flush = function(delay) {
|
1655
|
+
$browser.defer.flush(delay);
|
1428
1656
|
};
|
1429
1657
|
|
1430
1658
|
/**
|
@@ -1437,7 +1665,7 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
|
|
1437
1665
|
*/
|
1438
1666
|
$delegate.verifyNoPendingTasks = function() {
|
1439
1667
|
if ($browser.deferredFns.length) {
|
1440
|
-
throw Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
|
1668
|
+
throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
|
1441
1669
|
formatPendingTasksAsString($browser.deferredFns));
|
1442
1670
|
}
|
1443
1671
|
};
|
@@ -1460,7 +1688,7 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
|
|
1460
1688
|
angular.mock.$RootElementProvider = function() {
|
1461
1689
|
this.$get = function() {
|
1462
1690
|
return angular.element('<div ng-app></div>');
|
1463
|
-
}
|
1691
|
+
};
|
1464
1692
|
};
|
1465
1693
|
|
1466
1694
|
/**
|
@@ -1468,18 +1696,27 @@ angular.mock.$RootElementProvider = function() {
|
|
1468
1696
|
* @name ngMock
|
1469
1697
|
* @description
|
1470
1698
|
*
|
1471
|
-
*
|
1472
|
-
*
|
1699
|
+
* # ngMock
|
1700
|
+
*
|
1701
|
+
* The `ngMock` module providers support to inject and mock Angular services into unit tests.
|
1702
|
+
* In addition, ngMock also extends various core ng services such that they can be
|
1703
|
+
* inspected and controlled in a synchronous manner within test code.
|
1704
|
+
*
|
1705
|
+
* {@installModule mocks}
|
1706
|
+
*
|
1707
|
+
* <div doc-module-components="ngMock"></div>
|
1708
|
+
*
|
1473
1709
|
*/
|
1474
1710
|
angular.module('ngMock', ['ng']).provider({
|
1475
1711
|
$browser: angular.mock.$BrowserProvider,
|
1476
1712
|
$exceptionHandler: angular.mock.$ExceptionHandlerProvider,
|
1477
1713
|
$log: angular.mock.$LogProvider,
|
1714
|
+
$interval: angular.mock.$IntervalProvider,
|
1478
1715
|
$httpBackend: angular.mock.$HttpBackendProvider,
|
1479
1716
|
$rootElement: angular.mock.$RootElementProvider
|
1480
|
-
}).config(function($provide) {
|
1717
|
+
}).config(['$provide', function($provide) {
|
1481
1718
|
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
|
1482
|
-
});
|
1719
|
+
}]);
|
1483
1720
|
|
1484
1721
|
/**
|
1485
1722
|
* @ngdoc overview
|
@@ -1490,9 +1727,9 @@ angular.module('ngMock', ['ng']).provider({
|
|
1490
1727
|
* Currently there is only one mock present in this module -
|
1491
1728
|
* the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
|
1492
1729
|
*/
|
1493
|
-
angular.module('ngMockE2E', ['ng']).config(function($provide) {
|
1730
|
+
angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
1494
1731
|
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
|
1495
|
-
});
|
1732
|
+
}]);
|
1496
1733
|
|
1497
1734
|
/**
|
1498
1735
|
* @ngdoc object
|
@@ -1532,7 +1769,7 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
|
|
1532
1769
|
*
|
1533
1770
|
* // adds a new phone to the phones array
|
1534
1771
|
* $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
|
1535
|
-
* phones.push(angular.
|
1772
|
+
* phones.push(angular.fromJson(data));
|
1536
1773
|
* });
|
1537
1774
|
* $httpBackend.whenGET(/^\/templates\//).passThrough();
|
1538
1775
|
* //...
|
@@ -1557,7 +1794,8 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
|
|
1557
1794
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
1558
1795
|
* control how a matched request is handled.
|
1559
1796
|
*
|
1560
|
-
* - respond –
|
1797
|
+
* - respond –
|
1798
|
+
* `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
|
1561
1799
|
* – The respond method takes a set of static data to be returned or a function that can return
|
1562
1800
|
* an array containing response status (number), response data (string) and response headers
|
1563
1801
|
* (Object).
|
@@ -1659,7 +1897,8 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
|
|
1659
1897
|
* control how a matched request is handled.
|
1660
1898
|
*/
|
1661
1899
|
angular.mock.e2e = {};
|
1662
|
-
angular.mock.e2e.$httpBackendDecorator =
|
1900
|
+
angular.mock.e2e.$httpBackendDecorator =
|
1901
|
+
['$rootScope', '$delegate', '$browser', createHttpBackendMock];
|
1663
1902
|
|
1664
1903
|
|
1665
1904
|
angular.mock.clearDataCache = function() {
|
@@ -1667,36 +1906,24 @@ angular.mock.clearDataCache = function() {
|
|
1667
1906
|
cache = angular.element.cache;
|
1668
1907
|
|
1669
1908
|
for(key in cache) {
|
1670
|
-
if (
|
1909
|
+
if (Object.prototype.hasOwnProperty.call(cache,key)) {
|
1671
1910
|
var handle = cache[key].handle;
|
1672
1911
|
|
1673
|
-
handle && angular.element(handle.elem).
|
1912
|
+
handle && angular.element(handle.elem).off();
|
1674
1913
|
delete cache[key];
|
1675
1914
|
}
|
1676
1915
|
}
|
1677
1916
|
};
|
1678
1917
|
|
1679
1918
|
|
1680
|
-
window.jstestdriver && (function(window) {
|
1681
|
-
/**
|
1682
|
-
* Global method to output any number of objects into JSTD console. Useful for debugging.
|
1683
|
-
*/
|
1684
|
-
window.dump = function() {
|
1685
|
-
var args = [];
|
1686
|
-
angular.forEach(arguments, function(arg) {
|
1687
|
-
args.push(angular.mock.dump(arg));
|
1688
|
-
});
|
1689
|
-
jstestdriver.console.log.apply(jstestdriver.console, args);
|
1690
|
-
if (window.console) {
|
1691
|
-
window.console.log.apply(window.console, args);
|
1692
|
-
}
|
1693
|
-
};
|
1694
|
-
})(window);
|
1695
1919
|
|
1920
|
+
if(window.jasmine || window.mocha) {
|
1696
1921
|
|
1697
|
-
|
1922
|
+
var currentSpec = null,
|
1923
|
+
isSpecRunning = function() {
|
1924
|
+
return currentSpec && (window.mocha || currentSpec.queue.running);
|
1925
|
+
};
|
1698
1926
|
|
1699
|
-
var currentSpec = null;
|
1700
1927
|
|
1701
1928
|
beforeEach(function() {
|
1702
1929
|
currentSpec = this;
|
@@ -1710,7 +1937,7 @@ window.jstestdriver && (function(window) {
|
|
1710
1937
|
currentSpec = null;
|
1711
1938
|
|
1712
1939
|
if (injector) {
|
1713
|
-
injector.get('$rootElement').
|
1940
|
+
injector.get('$rootElement').off();
|
1714
1941
|
injector.get('$browser').pollFns.length = 0;
|
1715
1942
|
}
|
1716
1943
|
|
@@ -1729,10 +1956,6 @@ window.jstestdriver && (function(window) {
|
|
1729
1956
|
angular.callbacks.counter = 0;
|
1730
1957
|
});
|
1731
1958
|
|
1732
|
-
function isSpecRunning() {
|
1733
|
-
return currentSpec && (window.mocha || currentSpec.queue.running);
|
1734
|
-
}
|
1735
|
-
|
1736
1959
|
/**
|
1737
1960
|
* @ngdoc function
|
1738
1961
|
* @name angular.mock.module
|
@@ -1745,9 +1968,11 @@ window.jstestdriver && (function(window) {
|
|
1745
1968
|
*
|
1746
1969
|
* See {@link angular.mock.inject inject} for usage example
|
1747
1970
|
*
|
1748
|
-
* @param {...(string|Function)} fns any number of modules which are represented as string
|
1971
|
+
* @param {...(string|Function|Object)} fns any number of modules which are represented as string
|
1749
1972
|
* aliases or as anonymous module initialization functions. The modules are used to
|
1750
|
-
* configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
|
1973
|
+
* configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
|
1974
|
+
* object literal is passed they will be register as values in the module, the key being
|
1975
|
+
* the module name and the value being what is returned.
|
1751
1976
|
*/
|
1752
1977
|
window.module = angular.mock.module = function() {
|
1753
1978
|
var moduleFns = Array.prototype.slice.call(arguments, 0);
|
@@ -1755,11 +1980,19 @@ window.jstestdriver && (function(window) {
|
|
1755
1980
|
/////////////////////
|
1756
1981
|
function workFn() {
|
1757
1982
|
if (currentSpec.$injector) {
|
1758
|
-
throw Error('Injector already created, can not register a module!');
|
1983
|
+
throw new Error('Injector already created, can not register a module!');
|
1759
1984
|
} else {
|
1760
1985
|
var modules = currentSpec.$modules || (currentSpec.$modules = []);
|
1761
1986
|
angular.forEach(moduleFns, function(module) {
|
1762
|
-
|
1987
|
+
if (angular.isObject(module) && !angular.isArray(module)) {
|
1988
|
+
modules.push(function($provide) {
|
1989
|
+
angular.forEach(module, function(value, key) {
|
1990
|
+
$provide.value(key, value);
|
1991
|
+
});
|
1992
|
+
});
|
1993
|
+
} else {
|
1994
|
+
modules.push(module);
|
1995
|
+
}
|
1763
1996
|
});
|
1764
1997
|
}
|
1765
1998
|
}
|
@@ -1776,8 +2009,40 @@ window.jstestdriver && (function(window) {
|
|
1776
2009
|
* instance of {@link AUTO.$injector $injector} per test, which is then used for
|
1777
2010
|
* resolving references.
|
1778
2011
|
*
|
1779
|
-
* See also {@link angular.mock.module module}
|
1780
2012
|
*
|
2013
|
+
* ## Resolving References (Underscore Wrapping)
|
2014
|
+
* Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
|
2015
|
+
* in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
|
2016
|
+
* that is declared in the scope of the `describe()` block. Since we would, most likely, want
|
2017
|
+
* the variable to have the same name of the reference we have a problem, since the parameter
|
2018
|
+
* to the `inject()` function would hide the outer variable.
|
2019
|
+
*
|
2020
|
+
* To help with this, the injected parameters can, optionally, be enclosed with underscores.
|
2021
|
+
* These are ignored by the injector when the reference name is resolved.
|
2022
|
+
*
|
2023
|
+
* For example, the parameter `_myService_` would be resolved as the reference `myService`.
|
2024
|
+
* Since it is available in the function body as _myService_, we can then assign it to a variable
|
2025
|
+
* defined in an outer scope.
|
2026
|
+
*
|
2027
|
+
* ```
|
2028
|
+
* // Defined out reference variable outside
|
2029
|
+
* var myService;
|
2030
|
+
*
|
2031
|
+
* // Wrap the parameter in underscores
|
2032
|
+
* beforeEach( inject( function(_myService_){
|
2033
|
+
* myService = _myService_;
|
2034
|
+
* }));
|
2035
|
+
*
|
2036
|
+
* // Use myService in a series of tests.
|
2037
|
+
* it('makes use of myService', function() {
|
2038
|
+
* myService.doStuff();
|
2039
|
+
* });
|
2040
|
+
*
|
2041
|
+
* ```
|
2042
|
+
*
|
2043
|
+
* See also {@link angular.mock.module angular.mock.module}
|
2044
|
+
*
|
2045
|
+
* ## Example
|
1781
2046
|
* Example of what a typical jasmine tests looks like with the inject method.
|
1782
2047
|
* <pre>
|
1783
2048
|
*
|
@@ -1810,7 +2075,7 @@ window.jstestdriver && (function(window) {
|
|
1810
2075
|
* inject(function(version) {
|
1811
2076
|
* expect(version).toEqual('overridden');
|
1812
2077
|
* });
|
1813
|
-
* )
|
2078
|
+
* });
|
1814
2079
|
* });
|
1815
2080
|
*
|
1816
2081
|
* </pre>
|
@@ -1833,7 +2098,9 @@ window.jstestdriver && (function(window) {
|
|
1833
2098
|
}
|
1834
2099
|
for(var i = 0, ii = blockFns.length; i < ii; i++) {
|
1835
2100
|
try {
|
2101
|
+
/* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
|
1836
2102
|
injector.invoke(blockFns[i] || angular.noop, this);
|
2103
|
+
/* jshint +W040 */
|
1837
2104
|
} catch (e) {
|
1838
2105
|
if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack;
|
1839
2106
|
throw e;
|
@@ -1843,4 +2110,7 @@ window.jstestdriver && (function(window) {
|
|
1843
2110
|
}
|
1844
2111
|
}
|
1845
2112
|
};
|
1846
|
-
}
|
2113
|
+
}
|
2114
|
+
|
2115
|
+
|
2116
|
+
})(window, window.angular);
|