diff options
| author | Igor Minar | 2012-03-16 10:48:59 -0700 | 
|---|---|---|
| committer | Igor Minar | 2012-03-16 10:52:40 -0700 | 
| commit | f13dd3393dfb7a33565c9360342c193bc0bddcb6 (patch) | |
| tree | fcf54fb63bb30dcf9e131c8d34d440b626019fa9 | |
| parent | bca96e7c7cc723a091241fddd6845d6de262a3c9 (diff) | |
| download | angular.js-f13dd3393dfb7a33565c9360342c193bc0bddcb6.tar.bz2 | |
feat(injector): infer _foo_ as foo
this is to enable nicer tests:
 describe('fooSvc', function() {
   var fooSvc;
   beforeEach(inject(function(_fooSvc_) {
     fooSvc = _fooSvc_;
   }));
   it('should do this thing', function() {
     //test fooSvc
   });
 });
| -rw-r--r-- | docs/content/guide/dev_guide.di.understanding_di.ngdoc | 97 | ||||
| -rw-r--r-- | src/Injector.js | 4 | ||||
| -rw-r--r-- | test/InjectorSpec.js | 6 | 
3 files changed, 105 insertions, 2 deletions
| diff --git a/docs/content/guide/dev_guide.di.understanding_di.ngdoc b/docs/content/guide/dev_guide.di.understanding_di.ngdoc index dd6dda03..9b48585c 100644 --- a/docs/content/guide/dev_guide.di.understanding_di.ngdoc +++ b/docs/content/guide/dev_guide.di.understanding_di.ngdoc @@ -87,6 +87,103 @@ minifiers/obfuscators. In the future, we may provide a pre-processor which will  code and insert the `$inject` into the source code so that it can be minified/obfuscated. +### Dependency inference and variable name shadowing + +During inference, the injector considers argument names with leading and trailing underscores to be +equivivalent to the name without these underscores. For example `_fooSvc_` argument name is treated +as if it was `fooSvc`, this is useful especially in tests where variable name shadowing can cause +some friction. This is best illustrated on examples: + +When testing a service, it's common to need a reference to it in every single test. This can be +done in jasmine with DI inference like this: + +<pre> +describe('fooSvc', function() { +  it('should do this thing', inject(function(fooSvc) { +    //test fooSvc +  })); + +  it('should do that thing', inject(function(fooSvc) { +    //test fooSvc +  })); + +  // more its +}); +</pre> + +... but having to inject the service over and over gets easily tiresome. + +It's likely better to rewrite these tests with a use of jasmine's `beforeEach`: + +<pre> +describe('fooSvc', function() { +  var fooSvc; + +  beforeEach(inject(function(fooSvc) { +    fooSvc = fooSvc; // DOESN'T WORK! outer fooSvc is being shadowed +  })); + +  it('should do this thing', function() { +    //test fooSvc +  }); + +  it('should do that thing', function() { +    //test fooSvc +  }); + +  // more its +}); +</pre> + +This obviously won't work because `fooSvc` variable in the describe block is being shadowed by the +`fooSvc` argument of the beforeEach function. So we have to resort to alternative solutions, like +for example use of array notation to annotate the beforeEach fn: + +<pre> +describe('fooSvc', function() { +  var fooSvc; + +  beforeEach(inject(['fooSvc', function(fooSvc_) { +    fooSvc = fooSvc_; +  }])); + +  it('should do this thing', function() { +    //test fooSvc +  }); + +  it('should do that thing', function() { +    //test fooSvc +  }); +}); +</pre> + + +That's better, but it's still annoying, especially if you have many services to inject. + +To resolve this shadowing problem, the injector considers `_fooSvc_` argument names equal to +`fooSvc`, so the test can be rewritten like this: + +<pre> + describe('fooSvc', function() { +   var fooSvc; + +   beforeEach(inject(function(_fooSvc_) { +     fooSvc = _fooSvc_; +   })); + +   it('should do this thing', function() { +     //test fooSvc +   }); + +   it('should do that thing', function() { +     //test fooSvc +   }); + +   // more its + }); +</pre> + +  ## Related Topics  * {@link dev_guide.services Angular Services} diff --git a/src/Injector.js b/src/Injector.js index 10072959..1844db2a 100644 --- a/src/Injector.js +++ b/src/Injector.js @@ -40,7 +40,7 @@  var FN_ARGS = /^function\s*[^\(]*\(([^\)]*)\)/m;  var FN_ARG_SPLIT = /,/; -var FN_ARG = /^\s*(.+?)\s*$/; +var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;  function inferInjectionArgs(fn) {    assertArgFn(fn); @@ -49,7 +49,7 @@ function inferInjectionArgs(fn) {      var fnText = fn.toString().replace(STRIP_COMMENTS, '');      var argDecl = fnText.match(FN_ARGS);      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ -      arg.replace(FN_ARG, function(all, name){ +      arg.replace(FN_ARG, function(all, underscore, name){          args.push(name);        });      }); diff --git a/test/InjectorSpec.js b/test/InjectorSpec.js index cc5c5b50..16cf1524 100644 --- a/test/InjectorSpec.js +++ b/test/InjectorSpec.js @@ -147,6 +147,12 @@ describe('injector', function() {      }); +    it('should strip leading and trailing underscores from arg name during inference', function() { +      function beforeEachFn(_foo_) { /* foo = _foo_ */ }; +      expect(inferInjectionArgs(beforeEachFn)).toEqual(['foo']); +    }); + +      it('should handle no arg functions', function() {        function $f_n0() {}        expect(inferInjectionArgs($f_n0)).toEqual([]); | 
