mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-20 20:31:52 +00:00
Introduced injector and $new to scope, and injection into link methods and controllers
- added angular.injector(scope, services, instanceCache) which returns inject
- inject method can return, instance, or call function which have $inject
property
- initialize services with $creation=[eager|eager-publish] this means that
only some of the services are now globally accessible
- upgraded $become on scope to use injector hence respect the $inject property
for injection
- $become should not be run multiple times and will most likely be removed
in future version
- added $new on scope to create a child scope
- $inject is respected on constructor function
- simplified scopes so that they no longer have separate __proto__ for
parent, api, behavior and instance this should speed up execution since
scope will now create one __proto__ chain per scope (not three).
BACKWARD COMPATIBILITY WARNING:
- services now need to have $inject instead of inject property for proper
injection this breaks backward compatibility
- not all services are now published into root scope
(only: $location, $cookie, $window)
- if you have widget/directive which uses services on scope
(such as this.$xhr), you will now have to inject that service in
(as it is not published on the root scope anymore)
This commit is contained in:
parent
fbfd160316
commit
d9abfe8a7e
17 changed files with 347 additions and 213 deletions
1
Rakefile
1
Rakefile
|
|
@ -29,6 +29,7 @@ task :compile_scenario do
|
||||||
src/jqLite.js \
|
src/jqLite.js \
|
||||||
src/JSON.js \
|
src/JSON.js \
|
||||||
src/Scope.js \
|
src/Scope.js \
|
||||||
|
src/Injector.js \
|
||||||
src/Parser.js \
|
src/Parser.js \
|
||||||
src/Resource.js \
|
src/Resource.js \
|
||||||
src/Browser.js \
|
src/Browser.js \
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,10 @@ function escapeAttr(html) {
|
||||||
'"');
|
'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function concat(array1, array2, index) {
|
||||||
|
return array1.concat(slice.call(array2, index, array2.length));
|
||||||
|
}
|
||||||
|
|
||||||
function bind(self, fn) {
|
function bind(self, fn) {
|
||||||
var curryArgs = arguments.length > 2 ? slice.call(arguments, 2, arguments.length) : [];
|
var curryArgs = arguments.length > 2 ? slice.call(arguments, 2, arguments.length) : [];
|
||||||
if (typeof fn == $function) {
|
if (typeof fn == $function) {
|
||||||
|
|
@ -403,7 +407,7 @@ function angularInit(config){
|
||||||
// TODO default to the source of angular.js
|
// TODO default to the source of angular.js
|
||||||
var scope = compile(window.document, _null, {'$config':config});
|
var scope = compile(window.document, _null, {'$config':config});
|
||||||
if (config.css)
|
if (config.css)
|
||||||
scope.$browser.addCss(config.base_url + config.css);
|
scope.$inject('$browser').addCss(config.base_url + config.css);
|
||||||
scope.$init();
|
scope.$init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ extend(angular, {
|
||||||
'extend': extend,
|
'extend': extend,
|
||||||
'equals': equals,
|
'equals': equals,
|
||||||
'foreach': foreach,
|
'foreach': foreach,
|
||||||
|
'injector': createInjector,
|
||||||
'noop':noop,
|
'noop':noop,
|
||||||
'bind':bind,
|
'bind':bind,
|
||||||
'toJson': toJson,
|
'toJson': toJson,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Template.prototype = {
|
||||||
foreach(this.inits, function(fn) {
|
foreach(this.inits, function(fn) {
|
||||||
queue.push(function() {
|
queue.push(function() {
|
||||||
childScope.$tryEval(function(){
|
childScope.$tryEval(function(){
|
||||||
return fn.call(childScope, element);
|
return childScope.$inject(fn, childScope, element);
|
||||||
}, element);
|
}, element);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -96,8 +96,7 @@ Compiler.prototype = {
|
||||||
return function(element, parentScope){
|
return function(element, parentScope){
|
||||||
element = jqLite(element);
|
element = jqLite(element);
|
||||||
var scope = parentScope && parentScope.$eval ?
|
var scope = parentScope && parentScope.$eval ?
|
||||||
parentScope :
|
parentScope : createScope(parentScope);
|
||||||
createScope(parentScope || {}, angularService);
|
|
||||||
return extend(scope, {
|
return extend(scope, {
|
||||||
$element:element,
|
$element:element,
|
||||||
$init: function() {
|
$init: function() {
|
||||||
|
|
@ -124,7 +123,7 @@ Compiler.prototype = {
|
||||||
text:function(text) {return jqLite(document.createTextNode(text));},
|
text:function(text) {return jqLite(document.createTextNode(text));},
|
||||||
descend: function(value){ if(isDefined(value)) descend = value; return descend;},
|
descend: function(value){ if(isDefined(value)) descend = value; return descend;},
|
||||||
directives: function(value){ if(isDefined(value)) directives = value; return directives;},
|
directives: function(value){ if(isDefined(value)) directives = value; return directives;},
|
||||||
scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value ; return template.newScope;}
|
scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value; return template.newScope;}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
priority = element.attr('ng:eval-order') || priority || 0;
|
priority = element.attr('ng:eval-order') || priority || 0;
|
||||||
|
|
|
||||||
59
src/Injector.js
Normal file
59
src/Injector.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* Create an inject method
|
||||||
|
* @param providerScope provider's "this"
|
||||||
|
* @param providers a function(name) which returns provider function
|
||||||
|
* @param cache place where instances are saved for reuse
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
function createInjector(providerScope, providers, cache) {
|
||||||
|
providers = providers || angularService;
|
||||||
|
cache = cache || {};
|
||||||
|
providerScope = providerScope || {};
|
||||||
|
/**
|
||||||
|
* injection function
|
||||||
|
* @param value: string, array, object or function.
|
||||||
|
* @param scope: optional function "this"
|
||||||
|
* @param args: optional arguments to pass to function after injection
|
||||||
|
* parameters
|
||||||
|
* @returns depends on value:
|
||||||
|
* string: return an instance for the injection key.
|
||||||
|
* array of keys: returns an array of instances.
|
||||||
|
* function: look at $inject property of function to determine instances
|
||||||
|
* and then call the function with instances and scope. Any
|
||||||
|
* additional arguments are passed on to function.
|
||||||
|
* object: initialize eager providers and publish them the ones with publish here.
|
||||||
|
* none: same as object but use providerScope as place to publish.
|
||||||
|
*/
|
||||||
|
return function inject(value, scope, args){
|
||||||
|
var returnValue, provider, creation;
|
||||||
|
if (isString(value)) {
|
||||||
|
if (!cache.hasOwnProperty(value)) {
|
||||||
|
provider = providers[value];
|
||||||
|
if (!provider) throw "Unknown provider for '"+value+"'.";
|
||||||
|
cache[value] = inject(provider, providerScope);
|
||||||
|
}
|
||||||
|
returnValue = cache[value];
|
||||||
|
} else if (isArray(value)) {
|
||||||
|
returnValue = [];
|
||||||
|
foreach(value, function(name) {
|
||||||
|
returnValue.push(inject(name));
|
||||||
|
});
|
||||||
|
} else if (isFunction(value)) {
|
||||||
|
returnValue = inject(value.$inject || []);
|
||||||
|
returnValue = value.apply(scope, concat(returnValue, arguments, 2));
|
||||||
|
} else if (isObject(value)) {
|
||||||
|
foreach(providers, function(provider, name){
|
||||||
|
creation = provider.$creation;
|
||||||
|
if (creation == 'eager') {
|
||||||
|
inject(name);
|
||||||
|
}
|
||||||
|
if (creation == 'eager-published') {
|
||||||
|
setter(value, name, inject(name));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
returnValue = inject(providerScope);
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
};
|
||||||
|
}
|
||||||
61
src/Scope.js
61
src/Scope.js
|
|
@ -108,20 +108,14 @@ function errorHandlerFor(element, error) {
|
||||||
elementError(element, NG_EXCEPTION, isDefined(error) ? toJson(error) : error);
|
elementError(element, NG_EXCEPTION, isDefined(error) ? toJson(error) : error);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createScope(parent, services, existing) {
|
function createScope(parent, providers, instanceCache) {
|
||||||
function Parent(){}
|
function Parent(){}
|
||||||
function API(){}
|
|
||||||
function Behavior(){}
|
|
||||||
|
|
||||||
parent = Parent.prototype = (parent || {});
|
parent = Parent.prototype = (parent || {});
|
||||||
|
var instance = new Parent();
|
||||||
var evalLists = {sorted:[]};
|
var evalLists = {sorted:[]};
|
||||||
var postList = [], postHash = {}, postId = 0;
|
var postList = [], postHash = {}, postId = 0;
|
||||||
var servicesCache = extend({}, existing);
|
|
||||||
var api = API.prototype = new Parent();
|
|
||||||
var behavior = Behavior.prototype = new API();
|
|
||||||
var instance = new Behavior();
|
|
||||||
|
|
||||||
extend(api, {
|
extend(instance, {
|
||||||
'this': instance,
|
'this': instance,
|
||||||
$id: (scopeId++),
|
$id: (scopeId++),
|
||||||
$parent: parent,
|
$parent: parent,
|
||||||
|
|
@ -227,46 +221,29 @@ function createScope(parent, services, existing) {
|
||||||
},
|
},
|
||||||
|
|
||||||
$become: function(Class) {
|
$become: function(Class) {
|
||||||
// remove existing
|
if (isFunction(Class)) {
|
||||||
foreach(behavior, function(value, key){ delete behavior[key]; });
|
instance.constructor = Class;
|
||||||
foreach((Class || noop).prototype, function(fn, name){
|
foreach(Class.prototype, function(fn, name){
|
||||||
behavior[name] = bind(instance, fn);
|
instance[name] = bind(instance, fn);
|
||||||
});
|
});
|
||||||
(Class || noop).call(instance);
|
instance.$inject.apply(instance, concat([Class, instance], arguments, 1));
|
||||||
|
|
||||||
//TODO: backwards compatibility hack, remove when Feedback's init methods are removed
|
|
||||||
if (behavior.hasOwnProperty('init')) {
|
|
||||||
behavior.init();
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
$new: function(Class) {
|
||||||
|
var child = createScope(instance);
|
||||||
|
child.$become.apply(instance, concat([Class], arguments, 1));
|
||||||
|
instance.$onEval(child.$eval);
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!parent.$root) {
|
if (!parent.$root) {
|
||||||
api.$root = instance;
|
instance.$root = instance;
|
||||||
api.$parent = instance;
|
instance.$parent = instance;
|
||||||
|
(instance.$inject = createInjector(instance, providers, instanceCache))();
|
||||||
}
|
}
|
||||||
|
|
||||||
function inject(name){
|
|
||||||
var service = servicesCache[name], factory, args = [];
|
|
||||||
if (isUndefined(service)) {
|
|
||||||
factory = services[name];
|
|
||||||
if (!isFunction(factory))
|
|
||||||
throw "Don't know how to inject '" + name + "'.";
|
|
||||||
foreach(factory.inject, function(dependency){
|
|
||||||
args.push(inject(dependency));
|
|
||||||
});
|
|
||||||
servicesCache[name] = service = factory.apply(instance, args);
|
|
||||||
}
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(services, function(_, name){
|
|
||||||
var service = inject(name);
|
|
||||||
if (service) {
|
|
||||||
setter(instance, name, service);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
src/angular-bootstrap.js
vendored
1
src/angular-bootstrap.js
vendored
|
|
@ -41,6 +41,7 @@
|
||||||
addScript("/JSON.js");
|
addScript("/JSON.js");
|
||||||
addScript("/Compiler.js");
|
addScript("/Compiler.js");
|
||||||
addScript("/Scope.js");
|
addScript("/Scope.js");
|
||||||
|
addScript("/Injector.js");
|
||||||
addScript("/jqLite.js");
|
addScript("/jqLite.js");
|
||||||
addScript("/Parser.js");
|
addScript("/Parser.js");
|
||||||
addScript("/Resource.js");
|
addScript("/Resource.js");
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?([^\?#]+)(\?([^#]*))?(#(.*))?$/,
|
var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?([^\?#]+)(\?([^#]*))?(#(.*))?$/,
|
||||||
HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/,
|
HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/,
|
||||||
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21};
|
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21},
|
||||||
|
EAGER = 'eager',
|
||||||
|
EAGER_PUBLISHED = EAGER + '-published';
|
||||||
|
|
||||||
angularService("$window", bind(window, identity, window));
|
function angularServiceInject(name, fn, inject, eager) {
|
||||||
angularService("$document", function(window){
|
angularService(name, fn, {$inject:inject, $creation:eager});
|
||||||
|
}
|
||||||
|
|
||||||
|
angularServiceInject("$window", bind(window, identity, window), [], EAGER_PUBLISHED);
|
||||||
|
angularServiceInject("$document", function(window){
|
||||||
return jqLite(window.document);
|
return jqLite(window.document);
|
||||||
}, {inject:['$window']});
|
}, ['$window'], EAGER_PUBLISHED);
|
||||||
|
|
||||||
angularService("$location", function(browser){
|
angularServiceInject("$location", function(browser){
|
||||||
var scope = this,
|
var scope = this,
|
||||||
location = {parse:parseUrl, toString:toString, update:update},
|
location = {parse:parseUrl, toString:toString, update:update},
|
||||||
lastLocation = {};
|
lastLocation = {};
|
||||||
|
|
@ -92,9 +98,9 @@ angularService("$location", function(browser){
|
||||||
update();
|
update();
|
||||||
return location.href;
|
return location.href;
|
||||||
}
|
}
|
||||||
}, {inject: ['$browser']});
|
}, ['$browser'], EAGER_PUBLISHED);
|
||||||
|
|
||||||
angularService("$log", function($window){
|
angularServiceInject("$log", function($window){
|
||||||
var console = $window.console || {log: noop, warn: noop, info: noop, error: noop},
|
var console = $window.console || {log: noop, warn: noop, info: noop, error: noop},
|
||||||
log = console.log || noop;
|
log = console.log || noop;
|
||||||
return {
|
return {
|
||||||
|
|
@ -103,15 +109,15 @@ angularService("$log", function($window){
|
||||||
info: bind(console, console.info || log),
|
info: bind(console, console.info || log),
|
||||||
error: bind(console, console.error || log)
|
error: bind(console, console.error || log)
|
||||||
};
|
};
|
||||||
}, {inject:['$window']});
|
}, ['$window'], EAGER_PUBLISHED);
|
||||||
|
|
||||||
angularService('$exceptionHandler', function($log){
|
angularServiceInject('$exceptionHandler', function($log){
|
||||||
return function(e) {
|
return function(e) {
|
||||||
$log.error(e);
|
$log.error(e);
|
||||||
};
|
};
|
||||||
}, {inject:['$log']});
|
}, ['$log'], EAGER_PUBLISHED);
|
||||||
|
|
||||||
angularService("$hover", function(browser, document) {
|
angularServiceInject("$hover", function(browser, document) {
|
||||||
var tooltip, self = this, error, width = 300, arrowWidth = 10, body = jqLite(document[0].body);
|
var tooltip, self = this, error, width = 300, arrowWidth = 10, body = jqLite(document[0].body);
|
||||||
browser.hover(function(element, show){
|
browser.hover(function(element, show){
|
||||||
if (show && (error = element.attr(NG_EXCEPTION) || element.attr(NG_VALIDATION_ERROR))) {
|
if (show && (error = element.attr(NG_EXCEPTION) || element.attr(NG_VALIDATION_ERROR))) {
|
||||||
|
|
@ -155,14 +161,13 @@ angularService("$hover", function(browser, document) {
|
||||||
tooltip = _null;
|
tooltip = _null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, {inject:['$browser', '$document']});
|
}, ['$browser', '$document'], EAGER);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Keeps references to all invalid widgets found during validation. Can be queried to find if there
|
/* Keeps references to all invalid widgets found during validation. Can be queried to find if there
|
||||||
* are invalid widgets currently displayed
|
* are invalid widgets currently displayed
|
||||||
*/
|
*/
|
||||||
angularService("$invalidWidgets", function(){
|
angularServiceInject("$invalidWidgets", function(){
|
||||||
var invalidWidgets = [];
|
var invalidWidgets = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -217,7 +222,7 @@ angularService("$invalidWidgets", function(){
|
||||||
}
|
}
|
||||||
|
|
||||||
return invalidWidgets;
|
return invalidWidgets;
|
||||||
});
|
}, [], EAGER_PUBLISHED);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -244,7 +249,7 @@ function switchRouteMatcher(on, when, dstName) {
|
||||||
return match ? dst : _null;
|
return match ? dst : _null;
|
||||||
}
|
}
|
||||||
|
|
||||||
angularService('$route', function(location){
|
angularServiceInject('$route', function(location){
|
||||||
var routes = {},
|
var routes = {},
|
||||||
onChange = [],
|
onChange = [],
|
||||||
matcher = switchRouteMatcher,
|
matcher = switchRouteMatcher,
|
||||||
|
|
@ -284,9 +289,9 @@ angularService('$route', function(location){
|
||||||
}
|
}
|
||||||
this.$watch(function(){return dirty + location.hash;}, updateRoute);
|
this.$watch(function(){return dirty + location.hash;}, updateRoute);
|
||||||
return $route;
|
return $route;
|
||||||
}, {inject: ['$location']});
|
}, ['$location']);
|
||||||
|
|
||||||
angularService('$xhr', function($browser, $error, $log){
|
angularServiceInject('$xhr', function($browser, $error, $log){
|
||||||
var self = this;
|
var self = this;
|
||||||
return function(method, url, post, callback){
|
return function(method, url, post, callback){
|
||||||
if (isFunction(post)) {
|
if (isFunction(post)) {
|
||||||
|
|
@ -315,15 +320,15 @@ angularService('$xhr', function($browser, $error, $log){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, {inject:['$browser', '$xhr.error', '$log']});
|
}, ['$browser', '$xhr.error', '$log']);
|
||||||
|
|
||||||
angularService('$xhr.error', function($log){
|
angularServiceInject('$xhr.error', function($log){
|
||||||
return function(request, response){
|
return function(request, response){
|
||||||
$log.error('ERROR: XHR: ' + request.url, request, response);
|
$log.error('ERROR: XHR: ' + request.url, request, response);
|
||||||
};
|
};
|
||||||
}, {inject:['$log']});
|
}, ['$log']);
|
||||||
|
|
||||||
angularService('$xhr.bulk', function($xhr, $error, $log){
|
angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
|
||||||
var requests = [],
|
var requests = [],
|
||||||
scope = this;
|
scope = this;
|
||||||
function bulkXHR(method, url, post, callback) {
|
function bulkXHR(method, url, post, callback) {
|
||||||
|
|
@ -371,9 +376,9 @@ angularService('$xhr.bulk', function($xhr, $error, $log){
|
||||||
};
|
};
|
||||||
this.$onEval(PRIORITY_LAST, bulkXHR.flush);
|
this.$onEval(PRIORITY_LAST, bulkXHR.flush);
|
||||||
return bulkXHR;
|
return bulkXHR;
|
||||||
}, {inject:['$xhr', '$xhr.error', '$log']});
|
}, ['$xhr', '$xhr.error', '$log']);
|
||||||
|
|
||||||
angularService('$xhr.cache', function($xhr){
|
angularServiceInject('$xhr.cache', function($xhr){
|
||||||
var inflight = {}, self = this;
|
var inflight = {}, self = this;
|
||||||
function cache(method, url, post, callback, verifyCache){
|
function cache(method, url, post, callback, verifyCache){
|
||||||
if (isFunction(post)) {
|
if (isFunction(post)) {
|
||||||
|
|
@ -415,12 +420,12 @@ angularService('$xhr.cache', function($xhr){
|
||||||
cache.data = {};
|
cache.data = {};
|
||||||
cache.delegate = $xhr;
|
cache.delegate = $xhr;
|
||||||
return cache;
|
return cache;
|
||||||
}, {inject:['$xhr.bulk']});
|
}, ['$xhr.bulk']);
|
||||||
|
|
||||||
angularService('$resource', function($xhr){
|
angularServiceInject('$resource', function($xhr){
|
||||||
var resource = new ResourceFactory($xhr);
|
var resource = new ResourceFactory($xhr);
|
||||||
return bind(resource, resource.route);
|
return bind(resource, resource.route);
|
||||||
}, {inject: ['$xhr.cache']});
|
}, ['$xhr.cache']);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -430,7 +435,7 @@ angularService('$resource', function($xhr){
|
||||||
* Only a simple Object is exposed and by adding or removing properties to/from this object, new
|
* Only a simple Object is exposed and by adding or removing properties to/from this object, new
|
||||||
* cookies are created or deleted from the browser at the end of the current eval.
|
* cookies are created or deleted from the browser at the end of the current eval.
|
||||||
*/
|
*/
|
||||||
angularService('$cookies', function($browser) {
|
angularServiceInject('$cookies', function($browser) {
|
||||||
var rootScope = this,
|
var rootScope = this,
|
||||||
cookies = {},
|
cookies = {},
|
||||||
lastCookies = {},
|
lastCookies = {},
|
||||||
|
|
@ -499,14 +504,14 @@ angularService('$cookies', function($browser) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {inject: ['$browser']});
|
}, ['$browser'], EAGER_PUBLISHED);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $cookieStore provides a key-value (string-object) storage that is backed by session cookies.
|
* $cookieStore provides a key-value (string-object) storage that is backed by session cookies.
|
||||||
* Objects put or retrieved from this storage are automatically serialized or deserialized.
|
* Objects put or retrieved from this storage are automatically serialized or deserialized.
|
||||||
*/
|
*/
|
||||||
angularService('$cookieStore', function($store) {
|
angularServiceInject('$cookieStore', function($store) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get: function(/**string*/key) {
|
get: function(/**string*/key) {
|
||||||
|
|
@ -522,4 +527,4 @@ angularService('$cookieStore', function($store) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}, {inject: ['$cookies']});
|
}, ['$cookies'], EAGER_PUBLISHED);
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ angularWidget('ng:include', function(element){
|
||||||
this.directives(true);
|
this.directives(true);
|
||||||
} else {
|
} else {
|
||||||
element[0]['ng:compiled'] = true;
|
element[0]['ng:compiled'] = true;
|
||||||
return function(element){
|
return extend(function(xhr, element){
|
||||||
var scope = this, childScope;
|
var scope = this, childScope;
|
||||||
var changeCounter = 0;
|
var changeCounter = 0;
|
||||||
function incrementChange(){ changeCounter++;}
|
function incrementChange(){ changeCounter++;}
|
||||||
|
|
@ -266,7 +266,7 @@ angularWidget('ng:include', function(element){
|
||||||
var src = this.$eval(srcExp),
|
var src = this.$eval(srcExp),
|
||||||
useScope = this.$eval(scopeExp);
|
useScope = this.$eval(scopeExp);
|
||||||
if (src) {
|
if (src) {
|
||||||
scope.$xhr.cache('GET', src, function(code, response){
|
xhr('GET', src, function(code, response){
|
||||||
element.html(response);
|
element.html(response);
|
||||||
childScope = useScope || createScope(scope);
|
childScope = useScope || createScope(scope);
|
||||||
compiler.compile(element)(element, childScope);
|
compiler.compile(element)(element, childScope);
|
||||||
|
|
@ -276,7 +276,7 @@ angularWidget('ng:include', function(element){
|
||||||
element.html('');
|
element.html('');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}, {$inject:['$xhr.cache']});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
71
test/InjectorSpec.js
Normal file
71
test/InjectorSpec.js
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
describe('injector', function(){
|
||||||
|
var providers;
|
||||||
|
var cache;
|
||||||
|
var inject;
|
||||||
|
var scope;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
providers = extensionMap({}, 'providers');
|
||||||
|
cache = {};
|
||||||
|
scope = {};
|
||||||
|
inject = createInjector(scope, providers, cache);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return same instance from calling provider", function(){
|
||||||
|
providers('text', function(){ return scope.name; });
|
||||||
|
scope.name = 'abc';
|
||||||
|
expect(inject('text')).toEqual('abc');
|
||||||
|
expect(cache.text).toEqual('abc');
|
||||||
|
scope.name = 'deleted';
|
||||||
|
expect(inject('text')).toEqual('abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return an array of instances", function(){
|
||||||
|
cache.a = 0;
|
||||||
|
providers('b', function(){return 2;});
|
||||||
|
expect(inject(['a', 'b'])).toEqual([0,2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call function", function(){
|
||||||
|
providers('a', function(){return 1;});
|
||||||
|
providers('b', function(){return 2;});
|
||||||
|
var args;
|
||||||
|
function fn(a, b, c, d) {
|
||||||
|
args = [this, a, b, c, d];
|
||||||
|
}
|
||||||
|
fn.$inject = ['a', 'b'];
|
||||||
|
inject(fn, {name:"this"}, 3, 4);
|
||||||
|
expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject providers', function(){
|
||||||
|
providers('a', function(){return this.mi = 'Mi';});
|
||||||
|
providers('b', function(mi){return this.name = mi+'sko';}, {$inject:['a']});
|
||||||
|
expect(inject('b')).toEqual('Misko');
|
||||||
|
expect(scope).toEqual({mi:'Mi', name:'Misko'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide usefull message if no provider', function(){
|
||||||
|
assertThrows("Unknown provider for 'idontexist'.", function(){
|
||||||
|
inject('idontexist');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should autostart eager services', function(){
|
||||||
|
var log = '';
|
||||||
|
providers('eager', function(){log += 'eager;';}, {$creation: 'eager'});
|
||||||
|
inject();
|
||||||
|
expect(log).toEqual('eager;');
|
||||||
|
expect(scope.eager).not.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return a list of published objects', function(){
|
||||||
|
var log = '';
|
||||||
|
providers('eager', function(){log += 'eager;'; return 'pub'; }, {$creation: 'eager-published'});
|
||||||
|
inject();
|
||||||
|
expect(log).toEqual('eager;');
|
||||||
|
expect(scope.eager).toEqual('pub');
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -162,26 +162,30 @@ describe("resource", function() {
|
||||||
|
|
||||||
it('should excersize full stack', function(){
|
it('should excersize full stack', function(){
|
||||||
var scope = angular.compile('<div></div>');
|
var scope = angular.compile('<div></div>');
|
||||||
var Person = scope.$resource('/Person/:id');
|
var $browser = scope.$inject('$browser');
|
||||||
scope.$browser.xhr.expectGET('/Person/123').respond('\n{\nname:\n"misko"\n}\n');
|
var $resource = scope.$inject('$resource');
|
||||||
|
var Person = $resource('/Person/:id');
|
||||||
|
$browser.xhr.expectGET('/Person/123').respond('\n{\nname:\n"misko"\n}\n');
|
||||||
var person = Person.get({id:123});
|
var person = Person.get({id:123});
|
||||||
scope.$browser.xhr.flush();
|
$browser.xhr.flush();
|
||||||
expect(person.name).toEqual('misko');
|
expect(person.name).toEqual('misko');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the same object when verifying the cache', function(){
|
it('should return the same object when verifying the cache', function(){
|
||||||
var scope = angular.compile('<div></div>');
|
var scope = angular.compile('<div></div>');
|
||||||
var Person = scope.$resource('/Person/:id', null, {query: {method:'GET', isArray: true, verifyCache: true}});
|
var $browser = scope.$inject('$browser');
|
||||||
scope.$browser.xhr.expectGET('/Person/123').respond('[\n{\nname:\n"misko"\n}\n]');
|
var $resource = scope.$inject('$resource');
|
||||||
|
var Person = $resource('/Person/:id', null, {query: {method:'GET', isArray: true, verifyCache: true}});
|
||||||
|
$browser.xhr.expectGET('/Person/123').respond('[\n{\nname:\n"misko"\n}\n]');
|
||||||
var person = Person.query({id:123});
|
var person = Person.query({id:123});
|
||||||
scope.$browser.xhr.flush();
|
$browser.xhr.flush();
|
||||||
expect(person[0].name).toEqual('misko');
|
expect(person[0].name).toEqual('misko');
|
||||||
|
|
||||||
scope.$browser.xhr.expectGET('/Person/123').respond('[\n{\nname:\n"rob"\n}\n]');
|
$browser.xhr.expectGET('/Person/123').respond('[\n{\nname:\n"rob"\n}\n]');
|
||||||
var person2 = Person.query({id:123});
|
var person2 = Person.query({id:123});
|
||||||
expect(person2[0].name).toEqual('misko');
|
expect(person2[0].name).toEqual('misko');
|
||||||
var person2Cache = person2;
|
var person2Cache = person2;
|
||||||
scope.$browser.xhr.flush();
|
$browser.xhr.flush();
|
||||||
expect(person2Cache).toEqual(person2);
|
expect(person2Cache).toEqual(person2);
|
||||||
expect(person2[0].name).toEqual('rob');
|
expect(person2[0].name).toEqual('rob');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,10 @@ describe("ScenarioSpec: configuration", function(){
|
||||||
var url = "http://server/#?book=moby";
|
var url = "http://server/#?book=moby";
|
||||||
var scope = compile("<div>{{$location}}</div>");
|
var scope = compile("<div>{{$location}}</div>");
|
||||||
var $location = scope.$location;
|
var $location = scope.$location;
|
||||||
|
var $browser = scope.$inject('$browser');
|
||||||
expect($location.hashSearch.book).toBeUndefined();
|
expect($location.hashSearch.book).toBeUndefined();
|
||||||
scope.$browser.setUrl(url);
|
$browser.setUrl(url);
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
expect($location.hashSearch.book).toEqual('moby');
|
expect($location.hashSearch.book).toEqual('moby');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,27 @@
|
||||||
describe('scope/model', function(){
|
describe('scope/model', function(){
|
||||||
|
|
||||||
|
var temp;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
temp = window.temp = {};
|
||||||
|
temp.InjectController = function(exampleService, extra) {
|
||||||
|
this.localService = exampleService;
|
||||||
|
this.extra = extra;
|
||||||
|
this.$root.injectController = this;
|
||||||
|
};
|
||||||
|
temp.InjectController.$inject = ["exampleService"];
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
window.temp = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
it('should create a scope with parent', function(){
|
it('should create a scope with parent', function(){
|
||||||
var model = createScope({name:'Misko'});
|
var model = createScope({name:'Misko'});
|
||||||
expect(model.name).toEqual('Misko');
|
expect(model.name).toEqual('Misko');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have $get/set$/parent$', function(){
|
it('should have $get/$set/$parent', function(){
|
||||||
var parent = {};
|
var parent = {};
|
||||||
var model = createScope(parent);
|
var model = createScope(parent);
|
||||||
model.$set('name', 'adam');
|
model.$set('name', 'adam');
|
||||||
|
|
@ -138,40 +154,6 @@ describe('scope/model', function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('service injection', function(){
|
|
||||||
it('should inject services', function(){
|
|
||||||
var scope = createScope(null, {
|
|
||||||
service:function(){
|
|
||||||
return "ABC";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(scope.service).toEqual("ABC");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should inject arugments', function(){
|
|
||||||
var scope = createScope(null, {
|
|
||||||
name:function(){
|
|
||||||
return "misko";
|
|
||||||
},
|
|
||||||
greet: extend(function(name) {
|
|
||||||
return 'hello ' + name;
|
|
||||||
}, {inject:['name']})
|
|
||||||
});
|
|
||||||
expect(scope.greet).toEqual("hello misko");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error on missing dependency', function(){
|
|
||||||
try {
|
|
||||||
createScope(null, {
|
|
||||||
greet: extend(function(name) {
|
|
||||||
}, {inject:['name']})
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
expect(e).toEqual("Don't know how to inject 'name'.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getterFn', function(){
|
describe('getterFn', function(){
|
||||||
it('should get chain', function(){
|
it('should get chain', function(){
|
||||||
expect(getterFn('a.b')(undefined)).toEqual(undefined);
|
expect(getterFn('a.b')(undefined)).toEqual(undefined);
|
||||||
|
|
@ -215,4 +197,27 @@ describe('scope/model', function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('$new', function(){
|
||||||
|
it('should $new should create new child scope and $become controller', function(){
|
||||||
|
var parent = createScope(null, {exampleService: function(){return 'Example Service';}});
|
||||||
|
var child = parent.$new(temp.InjectController, 10);
|
||||||
|
expect(child.localService).toEqual('Example Service');
|
||||||
|
expect(child.extra).toEqual(10);
|
||||||
|
|
||||||
|
child.$onEval(function(){ this.run = true; });
|
||||||
|
parent.$eval();
|
||||||
|
expect(child.run).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('$become', function(){
|
||||||
|
it('should inject properties on controller defined in $inject', function(){
|
||||||
|
var parent = createScope(null, {exampleService: function(){return 'Example Service';}});
|
||||||
|
var child = createScope(parent);
|
||||||
|
child.$become(temp.InjectController, 10);
|
||||||
|
expect(child.localService).toEqual('Example Service');
|
||||||
|
expect(child.extra).toEqual(10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,9 @@ describe('Validator:asynchronous', function(){
|
||||||
if (self.$element) self.$element.remove();
|
if (self.$element) self.$element.remove();
|
||||||
var oldCache = jqCache;
|
var oldCache = jqCache;
|
||||||
jqCache = {};
|
jqCache = {};
|
||||||
|
if (size(oldCache)) {
|
||||||
|
dump(oldCache);
|
||||||
|
}
|
||||||
expect(size(oldCache)).toEqual(0);
|
expect(size(oldCache)).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ describe("directives", function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support nested controllers', function(){
|
it('should support nested controllers', function(){
|
||||||
temp.ChildGreeter = function() {
|
temp.ChildGreeter = function(){
|
||||||
this.greeting = 'hey';
|
this.greeting = 'hey';
|
||||||
this.$root.childGreeter = this;
|
this.$root.childGreeter = this;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
describe("service", function(){
|
describe("service", function(){
|
||||||
var scope, $xhrError, $log, mockServices;
|
var scope, $xhrError, $log, mockServices, inject, $browser, $browserXhr, $xhrBulk, $xhr, $route;
|
||||||
|
|
||||||
beforeEach(function(){
|
beforeEach(function(){
|
||||||
$xhrError = jasmine.createSpy('$xhr.error');
|
$xhrError = jasmine.createSpy('$xhr.error');
|
||||||
$log = {};
|
$log = {};
|
||||||
scope = createScope(null, angularService, {
|
scope = createScope({}, angularService, {
|
||||||
'$xhr.error': $xhrError,
|
'$xhr.error': $xhrError,
|
||||||
'$log': $log
|
'$log': $log
|
||||||
});
|
});
|
||||||
|
inject = scope.$inject;
|
||||||
|
$browser = inject('$browser');
|
||||||
|
$browserXhr = $browser.xhr;
|
||||||
|
$xhrBulk = scope.$inject('$xhr.bulk');
|
||||||
|
$xhr = scope.$inject('$xhr');
|
||||||
|
$route = scope.$inject('$route');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function(){
|
afterEach(function(){
|
||||||
|
|
@ -38,7 +44,7 @@ describe("service", function(){
|
||||||
function warn(){ logger+= 'warn;'; }
|
function warn(){ logger+= 'warn;'; }
|
||||||
function info(){ logger+= 'info;'; }
|
function info(){ logger+= 'info;'; }
|
||||||
function error(){ logger+= 'error;'; }
|
function error(){ logger+= 'error;'; }
|
||||||
var scope = createScope(null, angularService, {$window: {console:{log:log, warn:warn, info:info, error:error}}, $document:[{cookie:''}]});
|
var scope = createScope({}, angularService, {$window: {console:{log:log, warn:warn, info:info, error:error}}, $document:[{cookie:''}]});
|
||||||
scope.$log.log();
|
scope.$log.log();
|
||||||
scope.$log.warn();
|
scope.$log.warn();
|
||||||
scope.$log.info();
|
scope.$log.info();
|
||||||
|
|
@ -49,7 +55,7 @@ describe("service", function(){
|
||||||
it('should use console.log if other not present', function(){
|
it('should use console.log if other not present', function(){
|
||||||
var logger = "";
|
var logger = "";
|
||||||
function log(){ logger+= 'log;'; }
|
function log(){ logger+= 'log;'; }
|
||||||
var scope = createScope(null, angularService, {$window: {console:{log:log}}, $document:[{cookie:''}]});
|
var scope = createScope({}, angularService, {$window: {console:{log:log}}, $document:[{cookie:''}]});
|
||||||
scope.$log.log();
|
scope.$log.log();
|
||||||
scope.$log.warn();
|
scope.$log.warn();
|
||||||
scope.$log.info();
|
scope.$log.info();
|
||||||
|
|
@ -58,7 +64,7 @@ describe("service", function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use noop if no console', function(){
|
it('should use noop if no console', function(){
|
||||||
var scope = createScope(null, angularService, {$window: {}, $document:[{cookie:''}]});
|
var scope = createScope({}, angularService, {$window: {}, $document:[{cookie:''}]});
|
||||||
scope.$log.log();
|
scope.$log.log();
|
||||||
scope.$log.warn();
|
scope.$log.warn();
|
||||||
scope.$log.info();
|
scope.$log.info();
|
||||||
|
|
@ -182,49 +188,47 @@ describe("service", function(){
|
||||||
function BookChapter() {
|
function BookChapter() {
|
||||||
this.log = '<init>';
|
this.log = '<init>';
|
||||||
}
|
}
|
||||||
BookChapter.prototype.init = function(){
|
|
||||||
log += 'init();';
|
|
||||||
};
|
|
||||||
var scope = compile('<div></div>').$init();
|
var scope = compile('<div></div>').$init();
|
||||||
scope.$route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'});
|
var $route = scope.$inject('$route');
|
||||||
scope.$route.when('/Blank');
|
$route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'});
|
||||||
scope.$route.onChange(function(){
|
$route.when('/Blank');
|
||||||
|
$route.onChange(function(){
|
||||||
log += 'onChange();';
|
log += 'onChange();';
|
||||||
});
|
});
|
||||||
scope.$location.parse('http://server#/Book/Moby/Chapter/Intro?p=123');
|
scope.$location.parse('http://server#/Book/Moby/Chapter/Intro?p=123');
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(log).toEqual('onChange();init();');
|
expect(log).toEqual('onChange();');
|
||||||
expect(scope.$route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'});
|
expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'});
|
||||||
expect(scope.$route.current.scope.log).toEqual('<init>');
|
expect($route.current.scope.log).toEqual('<init>');
|
||||||
var lastId = scope.$route.current.scope.$id;
|
var lastId = $route.current.scope.$id;
|
||||||
|
|
||||||
log = '';
|
log = '';
|
||||||
scope.$location.parse('http://server#/Blank?ignore');
|
scope.$location.parse('http://server#/Blank?ignore');
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(log).toEqual('onChange();');
|
expect(log).toEqual('onChange();');
|
||||||
expect(scope.$route.current.params).toEqual({ignore:true});
|
expect($route.current.params).toEqual({ignore:true});
|
||||||
expect(scope.$route.current.scope.$id).not.toEqual(lastId);
|
expect($route.current.scope.$id).not.toEqual(lastId);
|
||||||
|
|
||||||
log = '';
|
log = '';
|
||||||
scope.$location.parse('http://server#/NONE');
|
scope.$location.parse('http://server#/NONE');
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(log).toEqual('onChange();');
|
expect(log).toEqual('onChange();');
|
||||||
expect(scope.$route.current).toEqual(null);
|
expect($route.current).toEqual(null);
|
||||||
|
|
||||||
scope.$route.when('/NONE', {template:'instant update'});
|
$route.when('/NONE', {template:'instant update'});
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(scope.$route.current.template).toEqual('instant update');
|
expect($route.current.template).toEqual('instant update');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$resource', function(){
|
describe('$resource', function(){
|
||||||
it('should publish to root scope', function(){
|
it('should publish to root scope', function(){
|
||||||
expect(scope.$resource).toBeTruthy();
|
expect(scope.$inject('$resource')).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$xhr', function(){
|
describe('$xhr', function(){
|
||||||
var log, xhr;
|
var log;
|
||||||
function callback(code, response) {
|
function callback(code, response) {
|
||||||
expect(code).toEqual(200);
|
expect(code).toEqual(200);
|
||||||
log = log + toJson(response) + ';';
|
log = log + toJson(response) + ';';
|
||||||
|
|
@ -232,27 +236,26 @@ describe("service", function(){
|
||||||
|
|
||||||
beforeEach(function(){
|
beforeEach(function(){
|
||||||
log = '';
|
log = '';
|
||||||
xhr = scope.$browser.xhr;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should forward the request to $browser and decode JSON', function(){
|
it('should forward the request to $browser and decode JSON', function(){
|
||||||
xhr.expectGET('/reqGET').respond('first');
|
$browserXhr.expectGET('/reqGET').respond('first');
|
||||||
xhr.expectGET('/reqGETjson').respond('["second"]');
|
$browserXhr.expectGET('/reqGETjson').respond('["second"]');
|
||||||
xhr.expectPOST('/reqPOST', {post:'data'}).respond('third');
|
$browserXhr.expectPOST('/reqPOST', {post:'data'}).respond('third');
|
||||||
|
|
||||||
scope.$xhr('GET', '/reqGET', null, callback);
|
$xhr('GET', '/reqGET', null, callback);
|
||||||
scope.$xhr('GET', '/reqGETjson', null, callback);
|
$xhr('GET', '/reqGETjson', null, callback);
|
||||||
scope.$xhr('POST', '/reqPOST', {post:'data'}, callback);
|
$xhr('POST', '/reqPOST', {post:'data'}, callback);
|
||||||
|
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
|
|
||||||
expect(log).toEqual('"third";["second"];"first";');
|
expect(log).toEqual('"third";["second"];"first";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle non 200 status codes by forwarding to error handler', function(){
|
it('should handle non 200 status codes by forwarding to error handler', function(){
|
||||||
xhr.expectPOST('/req', 'MyData').respond(500, 'MyError');
|
$browserXhr.expectPOST('/req', 'MyData').respond(500, 'MyError');
|
||||||
scope.$xhr('POST', '/req', 'MyData', callback);
|
$xhr('POST', '/req', 'MyData', callback);
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
var cb = $xhrError.mostRecentCall.args[0].callback;
|
var cb = $xhrError.mostRecentCall.args[0].callback;
|
||||||
expect(typeof cb).toEqual($function);
|
expect(typeof cb).toEqual($function);
|
||||||
expect($xhrError).wasCalledWith(
|
expect($xhrError).wasCalledWith(
|
||||||
|
|
@ -262,45 +265,45 @@ describe("service", function(){
|
||||||
|
|
||||||
it('should handle exceptions in callback', function(){
|
it('should handle exceptions in callback', function(){
|
||||||
$log.error = jasmine.createSpy('$log.error');
|
$log.error = jasmine.createSpy('$log.error');
|
||||||
xhr.expectGET('/reqGET').respond('first');
|
$browserXhr.expectGET('/reqGET').respond('first');
|
||||||
scope.$xhr('GET', '/reqGET', null, function(){ throw "MyException"; });
|
$xhr('GET', '/reqGET', null, function(){ throw "MyException"; });
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
|
|
||||||
expect($log.error).wasCalledWith("MyException");
|
expect($log.error).wasCalledWith("MyException");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('bulk', function(){
|
describe('bulk', function(){
|
||||||
it('should collect requests', function(){
|
it('should collect requests', function(){
|
||||||
scope.$xhr.bulk.urls["/"] = {match:/.*/};
|
$xhrBulk.urls["/"] = {match:/.*/};
|
||||||
scope.$xhr.bulk('GET', '/req1', null, callback);
|
$xhrBulk('GET', '/req1', null, callback);
|
||||||
scope.$xhr.bulk('POST', '/req2', {post:'data'}, callback);
|
$xhrBulk('POST', '/req2', {post:'data'}, callback);
|
||||||
|
|
||||||
xhr.expectPOST('/', {
|
$browserXhr.expectPOST('/', {
|
||||||
requests:[{method:'GET', url:'/req1', data: null},
|
requests:[{method:'GET', url:'/req1', data: null},
|
||||||
{method:'POST', url:'/req2', data:{post:'data'} }]
|
{method:'POST', url:'/req2', data:{post:'data'} }]
|
||||||
}).respond([
|
}).respond([
|
||||||
{status:200, response:'first'},
|
{status:200, response:'first'},
|
||||||
{status:200, response:'second'}
|
{status:200, response:'second'}
|
||||||
]);
|
]);
|
||||||
scope.$xhr.bulk.flush(function(){ log += 'DONE';});
|
$xhrBulk.flush(function(){ log += 'DONE';});
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
expect(log).toEqual('"first";"second";DONE');
|
expect(log).toEqual('"first";"second";DONE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle non 200 status code by forwarding to error handler', function(){
|
it('should handle non 200 status code by forwarding to error handler', function(){
|
||||||
scope.$xhr.bulk.urls['/'] = {match:/.*/};
|
$xhrBulk.urls['/'] = {match:/.*/};
|
||||||
scope.$xhr.bulk('GET', '/req1', null, callback);
|
$xhrBulk('GET', '/req1', null, callback);
|
||||||
scope.$xhr.bulk('POST', '/req2', {post:'data'}, callback);
|
$xhrBulk('POST', '/req2', {post:'data'}, callback);
|
||||||
|
|
||||||
xhr.expectPOST('/', {
|
$browserXhr.expectPOST('/', {
|
||||||
requests:[{method:'GET', url:'/req1', data: null},
|
requests:[{method:'GET', url:'/req1', data: null},
|
||||||
{method:'POST', url:'/req2', data:{post:'data'} }]
|
{method:'POST', url:'/req2', data:{post:'data'} }]
|
||||||
}).respond([
|
}).respond([
|
||||||
{status:404, response:'NotFound'},
|
{status:404, response:'NotFound'},
|
||||||
{status:200, response:'second'}
|
{status:200, response:'second'}
|
||||||
]);
|
]);
|
||||||
scope.$xhr.bulk.flush(function(){ log += 'DONE';});
|
$xhrBulk.flush(function(){ log += 'DONE';});
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
|
|
||||||
expect($xhrError).wasCalled();
|
expect($xhrError).wasCalled();
|
||||||
var cb = $xhrError.mostRecentCall.args[0].callback;
|
var cb = $xhrError.mostRecentCall.args[0].callback;
|
||||||
|
|
@ -315,29 +318,29 @@ describe("service", function(){
|
||||||
|
|
||||||
describe('cache', function(){
|
describe('cache', function(){
|
||||||
var cache;
|
var cache;
|
||||||
beforeEach(function(){ cache = scope.$xhr.cache; });
|
beforeEach(function(){ cache = scope.$inject('$xhr.cache'); });
|
||||||
|
|
||||||
it('should cache requests', function(){
|
it('should cache requests', function(){
|
||||||
xhr.expectGET('/url').respond('first');
|
$browserXhr.expectGET('/url').respond('first');
|
||||||
cache('GET', '/url', null, callback);
|
cache('GET', '/url', null, callback);
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
xhr.expectGET('/url').respond('ERROR');
|
$browserXhr.expectGET('/url').respond('ERROR');
|
||||||
cache('GET', '/url', null, callback);
|
cache('GET', '/url', null, callback);
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
expect(log).toEqual('"first";"first";');
|
expect(log).toEqual('"first";"first";');
|
||||||
cache('GET', '/url', null, callback, false);
|
cache('GET', '/url', null, callback, false);
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
expect(log).toEqual('"first";"first";"first";');
|
expect(log).toEqual('"first";"first";"first";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first return cache request, then return server request', function(){
|
it('should first return cache request, then return server request', function(){
|
||||||
xhr.expectGET('/url').respond('first');
|
$browserXhr.expectGET('/url').respond('first');
|
||||||
cache('GET', '/url', null, callback, true);
|
cache('GET', '/url', null, callback, true);
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
xhr.expectGET('/url').respond('ERROR');
|
$browserXhr.expectGET('/url').respond('ERROR');
|
||||||
cache('GET', '/url', null, callback, true);
|
cache('GET', '/url', null, callback, true);
|
||||||
expect(log).toEqual('"first";"first";');
|
expect(log).toEqual('"first";"first";');
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
expect(log).toEqual('"first";"first";"ERROR";');
|
expect(log).toEqual('"first";"first";"ERROR";');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -350,12 +353,12 @@ describe("service", function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep track of in flight requests and request only once', function(){
|
it('should keep track of in flight requests and request only once', function(){
|
||||||
scope.$xhr.bulk.urls['/bulk'] = {
|
scope.$inject('$xhr.bulk').urls['/bulk'] = {
|
||||||
match:function(url){
|
match:function(url){
|
||||||
return url == '/url';
|
return url == '/url';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
xhr.expectPOST('/bulk', {
|
$browserXhr.expectPOST('/bulk', {
|
||||||
requests:[{method:'GET', url:'/url', data: null}]
|
requests:[{method:'GET', url:'/url', data: null}]
|
||||||
}).respond([
|
}).respond([
|
||||||
{status:200, response:'123'}
|
{status:200, response:'123'}
|
||||||
|
|
@ -363,12 +366,12 @@ describe("service", function(){
|
||||||
cache('GET', '/url', null, callback);
|
cache('GET', '/url', null, callback);
|
||||||
cache('GET', '/url', null, callback);
|
cache('GET', '/url', null, callback);
|
||||||
cache.delegate.flush();
|
cache.delegate.flush();
|
||||||
xhr.flush();
|
$browserXhr.flush();
|
||||||
expect(log).toEqual('"123";"123";');
|
expect(log).toEqual('"123";"123";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should clear cache on non GET', function(){
|
it('should clear cache on non GET', function(){
|
||||||
xhr.expectPOST('abc', {}).respond({});
|
$browserXhr.expectPOST('abc', {}).respond({});
|
||||||
cache.data.url = {value:123};
|
cache.data.url = {value:123};
|
||||||
cache('POST', 'abc', {});
|
cache('POST', 'abc', {});
|
||||||
expect(cache.data.url).toBeUndefined();
|
expect(cache.data.url).toBeUndefined();
|
||||||
|
|
@ -380,12 +383,12 @@ describe("service", function(){
|
||||||
|
|
||||||
describe('$cookies', function() {
|
describe('$cookies', function() {
|
||||||
|
|
||||||
var scope;
|
var scope, $browser;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
var browser = new MockBrowser();
|
$browser = new MockBrowser();
|
||||||
browser.cookieHash['preexisting'] = 'oldCookie';
|
$browser.cookieHash['preexisting'] = 'oldCookie';
|
||||||
scope = createScope(null, angularService, {$browser: browser});
|
scope = createScope(null, angularService, {$browser: $browser});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -393,19 +396,19 @@ describe("service", function(){
|
||||||
function(){
|
function(){
|
||||||
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
||||||
|
|
||||||
// access internal cookie storage of the browser mock directly to simulate behavior of
|
// access internal cookie storage of the browser mock directly to simulate behavior of
|
||||||
// document.cookie
|
// document.cookie
|
||||||
scope.$browser.cookieHash['brandNew'] = 'cookie';
|
$browser.cookieHash['brandNew'] = 'cookie';
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
|
|
||||||
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'});
|
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'});
|
||||||
|
|
||||||
scope.$browser.cookieHash['brandNew'] = 'cookie2';
|
$browser.cookieHash['brandNew'] = 'cookie2';
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'});
|
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'});
|
||||||
|
|
||||||
delete scope.$browser.cookieHash['brandNew'];
|
delete $browser.cookieHash['brandNew'];
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -414,13 +417,13 @@ describe("service", function(){
|
||||||
scope.$cookies.oatmealCookie = 'nom nom';
|
scope.$cookies.oatmealCookie = 'nom nom';
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
|
|
||||||
expect(scope.$browser.cookies()).
|
expect($browser.cookies()).
|
||||||
toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});
|
toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});
|
||||||
|
|
||||||
scope.$cookies.oatmealCookie = 'gone';
|
scope.$cookies.oatmealCookie = 'gone';
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
|
|
||||||
expect(scope.$browser.cookies()).
|
expect($browser.cookies()).
|
||||||
toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'});
|
toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -428,7 +431,7 @@ describe("service", function(){
|
||||||
it('should ignore non-string values when asked to create a cookie', function() {
|
it('should ignore non-string values when asked to create a cookie', function() {
|
||||||
scope.$cookies.nonString = [1, 2, 3];
|
scope.$cookies.nonString = [1, 2, 3];
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(scope.$browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
||||||
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -438,21 +441,21 @@ describe("service", function(){
|
||||||
scope.$cookies.undefVal = undefined;
|
scope.$cookies.undefVal = undefined;
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
|
|
||||||
expect(scope.$browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should remove a cookie when a $cookies property is deleted', function() {
|
it('should remove a cookie when a $cookies property is deleted', function() {
|
||||||
scope.$cookies.oatmealCookie = 'nom nom';
|
scope.$cookies.oatmealCookie = 'nom nom';
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
expect(scope.$browser.cookies()).
|
expect($browser.cookies()).
|
||||||
toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});
|
toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});
|
||||||
|
|
||||||
delete scope.$cookies.oatmealCookie;
|
delete scope.$cookies.oatmealCookie;
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
|
|
||||||
expect(scope.$browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -485,13 +488,13 @@ describe("service", function(){
|
||||||
it('should serialize objects to json', function() {
|
it('should serialize objects to json', function() {
|
||||||
scope.$cookieStore.put('objectCookie', {id: 123, name: 'blah'});
|
scope.$cookieStore.put('objectCookie', {id: 123, name: 'blah'});
|
||||||
scope.$eval(); //force eval in test
|
scope.$eval(); //force eval in test
|
||||||
expect(scope.$browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'});
|
expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should deserialize json to object', function() {
|
it('should deserialize json to object', function() {
|
||||||
scope.$browser.cookies('objectCookie', '{"id":123,"name":"blah"}');
|
$browser.cookies('objectCookie', '{"id":123,"name":"blah"}');
|
||||||
scope.$browser.poll();
|
$browser.poll();
|
||||||
expect(scope.$cookieStore.get('objectCookie')).toEqual({id: 123, name: 'blah'});
|
expect(scope.$cookieStore.get('objectCookie')).toEqual({id: 123, name: 'blah'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -499,7 +502,7 @@ describe("service", function(){
|
||||||
it('should delete objects from the store when remove is called', function() {
|
it('should delete objects from the store when remove is called', function() {
|
||||||
scope.$cookieStore.put('gonner', { "I'll":"Be Back"});
|
scope.$cookieStore.put('gonner', { "I'll":"Be Back"});
|
||||||
scope.$eval(); //force eval in test
|
scope.$eval(); //force eval in test
|
||||||
expect(scope.$browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'});
|
expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -476,7 +476,7 @@ describe("widget", function(){
|
||||||
scope.childScope = createScope();
|
scope.childScope = createScope();
|
||||||
scope.childScope.name = 'misko';
|
scope.childScope.name = 'misko';
|
||||||
scope.url = 'myUrl';
|
scope.url = 'myUrl';
|
||||||
scope.$xhr.cache.data.myUrl = {value:'{{name}}'};
|
scope.$inject('$xhr.cache').data.myUrl = {value:'{{name}}'};
|
||||||
scope.$init();
|
scope.$init();
|
||||||
expect(element.text()).toEqual('misko');
|
expect(element.text()).toEqual('misko');
|
||||||
});
|
});
|
||||||
|
|
@ -487,7 +487,7 @@ describe("widget", function(){
|
||||||
scope.childScope = createScope();
|
scope.childScope = createScope();
|
||||||
scope.childScope.name = 'igor';
|
scope.childScope.name = 'igor';
|
||||||
scope.url = 'myUrl';
|
scope.url = 'myUrl';
|
||||||
scope.$xhr.cache.data.myUrl = {value:'{{name}}'};
|
scope.$inject('$xhr.cache').data.myUrl = {value:'{{name}}'};
|
||||||
scope.$init();
|
scope.$init();
|
||||||
|
|
||||||
expect(element.text()).toEqual('igor');
|
expect(element.text()).toEqual('igor');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue