diff options
34 files changed, 927 insertions, 665 deletions
diff --git a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc b/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc index c01b04b1..e98eb5e0 100644 --- a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc +++ b/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc @@ -31,8 +31,9 @@ myController.$inject = ['$location', '$log']; <doc:example module="MyServiceModule"> <doc:source> <script type="text/javascript"> -angular.module.MyServiceModule = ['$provide', function($provide){ - $provide.factory('notify', ['$window', function(win) { +angular. + module('MyServiceModule', []). + factory('notify', ['$window', function(win) { var msgs = []; return function(msg) { msgs.push(msg); @@ -42,7 +43,6 @@ angular.module.MyServiceModule = ['$provide', function($provide){ } }; }]); -}]; function myController(notifyService) { this.callNotify = function(msg) { diff --git a/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc b/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc index 5ca76654..43e5a4ae 100644 --- a/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc +++ b/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc @@ -53,7 +53,7 @@ provided by angular's web framework: } // get the main service to kick of the application - angular.injector(batchLogModule).get('routeTemplateMonitor'); + angular.injector([batchLogModule]).get('routeTemplateMonitor'); </pre> Things to notice in this example: diff --git a/docs/content/guide/dev_guide.templates.filters.creating_filters.ngdoc b/docs/content/guide/dev_guide.templates.filters.creating_filters.ngdoc index a8fd2ce7..98b41411 100644 --- a/docs/content/guide/dev_guide.templates.filters.creating_filters.ngdoc +++ b/docs/content/guide/dev_guide.templates.filters.creating_filters.ngdoc @@ -19,8 +19,8 @@ text upper-case and assigns color. <doc:example module="MyReverseModule"> <doc:source> <script type="text/javascript"> - angular.module.MyReverseModule = function ($filterProvider) { - $filterProvider.register('reverse', function() { + angular.module('MyReverseModule', []). + filter('reverse', function() { return function(input, uppercase) { var out = ""; for (var i = 0; i < input.length; i++) { @@ -33,7 +33,6 @@ text upper-case and assigns color. return out; } }); - } function Ctrl() { this.greeting = 'hello'; diff --git a/docs/src/templates/doc_widgets.js b/docs/src/templates/doc_widgets.js index c130add8..db49088d 100644 --- a/docs/src/templates/doc_widgets.js +++ b/docs/src/templates/doc_widgets.js @@ -22,8 +22,9 @@ ' </body>\n' + '</html>'; - angular.widget('doc:example', ['$injector', '$element', function($injector, element){ - this.descend(true); //compile the example code + angular.widget('doc:example', ['$injector', '$browser', '$location', '$element', + function($injector, $browser, $location, element){ + this.descend(false); // do not compile the example code var module = element.attr('module') || ''; //jQuery find() methods in this widget contain primitive selectors on purpose so that we can use @@ -38,30 +39,26 @@ jsfiddle = example.attr('jsfiddle') || true, scenario = element.find('pre').eq(1); //doc-scenario - var tabHtml = - '<ul class="doc-example">'; + var tabs = angular.element('<ul class="doc-example">'); // show source tab, if not disabled if (showSource) { - tabHtml += + tabs.append( '<li class="doc-example-heading"><h3>Source</h3></li>' + '<li class="doc-example-source" ng:non-bindable>' + jsFiddleButton(jsfiddle) + // may or may not have value - '<pre class="brush: js; html-script: true; toolbar: false;"></pre></li>'; + '<pre class="brush: js; html-script: true; toolbar: false;"></pre></li>'); } // show live preview tab - tabHtml += - '<li class="doc-example-heading"><h3>Live Preview</h3></li>' + - '<li class="doc-example-live">' + htmlSrc +'</li>'; + var livePreviewTab; + tabs.append('<li class="doc-example-heading"><h3>Live Preview</h3></li>'); + tabs.append(livePreviewTab = angular.element('<li class="doc-example-live">' + htmlSrc +'</li>')); // show scenario tab, if present if (scenario.text()) { - tabHtml += + tabs.append( '<li class="doc-example-heading"><h3>Scenario Test</h3></li>' + - '<li class="doc-example-scenario"><pre class="brush: js">' + scenario.text() + '</pre></li>'; + '<li class="doc-example-scenario"><pre class="brush: js">' + scenario.text() + '</pre></li>'); } - tabHtml += - '</ul>'; - var tabs = angular.element(tabHtml); tabs.find('li').eq(1).find('pre').text( HTML_TEMPLATE. @@ -82,10 +79,23 @@ alert(e); } - if (module) { - $injector.invoke(null, angular.module[module]); - } + return function() { + var scope = this; + var modules = [ + 'ng', + function($provide) { + $provide.value('$browser', $browser); + $provide.value('$location', $location); + } + ]; + module && modules.push(module); + angular.bootstrap(livePreviewTab, modules).invoke(function($rootScope) { + element.bind('$destroy', scope.$root.$watch(function() { + $rootScope.$digest(); + })); + }); + }; function jsFiddleButton(jsfiddle) { var fixJsFiddleIssue132 = true; diff --git a/example/personalLog/test/personalLogSpec.js b/example/personalLog/test/personalLogSpec.js index 8c4ab291..9393e047 100644 --- a/example/personalLog/test/personalLogSpec.js +++ b/example/personalLog/test/personalLogSpec.js @@ -2,7 +2,7 @@ describe('example.personalLog.LogCtrl', function() { var logCtrl; function createNotesCtrl() { - var injector = angular.injector('ng', 'ngMock'); + var injector = angular.injector(['ng', 'ngMock']); var scope = injector.get('$rootScope'); scope.$cookies = injector.get('$cookies'); return scope.$new(example.personalLog.LogCtrl); diff --git a/src/Angular.js b/src/Angular.js index 74443bd1..0f79d363 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -128,7 +128,7 @@ var $$scope = '$scope', </pre> * * @param {Object|Array} obj Object to iterate over. - * @param {function()} iterator Iterator function. + * @param {Function} iterator Iterator function. * @param {Object=} context Object to become context (`this`) for the iterator function. * @returns {Object|Array} Reference to `obj`. */ @@ -897,12 +897,14 @@ function angularInit(element, bootstrap) { * * @param {Element} element DOM element which is the root of angular application. * @param {Array<String,function>=} modules an array of module declarations. See: {@link angular.module modules} + * @param {angular.module.auta.$injector} the injector; */ function bootstrap(element, modules) { element = jqLite(element); modules = modules || []; modules.unshift('ng'); - createInjector(modules).invoke(null, + var injector = createInjector(modules); + injector.invoke( ['$rootScope', '$compile', '$injector', function(scope, compile, injector){ scope.$apply(function() { element.data('$injector', injector); @@ -910,6 +912,7 @@ function bootstrap(element, modules) { }); }] ); + return injector; } function bindJQuery() { diff --git a/src/AngularPublic.js b/src/AngularPublic.js index ef3d3ccb..4973f574 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -30,7 +30,7 @@ function publishExternalAPI(angular){ 'equals': equals, 'element': jqLite, 'forEach': forEach, - 'injector': function(){ return createInjector(arguments); }, + 'injector': createInjector, 'noop':noop, 'bind':bind, 'toJson': toJson, @@ -58,8 +58,8 @@ function publishExternalAPI(angular){ angularModule('ngLocale', []).service('$locale', $LocaleProvider); } - angularModule('ng', ['ngLocale'], ['$provide', '$injector', - function ngModule($provide, $injector) { + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { // TODO(misko): temporary services to get the compiler working; $provide.value('$textMarkup', angularTextMarkup); $provide.value('$attrMarkup', angularAttrMarkup); diff --git a/src/Injector.js b/src/Injector.js index 8326d645..c9901513 100644 --- a/src/Injector.js +++ b/src/Injector.js @@ -10,7 +10,7 @@ * dependency injection (see {@link guide/dev_guide.di dependency injection}). * - * @param {<string, function()>} modules... A list of module functions or their aliases. See + * @param {Array.<string|Function>} modules A list of module functions or their aliases. See * {@link angular.module}. The `ng` module must be explicitly added. * @returns {function()} Injector function. See {@link angular.module.AUTO.$injector $injector}. * @@ -18,11 +18,11 @@ * Typical usage * <pre> * // create an injector - * var $injector = angular.injector('ng'); + * var $injector = angular.injector(['ng']); * * // use the injector to kick of your application * // use the type inference to auto inject arguments, or use implicit injection - * $injector.invoke(null, function($rootScope, $compile, $document){ + * $injector.invoke(function($rootScope, $compile, $document){ * $compile($document)($rootScope); * $rootScope.$digest(); * }); @@ -113,14 +113,26 @@ function inferInjectionArgs(fn) { /** * @ngdoc method + * @name angular.module.AUTO.$injector#get + * @methodOf angular.module.AUTO.$injector + * + * @description + * Return an instance of the service. + * + * @param {string} name The name of the instance to retrieve. + * @return {*} The instance. + */ + +/** + * @ngdoc method * @name angular.module.AUTO.$injector#invoke * @methodOf angular.module.AUTO.$injector * * @description * Invoke the method and supply the method arguments from the `$injector`. * - * @param {Object} self The `this` for the invoked method. - * @param {function} fn The function to invoke. The function arguments come form the function annotation. + * @param {!function} fn The function to invoke. The function arguments come form the function annotation. + * @param {Object=} self The `this` for the invoked method. * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before * the `$injector` is consulted. * @return the value returned by the invoked `fn` function. @@ -238,29 +250,35 @@ function inferInjectionArgs(fn) { function createInjector(modulesToLoad) { - var cache = {}, - providerSuffix = 'Provider', + var providerSuffix = 'Provider', path = [], - $injector, - loadedModules = new HashMap(); - - value('$injector', $injector = { - get: getService, - invoke: invoke, - instantiate: instantiate - }); - value('$provide', { - service: supportObject(service), - factory: supportObject(factory), - value: supportObject(value), - decorator: decorator - }); + loadedModules = new HashMap(), + providerCache = { + $provide: { + service: supportObject(service), + factory: supportObject(factory), + value: supportObject(value), + decorator: decorator + } + }, + providerInjector = createInternalInjector(providerCache, function() { + throw Error("Unknown provider: " + path.join(' <- ')); + }), + instanceCache = {}, + instanceInjector = (instanceCache.$injector = + createInternalInjector(instanceCache, function(servicename) { + var provider = providerInjector.get(servicename + providerSuffix); + return instanceInjector.invoke(provider.$get, provider); + })); + loadModules(modulesToLoad); - return $injector; + return instanceInjector; //////////////////////////////////// + // $provider + //////////////////////////////////// function supportObject(delegate) { return function(key, value) { @@ -274,124 +292,146 @@ function createInjector(modulesToLoad) { function service(name, provider) { if (isFunction(provider)){ - provider = instantiate(provider); + provider = providerInjector.instantiate(provider); } if (!provider.$get) { throw Error('Provider ' + name + ' must define $get factory method.'); } - cache['#' + name + providerSuffix] = provider; + providerCache[name + providerSuffix] = provider; } function factory(name, factoryFn) { service(name, { $get:factoryFn }); } function value(name, value) { factory(name, valueFn(value)); } - function decorator(name, decorFn) { - var origProvider = cache['#' + name + providerSuffix]; - if (!origProvider) throw Error("Can't find provider for: " + name); - if (cache['#' + name]) throw Error("Service " + name + " already instantiated, can't decorate!"); - var orig$get = origProvider.$get; + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + origProvider.$get = function() { - var origInstance = $injector.invoke(origProvider, orig$get); - return $injector.invoke(null, decorFn, {$delegate: origInstance}); + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); }; } - - function getService(value) { - if (typeof value !== 'string') { - throw Error('Service name expected'); - } - var instanceKey = '#' + value, - instance = cache[instanceKey]; - if (instance !== undefined || cache.hasOwnProperty(instanceKey)) { - return instance; - } - try { - path.unshift(value); - var providerKey = instanceKey + providerSuffix, - provider = cache[providerKey]; - if (provider) { - return cache[instanceKey] = invoke(provider, provider.$get); + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad){ + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + if (isString(module)) { + var moduleFn = angularModule(module); + loadModules(moduleFn.requires); + + try { + for(var invokeQueue = moduleFn.invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { + var invokeArgs = invokeQueue[i], + provider = invokeArgs[0] == '$injector' + ? providerInjector + : providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } catch (e) { + if (e.message) e.message += ' from ' + module; + throw e; + } + } else if (isFunction(module)) { + try { + providerInjector.invoke(module); + } catch (e) { + if (e.message) e.message += ' from ' + module; + throw e; + } + } else if (isArray(module)) { + try { + providerInjector.invoke(module); + } catch (e) { + if (e.message) e.message += ' from ' + String(module[module.length - 1]); + throw e; + } } else { - throw Error("Unknown provider for '" + path.join("' <- '") + "'."); + assertArgFn(module, 'module'); } - } finally { - path.shift(); - } + }); } - function invoke(self, fn, locals){ - var args = [], - $inject, - length, - key; - - if (typeof fn == 'function') { - $inject = inferInjectionArgs(fn); - length = $inject.length; - } else { - if (isArray(fn)) { - $inject = fn; - length = $inject.length; - fn = $inject[--length]; - } - assertArgFn(fn, 'fn'); - } + //////////////////////////////////// + // internal Injector + //////////////////////////////////// - while(length--) { - key = $inject[length]; - args.unshift( - locals && locals.hasOwnProperty(key) - ? locals[key] - : getService($inject[length], path) - ); - } + function createInternalInjector(cache, factory) { - // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke - switch (self ? -1 : args.length) { - case 0: return fn(); - case 1: return fn(args[0]); - case 2: return fn(args[0], args[1]); - case 3: return fn(args[0], args[1], args[2]); - case 4: return fn(args[0], args[1], args[2], args[3]); - case 5: return fn(args[0], args[1], args[2], args[3], args[4]); - case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); - default: return fn.apply(self, args); + function getService(serviceName) { + if (typeof serviceName !== 'string') { + throw Error('Service name expected'); + } + if (cache.hasOwnProperty(serviceName)) { + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + return cache[serviceName] = factory(serviceName); + } finally { + path.shift(); + } + } } - } - function instantiate(Type, locals){ - var Constructor = function(){}, - instance; - Constructor.prototype = Type.prototype; - instance = new Constructor(); - return invoke(instance, Type, locals) || instance; - } + function invoke(fn, self, locals){ + var args = [], + $injectAnnotation, + $injectAnnotationIndex, + key; - function loadModules(modulesToLoad){ - forEach(modulesToLoad, function(module) { - if (loadedModules.get(module)) return; - loadedModules.put(module, true); - if (isString(module)) { - module = angularModule(module); - loadModules(module.requires); + if (typeof fn == 'function') { + $injectAnnotation = inferInjectionArgs(fn); + $injectAnnotationIndex = $injectAnnotation.length; + } else { + if (isArray(fn)) { + $injectAnnotation = fn; + $injectAnnotationIndex = $injectAnnotation.length; + fn = $injectAnnotation[--$injectAnnotationIndex]; + } + assertArgFn(fn, 'fn'); + } - for(var invokeQueue = module.invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { - var invokeArgs = invokeQueue[i], - service = getService(invokeArgs[0]); + while($injectAnnotationIndex--) { + key = $injectAnnotation[$injectAnnotationIndex]; + args.unshift(locals && locals.hasOwnProperty(key) ? locals[key] : getService(key)); + } - service[invokeArgs[1]].apply(service, invokeArgs[2]); - } - } else if (isFunction(module) || isArray(module)) { - invoke(null, module); - } else { - assertArgFn(module, 'module'); + // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke + switch (self ? -1 : args.length) { + case 0: return fn(); + case 1: return fn(args[0]); + case 2: return fn(args[0], args[1]); + case 3: return fn(args[0], args[1], args[2]); + case 4: return fn(args[0], args[1], args[2], args[3]); + case 5: return fn(args[0], args[1], args[2], args[3], args[4]); + case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); + default: return fn.apply(self, args); } - }); + } + + function instantiate(Type, locals){ + var Constructor = function(){}, + instance; + Constructor.prototype = Type.prototype; + instance = new Constructor(); + return invoke(Type, instance, locals) || instance; + } + + return { + invoke: invoke, + instantiate: instantiate, + get: getService + }; } } diff --git a/src/angular-mocks.js b/src/angular-mocks.js index f70731d3..d2dbb114 100644 --- a/src/angular-mocks.js +++ b/src/angular-mocks.js @@ -935,16 +935,56 @@ window.jstestdriver && (function(window) { * @return a method */ window.jasmine && (function(window) { - window.inject = function () { + + function getCurrentSpec() { + return jasmine.getEnv().currentSpec; + } + + function isSpecRunning() { + var spec = getCurrentSpec(); + return spec && spec.queue.running; + } + + window.module = function() { + var moduleFns = Array.prototype.slice.call(arguments, 0); + var stack = Error('Declaration Location').stack; + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + var spec = getCurrentSpec(); + if (spec.$injector) { + throw Error('Injector already created, can not register a module!'); + } else { + var modules = spec.$modules || (spec.$modules = []); + angular.forEach(moduleFns, function(module) { + modules.push(module); + }); + } + } + }; + window.inject = function() { var blockFns = Array.prototype.slice.call(arguments, 0); - return function() { - var injector = this.$injector; + var stack = Error('Declaration Location').stack; + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + var spec = getCurrentSpec(); + var modules = spec.$modules || []; + modules.unshift('ngMock'); + modules.unshift('ng'); + var injector = spec.$injector; if (!injector) { - injector = this.$injector = angular.injector('ng', 'ngMock'); + injector = spec.$injector = angular.injector(modules); } + console.log('inject', modules) for(var i = 0, ii = blockFns.length; i < ii; i++) { - injector.invoke(this, blockFns[i]); + try { + injector.invoke(blockFns[i] || angular.noop, this); + } catch (e) { + if(e.stack) e.stack += '\n' + stack; + throw e; + } } - }; + } } })(window); diff --git a/src/loader.js b/src/loader.js index ec30ad9a..3d5edd31 100644 --- a/src/loader.js +++ b/src/loader.js @@ -48,7 +48,7 @@ function setupModuleLoader(window) { * Then you can load your module like this: * * <pre> - * var injector = angular.injector('ng', 'MyModule') + * var injector = angular.injector(['ng', 'MyModule']) * </pre> * * @param {!string} name The name of the module to create or retrieve. @@ -67,13 +67,11 @@ function setupModuleLoader(window) { throw Error('No module: ' + name); } - function init(fn) { - invokeQueue.push(['$injector', 'invoke', [null, fn]]); - } - /** @type {!Array.<Array.<*>>} */ var invokeQueue = []; + var init = invokeLater('$injector', 'invoke'); + /** @type {angular.Module} */ var moduleInstance = { /** diff --git a/src/scenario/Application.js b/src/scenario/Application.js index ba6bbea7..d3a70569 100644 --- a/src/scenario/Application.js +++ b/src/scenario/Application.js @@ -93,7 +93,7 @@ angular.scenario.Application.prototype.executeAction = function(action) { angularInit($window.document, function(element) { element = $window.angular.element(element); var $injector = element.inheritedData('$injector'); - $injector.invoke(null, function($browser){ + $injector.invoke(function($browser){ $browser.notifyWhenNoOutstandingRequests(function() { action.call(self, $window, _jQuery($window.document)); }); diff --git a/src/scenario/Runner.js b/src/scenario/Runner.js index aeb5196a..cfde1f64 100644 --- a/src/scenario/Runner.js +++ b/src/scenario/Runner.js @@ -163,7 +163,7 @@ angular.scenario.Runner.prototype.createSpecRunner_ = function(scope) { */ angular.scenario.Runner.prototype.run = function(application) { var self = this; - var $root = angular.injector('ng').get('$rootScope'); + var $root = angular.injector(['ng']).get('$rootScope'); angular.extend($root, this); angular.forEach(angular.scenario.Runner.prototype, function(fn, name) { $root[name] = angular.bind(self, fn); diff --git a/src/scenario/dsl.js b/src/scenario/dsl.js index 12cbdb21..bbe29948 100644 --- a/src/scenario/dsl.js +++ b/src/scenario/dsl.js @@ -103,25 +103,25 @@ angular.scenario.dsl('browser', function() { api.url = function() { return this.addFutureAction('$location.url()', function($window, $document, done) { - done(null, $window.angular.injector('ng').get('$location').url()); + done(null, $window.angular.injector(['ng']).get('$location').url()); }); }; api.path = function() { return this.addFutureAction('$location.path()', function($window, $document, done) { - done(null, $window.angular.injector('ng').get('$location').path()); + done(null, $window.angular.injector(['ng']).get('$location').path()); }); }; api.search = function() { return this.addFutureAction('$location.search()', function($window, $document, done) { - done(null, $window.angular.injector('ng').get('$location').search()); + done(null, $window.angular.injector(['ng']).get('$location').search()); }); }; api.hash = function() { return this.addFutureAction('$location.hash()', function($window, $document, done) { - done(null, $window.angular.injector('ng').get('$location').hash()); + done(null, $window.angular.injector(['ng']).get('$location').hash()); }); }; diff --git a/src/service/compiler.js b/src/service/compiler.js index 8a0dca7d..727f7983 100644 --- a/src/service/compiler.js +++ b/src/service/compiler.js @@ -28,7 +28,7 @@ function $CompileProvider(){ forEach(this.linkFns, function(fn) { try { if (isArray(fn) || fn.$inject) { - $injector.invoke(childScope, fn, locals); + $injector.invoke(fn, childScope, locals); } else { fn.call(childScope, element); } @@ -97,7 +97,7 @@ function $CompileProvider(){ * that is a DOM clone of the original template. * <pre> - angular.injector('ng').invoke(null, function($rootScope, $compile) { + angular.injector(['ng']).invoke(function($rootScope, $compile) { // Chose one: // A: compile the entire window.document. @@ -143,8 +143,8 @@ function $CompileProvider(){ * - If you are not asking the linking function to clone the template, create the DOM element(s) * before you send them to the compiler and keep this reference around. * <pre> - * var $injector = angular.injector('ng'); - * var scope = $injector.invoke(null, function($rootScope, $compile){ + * var $injector = angular.injector(['ng']); + * var scope = $injector.invoke(function($rootScope, $compile){ * var element = $compile('<p>{{total}}</p>')($rootScope); * }); * </pre> @@ -277,7 +277,7 @@ function $CompileProvider(){ descend = false; directives = false; var parent = element.parent(); - template.addLinkFn($injector.invoke(selfApi, widget, locals)); + template.addLinkFn($injector.invoke(widget, selfApi, locals)); if (parent && parent[0]) { element = jqLite(parent[0].childNodes[elementIndex]); } @@ -310,7 +310,7 @@ function $CompileProvider(){ if (fn) { element.addClass('ng-directive'); template.addLinkFn((isArray(fn) || fn.$inject) - ? $injector.invoke(selfApi, fn, {$value:value, $element: element}) + ? $injector.invoke(fn, selfApi, {$value:value, $element: element}) : fn.call(selfApi, value, element)); } }); diff --git a/src/service/scope.js b/src/service/scope.js index 2836b42e..a19bf83e 100644 --- a/src/service/scope.js +++ b/src/service/scope.js @@ -50,7 +50,7 @@ function $RootScopeProvider(){ * * Here is a simple scope snippet to show how you can interact with the scope. * <pre> - angular.injector(function($rootScope) { + angular.injector(['ng']).invoke(function($rootScope) { var scope = $rootScope.$new(); scope.salutation = 'Hello'; scope.name = 'World'; @@ -168,7 +168,7 @@ function $RootScopeProvider(){ for(var key in ClassPrototype) { child[key] = bind(child, ClassPrototype[key]); } - $injector.invoke(child, Class, curryArguments); + $injector.invoke(Class, child, curryArguments); } return child; }, diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 55842acd..0ff0508f 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -346,18 +346,21 @@ describe('angular', function() { describe('angular service', function() { - it('should override services', inject(function($provide){ - $provide.value('fake', 'old'); - $provide.value('fake', 'new'); - }, function(fake) { - expect(fake).toEqual('new'); - })); + it('should override services', function() { + module(function($provide){ + $provide.value('fake', 'old'); + $provide.value('fake', 'new'); + }); + inject(function(fake) { + expect(fake).toEqual('new'); + }); + }); it('should inject dependencies specified by $inject and ignore function argument name', function() { - expect(angular.injector(function($provide){ + expect(angular.injector([function($provide){ $provide.factory('svc1', function() { return 'svc1'; }); $provide.factory('svc2', ['svc1', function(s) { return 'svc2-' + s; }]); - }).get('svc2')).toEqual('svc2-svc1'); + }]).get('svc2')).toEqual('svc2-svc1'); }); }); @@ -492,8 +495,7 @@ describe('angular', function() { describe('bootstrap', function() { it('should bootstrap app', function(){ var element = jqLite('<div>{{1+2}}</div>'); - var injector; - angular.bootstrap(element, [function($injector){ injector = $injector; }]); + var injector = angular.bootstrap(element); expect(injector).toBeDefined(); expect(element.data('$injector')).toBe(injector); dealoc(element); diff --git a/test/BinderSpec.js b/test/BinderSpec.js index efe7215b..a94e5eb2 100644 --- a/test/BinderSpec.js +++ b/test/BinderSpec.js @@ -13,7 +13,7 @@ describe('Binder', function() { content = jqLite(content); $compile(content)($rootScope); html = sortedHtml(content); - }).call(this); + }); return html; }; }); @@ -229,11 +229,11 @@ describe('Binder', function() { expect(element[0].childNodes.length - 1).toEqual(0); })); - it('IfTextBindingThrowsErrorDecorateTheSpan', inject( - function($exceptionHandlerProvider){ + it('IfTextBindingThrowsErrorDecorateTheSpan', function() { + module(function($exceptionHandlerProvider){ $exceptionHandlerProvider.mode('log'); - }, - function($rootScope, $exceptionHandler, $compile) { + }); + inject(function($rootScope, $exceptionHandler, $compile) { $compile('<div>{{error.throw()}}</div>', null, true)($rootScope); var errorLogs = $exceptionHandler.errors; @@ -250,28 +250,31 @@ describe('Binder', function() { $rootScope.error['throw'] = function() {return 'ok';}; $rootScope.$apply(); expect(errorLogs.length).toBe(0); - }) - ); + }); + }); - it('IfAttrBindingThrowsErrorDecorateTheAttribute', inject(function($exceptionHandlerProvider){ - $exceptionHandlerProvider.mode('log'); - }, function($rootScope, $exceptionHandler, $compile) { - $compile('<div attr="before {{error.throw()}} after"></div>', null, true)($rootScope); - var errorLogs = $exceptionHandler.errors; - var count = 0; + it('IfAttrBindingThrowsErrorDecorateTheAttribute', function() { + module(function($exceptionHandlerProvider){ + $exceptionHandlerProvider.mode('log'); + }); + inject(function($rootScope, $exceptionHandler, $compile) { + $compile('<div attr="before {{error.throw()}} after"></div>', null, true)($rootScope); + var errorLogs = $exceptionHandler.errors; + var count = 0; - $rootScope.error = { + $rootScope.error = { 'throw': function() {throw new Error('ErrorMsg' + (++count));} - }; - $rootScope.$apply(); - expect(errorLogs.length).not.toEqual(0); - expect(errorLogs.shift()).toMatch(/ErrorMsg1/); - errorLogs.length = 0; + }; + $rootScope.$apply(); + expect(errorLogs.length).not.toEqual(0); + expect(errorLogs.shift()).toMatch(/ErrorMsg1/); + errorLogs.length = 0; - $rootScope.error['throw'] = function() { return 'X';}; - $rootScope.$apply(); - expect(errorLogs.length).toMatch(0); - })); + $rootScope.error['throw'] = function() { return 'X';}; + $rootScope.$apply(); + expect(errorLogs.length).toMatch(0); + }); + }); it('NestedRepeater', inject(function($rootScope, $compile) { var element = $compile( @@ -395,19 +398,19 @@ describe('Binder', function() { $rootScope.$apply(); })); - it('ActionOnAHrefThrowsError', inject( - function($exceptionHandlerProvider){ + it('ActionOnAHrefThrowsError', function() { + module(function($exceptionHandlerProvider){ $exceptionHandlerProvider.mode('log'); - }, - function($rootScope, $exceptionHandler, $compile) { + }); + inject(function($rootScope, $exceptionHandler, $compile) { var input = $compile('<a ng:click="action()">Add Phone</a>')($rootScope); $rootScope.action = function() { throw new Error('MyError'); }; browserTrigger(input, 'click'); expect($exceptionHandler.errors[0]).toMatch(/MyError/); - }) - ); + }); + }); it('ShoulIgnoreVbNonBindable', inject(function($rootScope, $compile) { var element = $compile( @@ -477,11 +480,11 @@ describe('Binder', function() { assertChild(5, false); })); - it('ItShouldDisplayErrorWhenActionIsSyntacticlyIncorrect', inject( - function($exceptionHandlerProvider){ + it('ItShouldDisplayErrorWhenActionIsSyntacticlyIncorrect', function() { + module(function($exceptionHandlerProvider){ $exceptionHandlerProvider.mode('log'); - }, - function($rootScope, $exceptionHandler, $log, $compile) { + }); + inject(function($rootScope, $exceptionHandler, $log, $compile) { var element = $compile( '<div>' + '<input type="button" ng:click="greeting=\'ABC\'"/>' + @@ -498,8 +501,8 @@ describe('Binder', function() { browserTrigger(second, 'click'); expect($exceptionHandler.errors[0]). toMatchError(/Syntax Error: Token ':' not a primary expression/); - }) - ); + }); + }); it('ItShouldSelectTheCorrectRadioBox', inject(function($rootScope, $compile) { var element = $compile( diff --git a/test/InjectorSpec.js b/test/InjectorSpec.js index 3eec169a..4817dc32 100644 --- a/test/InjectorSpec.js +++ b/test/InjectorSpec.js @@ -4,10 +4,12 @@ describe('injector', function() { var providers; var injector; - beforeEach(inject(function($injector, $provide) { + beforeEach(module(function($provide) { providers = function(name, factory, annotations) { $provide.factory(name, extend(factory, annotations||{})); }; + })); + beforeEach(inject(function($injector){ injector = $injector; })); @@ -57,7 +59,7 @@ describe('injector', function() { it('should provide useful message if no provider', function() { expect(function() { injector.get('idontexist'); - }).toThrow("Unknown provider for 'idontexist'."); + }).toThrow("Unknown provider: idontexistProvider <- idontexist"); }); @@ -66,7 +68,7 @@ describe('injector', function() { providers('b', function(a) {return 2;}); expect(function() { injector.get('b'); - }).toThrow("Unknown provider for 'idontexist' <- 'a' <- 'b'."); + }).toThrow("Unknown provider: idontexistProvider <- idontexist <- a <- b"); }); @@ -88,13 +90,13 @@ describe('injector', function() { it('should call function', function() { fn.$inject = ['a', 'b', 'c', 'd']; - injector.invoke({name:"this"}, fn, {c:3, d:4}); + injector.invoke(fn, {name:"this"}, {c:3, d:4}); expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]); }); it('should treat array as annotations', function() { - injector.invoke({name:"this"}, ['a', 'b', 'c', 'd', fn], {c:3, d:4}); + injector.invoke(['a', 'b', 'c', 'd', fn], {name:"this"}, {c:3, d:4}); expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]); }); @@ -102,16 +104,16 @@ describe('injector', function() { it('should invoke the passed-in fn with all of the dependencies as arguments', function() { providers('c', function() {return 3;}); providers('d', function() {return 4;}); - expect(injector.invoke(null, ['a', 'b', 'c', 'd', fn])).toEqual(10); + expect(injector.invoke(['a', 'b', 'c', 'd', fn])).toEqual(10); }); it('should fail with errors if not function or array', function() { expect(function() { - injector.invoke({}, {}); + injector.invoke({}); }).toThrow("Argument 'fn' is not a function, got Object"); expect(function() { - injector.invoke({}, ['a', 123]); + injector.invoke(['a', 123], {}); }).toThrow("Argument 'fn' is not a function, got number"); }); }); @@ -183,7 +185,7 @@ describe('injector', function() { }); }, function(valueProvider, fnProvider, serviceProvider) { log += valueProvider.$get() + fnProvider.$get() + serviceProvider.$get(); - }]).invoke(null, function(value, fn, service) { + }]).invoke(function(value, fn, service) { log += '->' + value + fn + service; }); expect(log).toEqual('value;function;service;->value;function;service;'); @@ -191,13 +193,12 @@ describe('injector', function() { describe('module', function() { - it('should provide $injector and $provide even when no module is requested', function() { + it('should provide $injector even when no module is requested', function() { var $provide, $injector = createInjector([ angular.extend(function(p) { $provide = p; }, {$inject: ['$provide']}) ]); expect($injector.get('$injector')).toBe($injector); - expect($injector.get('$provide')).toBe($provide); }); @@ -425,28 +426,6 @@ describe('injector', function() { expect(log.join('; ')). toBe('myDecoratedService:input,dependency1; myService:decInput; dec+origReturn'); }); - - - it('should complain if the service to be decorated was already instantiated', function() { - injector = createInjector([function($provide, $injector) { - $provide.value('myService', function(val) { - log.push('myService:' + val); - return 'origReturn'; - }); - - $injector.get('myService'); - - expect(function() { - $provide.decorator('myService', function($delegate) { - return function(val) { - log.push('myDecoratedService:' + val); - var origVal = $delegate('decInput'); - return 'dec+' + origVal; - }; - }); - }).toThrow("Service myService already instantiated, can't decorate!"); - }]); - }); }); }); @@ -470,11 +449,27 @@ describe('injector', function() { }); - it('should handle no module alias', function() { + it('should decorate the missing service error with module name', function() { + angular.module('TestModule', [], function($injector) {}); expect(function() { - createInjector([function(dontExist) { - }], {}); - }).toThrow("Unknown provider for 'dontExist'."); + createInjector(['TestModule']); + }).toThrow('Unknown provider: $injector from TestModule'); + }); + + + it('should decorate the missing service error with module function', function() { + function myModule($injector){} + expect(function() { + createInjector([myModule]); + }).toThrow('Unknown provider: $injector from ' + myModule); + }); + + + it('should decorate the missing service error with module array function', function() { + function myModule($injector){} + expect(function() { + createInjector([['$injector', myModule]]); + }).toThrow('Unknown provider: $injector from ' + myModule); }); }); }); @@ -500,8 +495,8 @@ describe('injector', function() { it('should call functions and infer arguments', function() { - expect($injector.invoke(null, function(instance) { return instance; })).toBe(instance); - expect($injector.invoke(null, function(instance) { return instance; })).toBe(instance); + expect($injector.invoke(function(instance) { return instance; })).toBe(instance); + expect($injector.invoke(function(instance) { return instance; })).toBe(instance); }); }); @@ -518,52 +513,52 @@ describe('injector', function() { it('should invoke method', function() { - expect($injector.invoke(null, function(book, author) { + expect($injector.invoke(function(book, author) { return author + ':' + book; })).toEqual('melville:moby'); - expect($injector.invoke($injector, function(book, author) { + expect($injector.invoke(function(book, author) { expect(this).toEqual($injector); - return author + ':' + book;})).toEqual('melville:moby'); + return author + ':' + book;}, $injector)).toEqual('melville:moby'); }); it('should invoke method with locals', function() { - expect($injector.invoke(null, function(book, author) { + expect($injector.invoke(function(book, author) { return author + ':' + book; })).toEqual('melville:moby'); - expect($injector.invoke($injector, + expect($injector.invoke( function(book, author, chapter) { expect(this).toEqual($injector); return author + ':' + book + '-' + chapter; - }, {author:'m', chapter:'ch1'})).toEqual('m:moby-ch1'); + }, $injector, {author:'m', chapter:'ch1'})).toEqual('m:moby-ch1'); }); it('should invoke method which is annotated', function() { - expect($injector.invoke(null, extend(function(b, a) { + expect($injector.invoke(extend(function(b, a) { return a + ':' + b }, {$inject:['book', 'author']}))).toEqual('melville:moby'); - expect($injector.invoke($injector, extend(function(b, a) { + expect($injector.invoke(extend(function(b, a) { expect(this).toEqual($injector); return a + ':' + b; - }, {$inject:['book', 'author']}))).toEqual('melville:moby'); + }, {$inject:['book', 'author']}), $injector)).toEqual('melville:moby'); }); it('should invoke method which is an array of annotation', function() { - expect($injector.invoke(null, function(book, author) { + expect($injector.invoke(function(book, author) { return author + ':' + book; })).toEqual('melville:moby'); - expect($injector.invoke($injector, function(book, author) { + expect($injector.invoke(function(book, author) { expect(this).toEqual($injector); return author + ':' + book; - })).toEqual('melville:moby'); + }, $injector)).toEqual('melville:moby'); }); it('should throw usefull error on wrong argument type]', function() { expect(function() { - $injector.invoke(null, {}); + $injector.invoke({}); }).toThrow("Argument 'fn' is not a function, got Object"); }); }); @@ -610,4 +605,33 @@ describe('injector', function() { }).toThrow('MyError'); }); }); + + describe('protection modes', function() { + it('should prevent provider lookup in app', function() { + var $injector = createInjector([function($provide) { + $provide.value('name', 'angular'); + }]); + expect(function() { + $injector.get('nameProvider'); + }).toThrow("Unknown provider: nameProviderProvider <- nameProvider"); + }); + + + it('should prevent provider configuration in app', function() { + var $injector = createInjector([]); + expect(function() { + $injector.get('$provide').value('a', 'b'); + }).toThrow("Unknown provider: $provideProvider <- $provide"); + }); + + + it('should prevent instance lookup in module', function() { + function instanceLookupInModule(name) { throw Error('FAIL'); } + expect(function() { + createInjector([function($provide) { + $provide.value('name', 'angular') + }, instanceLookupInModule]); + }).toThrow('Unknown provider: name from ' + String(instanceLookupInModule)); + }); + }); }); diff --git a/test/angular-mocksSpec.js b/test/angular-mocksSpec.js index fbdd3b91..153c2e33 100644 --- a/test/angular-mocksSpec.js +++ b/test/angular-mocksSpec.js @@ -302,7 +302,7 @@ describe('ngMock', function() { })); - it('should log exceptions', inject(function($exceptionHandlerProvider){ + it('should log exceptions', module(function($exceptionHandlerProvider){ $exceptionHandlerProvider.mode('log'); var $exceptionHandler = $exceptionHandlerProvider.$get(); $exceptionHandler('MyError'); @@ -310,7 +310,7 @@ describe('ngMock', function() { })); - it('should thorw on wrong argument', inject(function($exceptionHandlerProvider) { + it('should throw on wrong argument', module(function($exceptionHandlerProvider) { expect(function() { $exceptionHandlerProvider.mode('XXX'); }).toThrow("Unknown mode 'XXX', only 'log'/'rethrow' modes are allowed!"); @@ -348,32 +348,83 @@ describe('ngMock', function() { }); }); - describe('jasmine inject', function(){ - it('should call invoke', function(){ - var count = 0; - function fn1(){ - expect(this).toBe(self); - count++; - } - function fn2(){ - expect(this).toBe(self); - count++; - } - var fn = inject(fn1, fn2); - var self = { - $injector: { - invoke: function(self, fn) { fn.call(self); } - } - }; + describe('jasmine module and inject', function(){ + var log; + + beforeEach(function(){ + log = ''; + }); + + describe('module', function() { + describe('in DSL', function() { + it('should load module', module(function() { + log += 'module'; + })); + + afterEach(function() { + inject(); + expect(log).toEqual('module'); + }); + }); + + + describe('inline in test', function() { + it('should load module', function() { + module(function() { + log += 'module'; + }); + inject(); + }); + + afterEach(function() { + expect(log).toEqual('module'); + }); + }); + }); + + describe('inject', function() { + describe('in DSL', function() { + it('should load module', inject(function() { + log += 'inject'; + })); - fn.call(self); - expect(count).toBe(2); + afterEach(function() { + expect(log).toEqual('inject'); + }); + }); + + + describe('inline in test', function() { + it('should load module', function() { + inject(function() { + log += 'inject'; + }); + }); + + afterEach(function() { + expect(log).toEqual('inject'); + }); + }); + + describe('module with inject', function() { + beforeEach(module(function(){ + log += 'module;'; + })); + + it('should inject', inject(function() { + log += 'inject;'; + })); + + afterEach(function() { + expect(log).toEqual('module;inject;') + }); + }); }); }); describe('$httpBackend', function() { - var hb, callback; + var hb, callback, realBackendSpy; beforeEach(inject(function($httpBackend) { callback = jasmine.createSpy('callback'); @@ -832,13 +883,17 @@ describe('ngMockE2E', function() { describe('$httpBackend', function() { var hb, realHttpBackend, callback; - beforeEach(inject(function($provide, $injector) { - callback = jasmine.createSpy('callback'); - realHttpBackend = jasmine.createSpy('real $httpBackend'); - $provide.value('$httpBackend', realHttpBackend); - $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); - hb = $injector.get('$httpBackend'); - })); + beforeEach(function() { + module(function($provide) { + callback = jasmine.createSpy('callback'); + realHttpBackend = jasmine.createSpy('real $httpBackend'); + $provide.value('$httpBackend', realHttpBackend); + $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); + }); + inject(function($injector) { + hb = $injector.get('$httpBackend'); + }); + }); describe('passThrough()', function() { diff --git a/test/directivesSpec.js b/test/directivesSpec.js index ffb6d57c..1825dc49 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -2,6 +2,12 @@ describe("directive", function() { + var $filterProvider; + + beforeEach(module(['$filterProvider', function(provider){ + $filterProvider = provider; + }])); + it("should ng:init", inject(function($rootScope, $compile) { var element = $compile('<div ng:init="a=123"></div>')($rootScope); expect($rootScope.a).toEqual(123); @@ -41,7 +47,7 @@ describe("directive", function() { expect(lowercase(element.html())).toEqual('<div onclick="">hello</div>'); })); - it('should set element element', inject(function($rootScope, $compile, $filterProvider) { + it('should set element element', inject(function($rootScope, $compile) { $filterProvider.register('myElement', valueFn(function() { return jqLite('<a>hello</a>'); })); @@ -73,7 +79,7 @@ describe("directive", function() { expect(element.text()).toEqual('Hello Misko!'); })); - it('should have $element set to current bind element', inject(function($rootScope, $compile, $filterProvider) { + it('should have $element set to current bind element', inject(function($rootScope, $compile) { var innerText; $filterProvider.register('myFilter', valueFn(function(text) { innerText = innerText || this.$element.text(); @@ -415,7 +421,7 @@ describe("directive", function() { scope.$apply(); expect(element.css(preCompStyle)).not.toBe('88px'); expect(element.css(postCompStyle)).not.toBe('99px'); - }); + }); }); }); diff --git a/test/loaderSpec.js b/test/loaderSpec.js index afea159b..e419a198 100644 --- a/test/loaderSpec.js +++ b/test/loaderSpec.js @@ -40,12 +40,12 @@ describe('module loader', function() { expect(myModule.requires).toEqual(['other']); expect(myModule.invokeQueue).toEqual([ - ['$injector', 'invoke', [null, 'init'] ], + ['$injector', 'invoke', ['init'] ], ['$provide', 'service', ['sk', 'sv'] ], ['$provide', 'factory', ['fk', 'fv'] ], ['$provide', 'value', ['k', 'v'] ], ['$filterProvider', 'register', ['f', 'ff'] ], - ['$injector', 'invoke', [null, 'init2'] ] + ['$injector', 'invoke', ['init2'] ] ]); }); diff --git a/test/markupSpec.js b/test/markupSpec.js index 7c7f64f8..e2e11f7f 100644 --- a/test/markupSpec.js +++ b/test/markupSpec.js @@ -150,7 +150,7 @@ describe("markups", function() { it('should bind Text with no Bindings', inject(function($compile) { var $rootScope; function newScope (){ - return $rootScope = angular.injector('ng').get('$rootScope'); + return $rootScope = angular.injector(['ng']).get('$rootScope'); } forEach(['checked', 'disabled', 'multiple', 'readonly', 'selected'], function(name) { var element = $compile('<div ng:' + name + '="some"></div>')(newScope()) diff --git a/test/service/autoScrollSpec.js b/test/service/autoScrollSpec.js index 8d04268b..86a47f50 100644 --- a/test/service/autoScrollSpec.js +++ b/test/service/autoScrollSpec.js @@ -53,7 +53,7 @@ describe('$autoScroll', function() { } - beforeEach(inject(function($provide) { + beforeEach(module(function($provide) { elmSpy = {}; $provide.value('$window', { scrollTo: jasmine.createSpy('$window.scrollTo'), @@ -108,11 +108,14 @@ describe('$autoScroll', function() { expectScrollingTo('id=top'))); - it('should not scroll when disabled', inject( - addElements('id=fake', 'a name=fake', 'input name=fake'), - disableScroller(), - changeHashAndScroll('fake'), - expectNoScrolling())); + it('should not scroll when disabled', function() { + module(disableScroller()); + inject( + addElements('id=fake', 'a name=fake', 'input name=fake'), + changeHashAndScroll('fake'), + expectNoScrolling() + ); + }); describe('watcher', function() { @@ -136,40 +139,57 @@ describe('$autoScroll', function() { })); - it('should scroll to element when hash change in hashbang mode', inject( - initLocation({html5Mode: false, historyApi: true}), - addElements('id=some'), - changeHashAndDigest('some'), - expectScrollingTo('id=some'))); + it('should scroll to element when hash change in hashbang mode', function() { + module(initLocation({html5Mode: false, historyApi: true})); + inject( + addElements('id=some'), + changeHashAndDigest('some'), + expectScrollingTo('id=some') + ); + }); - it('should scroll to element when hash change in html5 mode with no history api', inject( - initLocation({html5Mode: true, historyApi: false}), - addElements('id=some'), - changeHashAndDigest('some'), - expectScrollingTo('id=some'))); + it('should scroll to element when hash change in html5 mode with no history api', function() { + module(initLocation({html5Mode: true, historyApi: false})); + inject( + addElements('id=some'), + changeHashAndDigest('some'), + expectScrollingTo('id=some') + ); + }); - it('should not scroll when element does not exist', inject( - initLocation({html5Mode: false, historyApi: false}), - addElements('id=some'), - changeHashAndDigest('other'), - expectNoScrolling())); + it('should not scroll when element does not exist', function() { + module(initLocation({html5Mode: false, historyApi: false})); + inject( + addElements('id=some'), + changeHashAndDigest('other'), + expectNoScrolling() + ); + }); - it('should not scroll when html5 mode with history api', inject( - initLocation({html5Mode: true, historyApi: true}), - addElements('id=some'), - changeHashAndDigest('some'), - expectNoScrolling())); + it('should not scroll when html5 mode with history api', function() { + module(initLocation({html5Mode: true, historyApi: true})); + inject( + addElements('id=some'), + changeHashAndDigest('some'), + expectNoScrolling() + ); + }); - it('should not scroll when disabled', inject( - disableScroller(), - initLocation({html5Mode: false, historyApi: false}), - addElements('id=fake'), - changeHashAndDigest('fake'), - expectNoScrolling())); + it('should not scroll when disabled', function() { + module( + disableScroller(), + initLocation({html5Mode: false, historyApi: false}) + ); + inject( + addElements('id=fake'), + changeHashAndDigest('fake'), + expectNoScrolling() + ); + }); }); }); diff --git a/test/service/compilerSpec.js b/test/service/compilerSpec.js index ccf70aaf..6e6c211b 100644 --- a/test/service/compilerSpec.js +++ b/test/service/compilerSpec.js @@ -1,10 +1,10 @@ 'use strict'; describe('compiler', function() { - var compiler, textMmarkup, attrMarkup, directives, widgets, compile, log, $rootScope; + var textMarkup, attrMarkup, directives, widgets, compile, log; - beforeEach(inject(function($provide){ - textMmarkup = []; + beforeEach(module(function($provide){ + textMarkup = []; attrMarkup = []; widgets = extensionMap({}, 'widget'); directives = { @@ -26,7 +26,7 @@ describe('compiler', function() { }; log = ""; - $provide.value('$textMarkup', textMmarkup); + $provide.value('$textMarkup', textMarkup); $provide.value('$attrMarkup', attrMarkup); $provide.value('$directive', directives); $provide.value('$widget', widgets); @@ -138,7 +138,7 @@ describe('compiler', function() { it('should process markup before directives', inject(function($rootScope, $compile) { - textMmarkup.push(function(text, textNode, parentNode) { + textMarkup.push(function(text, textNode, parentNode) { if (text == 'middle') { expect(textNode.text()).toEqual(text); parentNode.attr('hello', text); @@ -176,7 +176,7 @@ describe('compiler', function() { this.directives(true); return noop; }; - textMmarkup.push(function(text, textNode, parent){ + textMarkup.push(function(text, textNode, parent){ if (text == '{{1+2}}') parent.text('3'); }); @@ -186,7 +186,7 @@ describe('compiler', function() { it('should allow multiple markups per text element', inject(function($rootScope, $compile) { - textMmarkup.push(function(text, textNode, parent){ + textMarkup.push(function(text, textNode, parent){ var index = text.indexOf('---'); if (index > -1) { textNode.after(text.substring(index + 3)); @@ -195,7 +195,7 @@ describe('compiler', function() { textNode.remove(); } }); - textMmarkup.push(function(text, textNode, parent){ + textMarkup.push(function(text, textNode, parent){ var index = text.indexOf('==='); if (index > -1) { textNode.after(text.substring(index + 3)); diff --git a/test/service/cookiesSpec.js b/test/service/cookiesSpec.js index d73923a6..5427ac36 100644 --- a/test/service/cookiesSpec.js +++ b/test/service/cookiesSpec.js @@ -1,13 +1,13 @@ 'use strict'; describe('$cookies', function() { - beforeEach(inject(function($provide) { + beforeEach(module(function($provide) { $provide.factory('$browser', function(){ return angular.extend(new angular.mock.$Browser(), {cookieHash: {preexisting:'oldCookie'}}); }); })); - + it('should provide access to existing cookies via object properties and keep them in sync', inject(function($cookies, $browser, $rootScope) { expect($cookies).toEqual({'preexisting': 'oldCookie'}); diff --git a/test/service/deferSpec.js b/test/service/deferSpec.js index e4554601..48c9e912 100644 --- a/test/service/deferSpec.js +++ b/test/service/deferSpec.js @@ -1,7 +1,7 @@ 'use strict'; describe('$defer', function() { - beforeEach(inject(function($provide) { + beforeEach(module(function($provide) { $provide.factory('$exceptionHandler', function(){ return jasmine.createSpy('$exceptionHandler'); }); diff --git a/test/service/exceptionHandlerSpec.js b/test/service/exceptionHandlerSpec.js index 00abff30..2f3d0e66 100644 --- a/test/service/exceptionHandlerSpec.js +++ b/test/service/exceptionHandlerSpec.js @@ -3,13 +3,13 @@ describe('$exceptionHandler', function() { - it('should log errors', inject( - function($provide){ + it('should log errors', function() { + module(function($provide){ $provide.service('$exceptionHandler', $ExceptionHandlerProvider); - }, - function($log, $exceptionHandler) { + }); + inject(function($log, $exceptionHandler) { $exceptionHandler('myError'); expect($log.error.logs.shift()).toEqual(['myError']); - } - )); + }); + }); }); diff --git a/test/service/filter/filtersSpec.js b/test/service/filter/filtersSpec.js index 40a78558..cc006447 100644 --- a/test/service/filter/filtersSpec.js +++ b/test/service/filter/filtersSpec.js @@ -8,13 +8,15 @@ describe('filters', function() { filter = $filter; })); - it('should called the filter when evaluating expression', inject(function($rootScope, $filterProvider) { + it('should call the filter when evaluating expression', function(){ var filter = jasmine.createSpy('myFilter'); - $filterProvider.register('myFilter', valueFn(filter)); - - $rootScope.$eval('10|myFilter'); + createInjector(['ng', function($filterProvider) { + $filterProvider.register('myFilter', valueFn(filter)); + }]).invoke(function($rootScope) { + $rootScope.$eval('10|myFilter'); + }); expect(filter).toHaveBeenCalledWith(10); - })); + }); describe('formatNumber', function() { var pattern; diff --git a/test/service/httpSpec.js b/test/service/httpSpec.js index 5efe2954..c6adee9e 100644 --- a/test/service/httpSpec.js +++ b/test/service/httpSpec.js @@ -1,20 +1,15 @@ 'use strict'; describe('$http', function() { - var $rootScope, callback; - beforeEach(inject( - function($exceptionHandlerProvider) { - $exceptionHandlerProvider.mode('log'); - }, - ['$rootScope', function($rs) { - $rootScope = $rs; - - spyOn($rootScope, '$apply').andCallThrough(); - callback = jasmine.createSpy('done'); - }] - )); + var callback; + beforeEach(function() { + callback = jasmine.createSpy('done'); + }); + beforeEach(module(function($exceptionHandlerProvider) { + $exceptionHandlerProvider.mode('log'); + })); afterEach(inject(function($exceptionHandler, $httpBackend) { forEach($exceptionHandler.errors, function(e) { @@ -33,73 +28,87 @@ describe('$http', function() { describe('interceptors', function() { - it('should default to an empty array', inject(function($httpProvider) { + it('should default to an empty array', module(function($httpProvider) { expect($httpProvider.responseInterceptors).toEqual([]); })); - it('should pass the responses through interceptors', inject(function($httpProvider, $q) { - // just change the response data and pass the response object along - $httpProvider.responseInterceptors.push(function(httpPromise) { - return httpPromise.then(function(response) { - response.data += '!'; - return response; + it('should pass the responses through interceptors', function() { + var shared = {}; + module(function($httpProvider, $provide) { + $provide.factory('testInterceptor', function ($q) { + return function(httpPromise) { + return httpPromise.then(function(response) { + var deferred = $q.defer(); + deferred.resolve({ + data: response.data + '?', + status: 209, + headers: response.headers, + config: response.config + }); + return deferred.promise; + }); + }; }); - }); - - // return a new resolved promise representing modified response object - $httpProvider.responseInterceptors.push(function(httpPromise) { - return httpPromise.then(function(response) { - var deferred = $q.defer(); - deferred.resolve({ - data: response.data + '?', - status: 209, - headers: response.headers, - config: response.config + // just change the response data and pass the response object along + $httpProvider.responseInterceptors.push(function(httpPromise) { + return httpPromise.then(function(response) { + response.data += '!'; + return response; }); - return deferred.promise; }); + + // return a new resolved promise representing modified response object + $httpProvider.responseInterceptors.push('testInterceptor'); }); - }, function($http, $httpBackend) { - $httpBackend.expect('GET', '/foo').respond(201, 'Hello'); - $http.get('/foo').success(function(data, status) { - expect(data).toBe('Hello!?'); - expect(status).toBe(209); - callback(); + inject(function($http, $httpBackend) { + $httpBackend.expect('GET', '/foo').respond(201, 'Hello'); + $http.get('/foo').success(function(data, status) { + expect(data).toBe('Hello!?'); + expect(status).toBe(209); + callback(); + }); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnce(); }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalledOnce(); - })); + }); - it('should support interceptors defined as services', inject( - function($provide, $httpProvider) { - $provide.factory('myInterceptor', function() { - return function(promise) { - return promise.then(function(response) { - response.data = uppercase(response.data); - return response; - }); - } - }); - $httpProvider.responseInterceptors.push('myInterceptor'); - }, function($http, $httpBackend) { - var response; + it('should support interceptors defined as services', function() { + module(function($provide, $httpProvider) { + $provide.factory('myInterceptor', function() { + return function(promise) { + return promise.then(function(response) { + response.data = uppercase(response.data); + return response; + }); + } + }); + $httpProvider.responseInterceptors.push('myInterceptor'); + }); + inject(function($http, $httpBackend) { + var response; - $httpBackend.expect('GET', '/test').respond('hello!'); - $http.get('/test').success(function(data) {response = data;}); - expect(response).toBeUndefined(); + $httpBackend.expect('GET', '/test').respond('hello!'); + $http.get('/test').success(function(data) {response = data;}); + expect(response).toBeUndefined(); - $httpBackend.flush(); - expect(response).toBe('HELLO!'); - } - )); + $httpBackend.flush(); + expect(response).toBe('HELLO!'); + }); + }); }); }); describe('the instance', function() { - var $httpBackend, $http; + var $httpBackend, $http, $rootScope; + + beforeEach(inject(['$rootScope', function($rs) { + $rootScope = $rs; + + spyOn($rootScope, '$apply').andCallThrough(); + }])); beforeEach(inject(['$httpBackend', '$http', function($hb, $h) { $httpBackend = $hb; diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js index 7c075fc0..c7cc9c23 100644 --- a/test/service/locationSpec.js +++ b/test/service/locationSpec.js @@ -335,11 +335,11 @@ describe('$location', function() { function initService(html5Mode, hashPrefix, supportHistory) { - return function($provide, $locationProvider){ + return module(function($provide, $locationProvider){ $locationProvider.html5Mode(html5Mode); $locationProvider.hashPrefix(hashPrefix); $provide.value('$sniffer', {history: supportHistory}); - }; + }); } function initBrowser(url, basePath) { return function($browser){ @@ -350,7 +350,8 @@ describe('$location', function() { describe('wiring', function() { - beforeEach(inject(initService(false, '!', true), initBrowser('http://new.com/a/b#!', '/a/b'))); + beforeEach(initService(false, '!', true)); + beforeEach(inject(initBrowser('http://new.com/a/b#!', '/a/b'))); it('should update $location when browser url changes', inject(function($browser, $location) { @@ -413,30 +414,34 @@ describe('$location', function() { // html5 history is disabled describe('disabled history', function() { - it('should use hashbang url with hash prefix', inject( - initService(false, '!'), - initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/index.html#!/a/b'); - $location.path('/new'); - $location.search({a: true}); - $rootScope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#!/new?a'); - }) - ); - - - it('should use hashbang url without hash prefix', inject( - initService(false, ''), - initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/index.html#/a/b'); - $location.path('/new'); - $location.search({a: true}); - $rootScope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#/new?a'); - }) - ); + it('should use hashbang url with hash prefix', function() { + initService(false, '!'); + inject( + initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#!/new?a'); + } + ); + }); + + + it('should use hashbang url without hash prefix', function() { + initService(false, ''); + inject( + initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#/new?a'); + } + ); + }); }); @@ -447,26 +452,30 @@ describe('$location', function() { dealoc($document); })); - it('should use hashbang url with hash prefix', inject( - initService(true, '!!', false), - initBrowser('http://domain.com/base/index.html#!!/a/b', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/index.html#!!/a/b'); - $location.path('/new'); - $location.search({a: true}); - $rootScope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#!!/new?a'); - }) - ); - - - it('should redirect to hashbang url when new url given', inject( - initService(true, '!'), - initBrowser('http://domain.com/base/new-path/index.html', '/base/index.html'), - function($browser, $location) { - expect($browser.url()).toBe('http://domain.com/base/index.html#!/new-path/index.html'); - }) - ); + it('should use hashbang url with hash prefix', function() { + initService(true, '!!', false); + inject( + initBrowser('http://domain.com/base/index.html#!!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!!/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#!!/new?a'); + } + ); + }); + + + it('should redirect to hashbang url when new url given', function() { + initService(true, '!'); + inject( + initBrowser('http://domain.com/base/new-path/index.html', '/base/index.html'), + function($browser, $location) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!/new-path/index.html'); + } + ); + }); }); @@ -477,41 +486,47 @@ describe('$location', function() { dealoc($document); })); - it('should use new url', inject( - initService(true, '', true), - initBrowser('http://domain.com/base/old/index.html#a', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/old/index.html#a'); - $location.path('/new'); - $location.search({a: true}); - $rootScope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/new?a#a'); - }) - ); - - - it('should rewrite when hashbang url given', inject( - initService(true, '!', true), - initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/a/b'); - $location.path('/new'); - $location.hash('abc'); - $rootScope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/new#abc'); - expect($location.path()).toBe('/new'); - }) - ); - - - it('should rewrite when hashbang url given (without hash prefix)', inject( - initService(true, '', true), - initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), - function($rootScope, $location, $browser) { - expect($browser.url()).toBe('http://domain.com/base/a/b'); - expect($location.path()).toBe('/a/b'); - }) - ); + it('should use new url', function() { + initService(true, '', true); + inject( + initBrowser('http://domain.com/base/old/index.html#a', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/old/index.html#a'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/new?a#a'); + } + ); + }); + + + it('should rewrite when hashbang url given', function() { + initService(true, '!', true); + inject( + initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/a/b'); + $location.path('/new'); + $location.hash('abc'); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/new#abc'); + expect($location.path()).toBe('/new'); + } + ); + }); + + + it('should rewrite when hashbang url given (without hash prefix)', function() { + initService(true, '', true); + inject( + initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/a/b'); + expect($location.path()).toBe('/a/b'); + } + ); + }); }); @@ -604,7 +619,7 @@ describe('$location', function() { var root, link, originalBrowser, lastEventPreventDefault; function configureService(linkHref, html5Mode, supportHist, attrs, content) { - return function($provide, $locationProvider){ + module(function($provide, $locationProvider) { var jqRoot = jqLite('<div></div>'); attrs = attrs ? ' ' + attrs + ' ' : ''; link = jqLite('<a href="' + linkHref + '"' + attrs + '>' + content + '</a>')[0]; @@ -616,7 +631,7 @@ describe('$location', function() { $provide.value('$sniffer', {history: supportHist}); $locationProvider.html5Mode(html5Mode); $locationProvider.hashPrefix('!'); - }; + }); } function initBrowser() { @@ -654,152 +669,178 @@ describe('$location', function() { }); - it('should rewrite rel link to new url when history enabled on new browser', inject( - configureService('link?a#b', true, true), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectRewriteTo($browser, 'http://host.com/base/link?a#b'); - }) - ); - - - it('should rewrite abs link to new url when history enabled on new browser', inject( - configureService('/base/link?a#b', true, true), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectRewriteTo($browser, 'http://host.com/base/link?a#b'); - }) - ); - - - it('should rewrite rel link to hashbang url when history enabled on old browser', inject( - configureService('link?a#b', true, false), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); - }) - ); - - - it('should rewrite abs link to hashbang url when history enabled on old browser', inject( - configureService('/base/link?a#b', true, false), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); - }) - ); - - - it('should not rewrite when history disabled', inject( - configureService('#new', false), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectNoRewrite($browser); - }) - ); - - - it('should not rewrite ng:ext-link', inject( - configureService('#new', true, true, 'ng:ext-link'), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectNoRewrite($browser); - }) - ); - - - it('should not rewrite full url links do different domain', inject( - configureService('http://www.dot.abc/a?b=c', true), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectNoRewrite($browser); - }) - ); - - - it('should not rewrite links with target="_blank"', inject( - configureService('/a?b=c', true, true, 'target="_blank"'), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectNoRewrite($browser); - }) - ); - - - it('should not rewrite links with target specified', inject( - configureService('/a?b=c', true, true, 'target="some-frame"'), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectNoRewrite($browser); - }) - ); - - - it('should rewrite full url links to same domain and base path', inject( - configureService('http://host.com/base/new', true), - initBrowser(), - initLocation(), - function($browser) { - browserTrigger(link, 'click'); - expectRewriteTo($browser, 'http://host.com/base/index.html#!/new'); - }) - ); - - - it('should rewrite when clicked span inside link', inject( - configureService('some/link', true, true, '', '<span>link</span>'), - initBrowser(), - initLocation(), - function($browser) { - var span = jqLite(link).find('span'); - - browserTrigger(span, 'click'); - expectRewriteTo($browser, 'http://host.com/base/some/link'); - }) - ); + it('should rewrite rel link to new url when history enabled on new browser', function() { + configureService('link?a#b', true, true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/link?a#b'); + } + ); + }); - // don't run next tests on IE<9, as browserTrigger does not simulate pressed keys - if (!(msie < 9)) { + it('should rewrite abs link to new url when history enabled on new browser', function() { + configureService('/base/link?a#b', true, true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/link?a#b'); + } + ); + }); + - it('should not rewrite when clicked with ctrl pressed', inject( - configureService('/a?b=c', true, true), + it('should rewrite rel link to hashbang url when history enabled on old browser', function() { + configureService('link?a#b', true, false); + inject( initBrowser(), initLocation(), function($browser) { - browserTrigger(link, 'click', ['ctrl']); + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); + } + ); + }); + + + it('should rewrite abs link to hashbang url when history enabled on old browser', function() { + configureService('/base/link?a#b', true, false); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); + } + ); + }); + + + it('should not rewrite when history disabled', function() { + configureService('#new', false); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + } + ); + }); + + + it('should not rewrite ng:ext-link', function() { + configureService('#new', true, true, 'ng:ext-link'); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + } + ); + }); + + + it('should not rewrite full url links do different domain', function() { + configureService('http://www.dot.abc/a?b=c', true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); expectNoRewrite($browser); - }) + } ); + }); + + + it('should not rewrite links with target="_blank"', function() { + configureService('/a?b=c', true, true, 'target="_blank"'); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + } + ); + }); - it('should not rewrite when clicked with meta pressed', inject( - configureService('/a?b=c', true, true), + it('should not rewrite links with target specified', function() { + configureService('/a?b=c', true, true, 'target="some-frame"'); + inject( initBrowser(), initLocation(), function($browser) { - browserTrigger(link, 'click', ['meta']); + browserTrigger(link, 'click'); expectNoRewrite($browser); - }) + } ); + }); + + + it('should rewrite full url links to same domain and base path', function() { + configureService('http://host.com/base/new', true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/new'); + } + ); + }); + + + it('should rewrite when clicked span inside link', function() { + configureService('some/link', true, true, '', '<span>link</span>'); + inject( + initBrowser(), + initLocation(), + function($browser) { + var span = jqLite(link).find('span'); + + browserTrigger(span, 'click'); + expectRewriteTo($browser, 'http://host.com/base/some/link'); + } + ); + }); + + + // don't run next tests on IE<9, as browserTrigger does not simulate pressed keys + if (!(msie < 9)) { + + it('should not rewrite when clicked with ctrl pressed', function() { + configureService('/a?b=c', true, true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click', ['ctrl']); + expectNoRewrite($browser); + } + ); + }); + + + it('should not rewrite when clicked with meta pressed', function() { + configureService('/a?b=c', true, true); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click', ['meta']); + expectNoRewrite($browser); + } + ); + }); } }); }); diff --git a/test/service/logSpec.js b/test/service/logSpec.js index ee250b66..98158ae0 100644 --- a/test/service/logSpec.js +++ b/test/service/logSpec.js @@ -9,7 +9,7 @@ describe('$log', function() { function info() { logger+= 'info;'; } function error() { logger+= 'error;'; } - beforeEach(inject(function($provide){ + beforeEach(module(function($provide){ $window = {}; logger = ''; $provide.service('$log', $LogProvider); diff --git a/test/service/parseSpec.js b/test/service/parseSpec.js index f57a52c7..08167843 100644 --- a/test/service/parseSpec.js +++ b/test/service/parseSpec.js @@ -154,7 +154,10 @@ describe('parser', function() { }); }); - var scope; + var scope, $filterProvider; + beforeEach(module(['$filterProvider', function (filterProvider) { + $filterProvider = filterProvider; + }])); beforeEach(inject(function ($rootScope) { scope = $rootScope; })); @@ -191,19 +194,19 @@ describe('parser', function() { expect(scope.$eval("'a' + 'b c'")).toEqual("ab c"); }); - it('should parse filters', inject(function($filterProvider) { + it('should parse filters', function() { $filterProvider.register('substring', valueFn(function(input, start, end) { return input.substring(start, end); })); expect(function() { scope.$eval("1|nonexistent"); - }).toThrow(new Error("Unknown provider for 'nonexistentFilter'.")); + }).toThrow(new Error("Unknown provider: nonexistentFilterProvider <- nonexistentFilter")); scope.offset = 3; expect(scope.$eval("'abcd'|substring:1:offset")).toEqual("bc"); expect(scope.$eval("'abcd'|substring:1:3|uppercase")).toEqual("BC"); - })); + }); it('should access scope', function() { scope.a = 123; diff --git a/test/service/scopeSpec.js b/test/service/scopeSpec.js index e1e8ab8b..96271bc9 100644 --- a/test/service/scopeSpec.js +++ b/test/service/scopeSpec.js @@ -117,15 +117,18 @@ describe('Scope', function() { })); - it('should delegate exceptions', inject(function($exceptionHandlerProvider) { - $exceptionHandlerProvider.mode('log'); - }, function($rootScope, $exceptionHandler, $log) { - $rootScope.$watch('a', function() {throw new Error('abc');}); - $rootScope.a = 1; - $rootScope.$digest(); - expect($exceptionHandler.errors[0].message).toEqual('abc'); - $log.assertEmpty(); - })); + it('should delegate exceptions', function() { + module(function($exceptionHandlerProvider) { + $exceptionHandlerProvider.mode('log'); + }); + inject(function($rootScope, $exceptionHandler, $log) { + $rootScope.$watch('a', function() {throw new Error('abc');}); + $rootScope.a = 1; + $rootScope.$digest(); + expect($exceptionHandler.errors[0].message).toEqual('abc'); + $log.assertEmpty(); + }); + }); it('should fire watches in order of addition', inject(function($rootScope) { @@ -459,25 +462,29 @@ describe('Scope', function() { })); - it('should catch exceptions', inject(function($exceptionHandlerProvider) { + it('should catch exceptions', function() { + module(function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); - }, function($rootScope, $exceptionHandler, $log) { - var log = ''; - var child = $rootScope.$new(); - $rootScope.$watch('a', function(scope, a) { log += '1'; }); - $rootScope.a = 0; - child.$apply(function() { throw new Error('MyError'); }); - expect(log).toEqual('1'); - expect($exceptionHandler.errors[0].message).toEqual('MyError'); - $log.error.logs.shift(); - })); + }); + inject(function($rootScope, $exceptionHandler, $log) { + var log = ''; + var child = $rootScope.$new(); + $rootScope.$watch('a', function(scope, a) { log += '1'; }); + $rootScope.a = 0; + child.$apply(function() { throw new Error('MyError'); }); + expect(log).toEqual('1'); + expect($exceptionHandler.errors[0].message).toEqual('MyError'); + $log.error.logs.shift(); + }); + }); describe('exceptions', function() { var log; - beforeEach(inject(function($exceptionHandlerProvider) { - $exceptionHandlerProvider.mode('log'); - }, function($rootScope) { + beforeEach(module(function($exceptionHandlerProvider) { + $exceptionHandlerProvider.mode('log'); + })); + beforeEach(inject(function($rootScope) { log = ''; $rootScope.$watch(function() { log += '$digest;'; }); $rootScope.$digest(); @@ -613,10 +620,10 @@ describe('Scope', function() { log += event.currentScope.id + '>'; } - beforeEach(inject( - function($exceptionHandlerProvider) { + beforeEach(module(function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); - }, function($rootScope) { + })); + beforeEach(inject(function($rootScope) { log = ''; child = $rootScope.$new(); grandChild = child.$new(); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 632724ce..753a36b4 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -247,8 +247,8 @@ describe('widget', function() { }; } + beforeEach(module(spyOnAutoScroll())); beforeEach(inject( - spyOnAutoScroll(), putIntoCache('template.html', 'CONTENT'), putIntoCache('another.html', 'CONTENT'))); @@ -681,7 +681,7 @@ describe('widget', function() { it('should be possible to nest ng:view in ng:include', inject(function() { // TODO(vojta): refactor this test - var injector = angular.injector('ng', 'ngMock'); + var injector = angular.injector(['ng', 'ngMock']); var myApp = injector.get('$rootScope'); var $httpBackend = injector.get('$httpBackend'); $httpBackend.expect('GET', 'includePartial.html').respond('view: <ng:view></ng:view>'); |
