how to unittest function in angular js? - angularjs

Just starting with angular unit testing and want to know something abt testing functions in controllers. I found some samples of how to unit test with karma but they all have the functions like this:
$scope.someFunction= function(){....}
Is it possible to just define the function without putting it on the $scope?

Yes you could, but that way functions would be like "private" functions, only accessible from inside your controller since controller are usually not accessible from other modules (controllers, directives or services).
The only way you would access a controller directly is when using them as API for a custom directive, see for example ngModelController for directive ngModel.

Related

How to identify NOT used controllers, factories, directives

I have huge angularjs app, with lots of controllers,factories and directives. I would like to find out if any of the component (controllers,factories and directives) NOT in use delete whole js. E.g. If controller "aboutController" is NOT used anywhere I want to delete it. Same way for factories and directives.
I have tried chrome's extension- JavaScript Tracker. I am also trying to use gulp-unused but it is providing NOT used code and I need NOT used js.

If I need to use IIFE, why doesn't Angular use it?

In John Papa's style guide he mentions the need to wrap every component in (function(){..}). This adds a couple lines to my code which makes me worried but not enough to justify a long work-around.
However, when I look at the actual Angular Code like the code for $compile and controller, I don't see these declarations.
Why is it important for me to isolate my variables with IIFE if Ng doesn't see it as important? Or a better question is why doesn't Angular implement IIFE?
Angular does use IIFE it wraps the code in
(function(window, document, undefined) {'use strict';
...
})(window, document);
So this distinguishes and protects the global/outer context and environment as a whole for all angular code
You can verify here
So it is wrapping the entire app right? But it isn't wrapping the
individual components
To answer your question, these components are not in separate files and are contained in single IIFE
the separate modules like angular-route, ng-resource are separated with angular.module() namespace or modular pattern from the global context
I think the answer may be, it depends.
First of all, AngularJS has to expose angular for the user to use, so it cannot be inside an IIFE. (just like jQuery exposes $ and jQuery, although it has an option that it only exposes jQuery).
And then, if you do decide to go with AngularJS, it won't be surprising that AngularJS expose some other stuff to the global space. But so far I have used AngularJS, I have only seen angular being exposed and all the things I do, I do it as
angular.module()
.controller()
.directive()
.factory()
.service();
and $compile is not exposed to the global space.
You only use IIFE to create a local scope so that the variables will not become part of the global scope.

Are Angular directive controllers only meant for exposing publicly?

From the AngularJS directive documentation:
Best Practice: use controller when you want to expose an API to other
directives. Otherwise use link.
Is this really the only case to use controllers inside directives?
what about some init functionality such as defaulting variable and scope values? should it generally go into link, unless publicly exposed?
I only use "link" when I have to implement some deeper DOM manipulation. Any "regular" component should use controllers. Basically the idea is to use "link" only when you don't have any other option as it's more involved and requires a deeper understanding of how Angular SJ works.

Does it make sense to have both link and controller on a directive?

From what I've gathered, link deals with dom manipulation while controller deals with directive specific logic. So does it make sense to have both link and controller with a directive? Since compile returns link, what about compile and controller used together?
For the number of directive that i have seen here is something that seems to be common
You implement controller if you want to expose an API for your directive. This API is used to control the directive. When directives take dependencies on other directives using require, what gets injected is a controller instance.
When dealing with forms we see FormController and NgModelController which are good examples of directive controllers.
For most of the other cases link function used.
For small cases if we need to do DOM manipulation compile can be used

Registering AngularJS components via providers

I'm implementing an Angular/RequireJS routing solution based on Dan Wahlin's article.
In the article, Dan makes the following register shortcuts on his app object:
app.register =
{
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
When I use these, I can correctly register and reference my controllers through RequireJS calls, but if I use the traditionall app.controller() or angular.module('myApp').controller() syntax, then Angular can't find them and I get errors from the router.
How is defining controllers, directives, etc. with the above method different, and why does it work with RequireJS where the more traditional method does not?
Any ideas?
Thanks,
-Nate
Since the controllers are being added dynamically things have to change a bit from the "norm" (unfortunately). The main difference is that controllers are being wrapped in RequireJS modules, being downloaded dynamically, and then being registered. The $controllerProvider.register allows for the dynamic registration. It's definitely not the normal technique but what's required in this scenario. That's why "app" (which is the RequireJS module that gets us to the application's AngularJS module) is passed in to all of the controller modules. It exposes the controller property shown above which handles the registration "on the fly".
If you download a controller script dynamically and then use the normal technique (angular.module('..').controller(..)) it won't register it properly - at least that was the case the last time I tried it. It's been several months since I've tried it but I'm assuming the same behavior is still there.
The bottom line is that when controllers (and other items such as services/factories) have scripts that are loaded "on the fly" things change somewhat and the way you access and register these items changes from the normal way that we're all used to seeing.

Resources