From 6ec5946094ee92b820bbacc886fa2367715e60b4 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Sun, 30 Nov 2014 16:40:53 +0200 Subject: [PATCH] feat(ngMocks): cleanup $inject annotations after each test this will help in detecting unannotated functions both in apps and angular core in case only part of the tests are run with strictDi --- src/auto/injector.js | 4 ++-- src/ngMock/angular-mocks.js | 14 ++++++++++++++ test/auto/injectorSpec.js | 6 +++++- test/ngMock/angular-mocksSpec.js | 33 ++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/auto/injector.js b/src/auto/injector.js index 5235f7c1e742..fb1dc3960a26 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -800,7 +800,7 @@ function createInjector(modulesToLoad, strictDi) { } var args = [], - $inject = annotate(fn, strictDi, serviceName), + $inject = createInjector.$$annotate(fn, strictDi, serviceName), length, i, key; @@ -839,7 +839,7 @@ function createInjector(modulesToLoad, strictDi) { invoke: invoke, instantiate: instantiate, get: getService, - annotate: annotate, + annotate: createInjector.$$annotate, has: function(name) { return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); } diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index b54c7f9bf731..1488f1b63b89 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2127,18 +2127,32 @@ angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) { if (window.jasmine || window.mocha) { var currentSpec = null, + annotatedFunctions, isSpecRunning = function() { return !!currentSpec; }; + angular.mock.$$annotate = angular.injector.$$annotate; + angular.injector.$$annotate = function(fn) { + if (typeof fn === 'function' && !fn.$inject) { + annotatedFunctions.push(fn); + } + return angular.mock.$$annotate.apply(this, arguments); + }; + (window.beforeEach || window.setup)(function() { + annotatedFunctions = []; currentSpec = this; }); (window.afterEach || window.teardown)(function() { var injector = currentSpec.$injector; + annotatedFunctions.forEach(function(fn) { + delete fn.$inject; + }); + angular.forEach(currentSpec.$modules, function(module) { if (module && module.$$hashKey) { module.$$hashKey = undefined; diff --git a/test/auto/injectorSpec.js b/test/auto/injectorSpec.js index 2132092c5166..049e3b91f193 100644 --- a/test/auto/injectorSpec.js +++ b/test/auto/injectorSpec.js @@ -238,7 +238,11 @@ describe('injector', function() { it('should publish annotate API', function() { - expect(injector.annotate).toBe(annotate); + expect(angular.mock.$$annotate).toBe(annotate); + spyOn(angular.mock, '$$annotate').andCallThrough(); + function fn() {} + injector.annotate(fn); + expect(angular.mock.$$annotate).toHaveBeenCalledWith(fn); }); }); diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 54ea6f340d0f..dc6652ce4e30 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -787,6 +787,39 @@ describe('ngMock', function() { expect(testFn.$$hashKey).toBeUndefined(); }); }); + + describe('$inject cleanup', function() { + function testFn() { + + } + + it('should add $inject when invoking test function', inject(function($injector) { + $injector.invoke(testFn); + expect(testFn.$inject).toBeDefined(); + })); + + it('should cleanup $inject after previous test', function() { + expect(testFn.$inject).toBeUndefined(); + }); + + it('should add $inject when annotating test function', inject(function($injector) { + $injector.annotate(testFn); + expect(testFn.$inject).toBeDefined(); + })); + + it('should cleanup $inject after previous test', function() { + expect(testFn.$inject).toBeUndefined(); + }); + + it('should invoke an already annotated function', inject(function($injector) { + testFn.$inject = []; + $injector.invoke(testFn); + })); + + it('should not cleanup $inject after previous test', function() { + expect(testFn.$inject).toBeDefined(); + }); + }); }); describe('in DSL', function() {