Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(injector): infer _foo_ as foo
Browse files Browse the repository at this point in the history
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
   });
 });
  • Loading branch information
IgorMinar committed Mar 16, 2012
1 parent bca96e7 commit f13dd33
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
97 changes: 97 additions & 0 deletions docs/content/guide/dev_guide.di.understanding_di.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
4 changes: 2 additions & 2 deletions src/Injector.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
});
});
Expand Down
6 changes: 6 additions & 0 deletions test/InjectorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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([]);
Expand Down

0 comments on commit f13dd33

Please sign in to comment.