Where do the module and inject jasmine functions come from? - angularjs

I keep seeing jasmine specs testing angular controllers/directives/filters employing these two functions but where do they come from? Where can I find their documentations?

Both come from Angular itself:
Angular.Mock.Inject documentation
Angular.Mock.Module documentation
I believe both are defined in angular-mocks.js, which puts module and inject as properties on window.

Related

how to unittest function in angular js?

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.

Sharing data between two directives (but not part of the same module)

I have the following situation:
I have my app (module "zmApp") which has a directive, "myDirective"
I am also using a 3rd party angular directive, lets call it "thirdPartyDirective", which is defined under "thirdPartyModule" by that author.
What I now want to do is share some data between 'myDirective' which is part of "zmApp" and "thirdPartyDirective" which is defined under "thirdPartyModule"
I tried creating a factory in zmApp and injecting it into "thirdPartyDirective", but that throws an error "Reference not found". I suspect its because they are two different modules.
I know directives can also have controllers, but my guess is if factories did not work nor will controllers.
How do I solve this predicament?
Many thanks

Breeze Angular Service Not Configuring Breeze to Angular Promises

I cannot get the Breeze Angular service (http://www.getbreezenow.com/documentation/breeze-angular) to configure Breeze to use Angular promises, i.e., I can never get the useNgPromises() function within breeze.bridge.angular.js to log a message to the console and thus I assume Breeze is never configured to use Angular promises.
My JS files are loaded as follows:
angular.js (v 1.3.14)
angular-route.js (v.1.3.14)
q.js (v 1.1.2) - This is here because I kept getting errors that Q was undefined if I left this out. I don't know if it is necessary to load Q.js if I use Angular promises instead.
breeze.js (v 1.5.3)
breeze.bridge.angular.js (v 1.1.0)
app.js and other app-specific JS files
So far, that satisfies steps #1 and #2 from the "Install It" section of that Breeze page.
Per steps #3 and #4 on that Breeze page and comments in breeze.bridge.angular.js, this is what my app.js looks like:
window.myApp = angular.module("myApp", [
"breeze.angular"
])
.value("breeze", window.breeze)
.config(["$routeProvider", function ($routeProvider) {
// Routing code
}])
.run(['breeze', function (breeze) {}]);
As far as I can tell, that code matches the Example #1 code on that Breeze page and satisfies steps #3 and #4 on that Breeze page.
Then I have some basic views that use controllers and datacontext JS files, the latter of which inject the breeze object as a dependency. To test whether Breeze is actually executing the configuration to work with Angular promises, I edited the breeze.bridge.angular.js file such that the following statement is included as the first line in the useNgPromises() function:
console.log("Using Angular promises!");
When I run my app, I never see that in the console, so I assume the configuration is not happening.
Am I doing something wrong in the setup? If so, what?
You absolutely do NOT need Q.js; the fact that you see errors relating to that library is an indication of a configuration mistake.
I think you found the problem when you added .value("breeze", window.breeze).
That one line wipes out the definition of the breeze service established by the 'breeze.angular' module (defined in breeze.bridge.angular.js), thus preventing the configuration of breeze for $http and $q. Without that configuration, breeze looks for a promises implementation elsewhere ... hence the complaint about missing Q.js. So ... yes ... that line was a disaster.
I wondered where you got the idea for that line. Thanks for referencing the Microsoft ASP Breeze/Angular template documentation. Wow that is old (2013). I'd kill it ... and the other defunct Visual Studio Breeze templates ... if I could (maybe I can). I thought we had made them hard to find. Looks like you found them. How?
That certainly isn't how we teach Breeze + Angular these days.
The "Todo Angular" sample is a far better guide (even if it is a year old).
I resolved the issue by commenting out the line:
.value("breeze", window.breeze)
I had included that line per the "Dependency Injection" section here: http://www.getbreezenow.com/ng-spa-template#module as well as the "Value Recipe" section here: https://docs.angularjs.org/guide/providers, but apparently it does not play well with the Breeze Angular service.
I am not sure exactly why this is the case but my best guess is that the issue was caused by Angular values not being configurable, per this explanation: https://gist.github.com/demisx/9605099, and I assume the Breeze Angular service requires the Breeze object to be configurable and therefore it should not be injected as a dependency for the app via the value recipe.
I should also note that after removing that troublesome line of code, I no longer receive an error indicating that Q.js is required since the Breeze Angular service successfully configures Breeze to use Angular's $q instead.

Lazy loading AngularJS modules with RequireJS

Thanks to the great article from Dan Wahlin, I managed to implement lazy loading of Angular's controllers and services. However, there does not seem to be a clean way to lazy load independent modules.
To better explain my question, assume that I have an app would be structure as below without RequireJS:
// Create independent module 'dataServices' module with 'Pictures' object
angular.module("dataServices", []).factory("Pictures", function (...) {...});
// Create 'webapp' ng-app, with dependency to 'dataServices', defining controllers
angular.module("webapp", ['dataServices'])
.controller("View1Controller", function (...) {...})
.controller("View2Controller", function (...) {...});
Here is the sample app with RequireJS in Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn
The core of the problem is that Angular does not allow adding dependency to ng-app post instantiation. As result, my solution is to use angular.injector to retrieve the instance of Picture object to be used in my View2Controller. See js/scripts/controllers/ctrl2.js file.
This creates 2 problems for me:
The injected services runs outside of angular and therefore all async call must end with $scope.$apply()
Messy code where some object can be injected using standard angular syntax while others require the explicit use of injector.
Have any of you figured out how to lazy load independent module using RequireJS and somehow hook this module in angular so normal angular dependency injection syntax can be used?
Note:
The question is on lazy loading of independent module. One simple solution to this specific example is to create "Pictures" object using cached $providers during ng-app.config but that is not what I am looking for. I am looking for solution that works with 3rd party module such as angular-resource.
I finalized my own implementation called angularAMD and here is the sample site that uses it:
http://marcoslin.github.io/angularAMD/
It handles config functions and out of order module definitions.
Hopefully this can help other looking for something to help them with RequireJS and AngularJS integration.
Take a look at my project in GitHub: angular-require-lazy
This project is intended to demonstrate an idea and motivate discussions. But is does what you want (check expenses-view.js, it loads ng-grid lazily).
I am very interested in comments, ideas etc.
(EDIT) The ng-grid Angular module is lazy loaded as follows:
expenses-view.js is loaded lazily, when the /expenses route is activated
expenses-view.js specifies ng-grid as a dependency, so RequireJs loads ng-grid first
ng-grid is the one that calls angular.module(...)
In order to accomplish this, I replaced (proxied actually) the real angular.module method with my own, that supports laziness. See bootstrap.js and route-config.js (the functions initLazyModules() and callRunBlocks()).
This implementation has its drawbacks that you should be aware of:
Config functions are not implemented (yet). I do not know if it is possible to lazily provide config-time dependencies.
Order matters in definitions. If service A depends on B but A is defined after B in your module, DI wil fail. This is because the lazyAngular proxy executes definitions immediately, unlike real Angular that makes sure dependencies are resolved before executing the definitions.
It looks like the Node.js module ocLazyLoad defines a way of doing this lazy-loading, though I'm not sure how it fares, performance-wise, compared to the methods in the other answers or hard-coding the dependencies. Any info on this would be appreciated. One interesting thing is that the other answers need RequireJS to operate, while ocLazyLoad doesn't.
It looks like ocLazyLoad defines another provider that injects the dependency after the containing module has already been instantiated. It seems to do this by essentially replicating some low-level Angular behavior, like module loading and providing, hence why it looks so complicated. It looks like it adds just about every core Angular module as a dependency: $compileProvider, $q, $injector, ng, and so many more.

basic testacular/jasmine/angular setup and usage

I am new to Jasmine, but would like to do more TDD in Javascript. I've been using the Angular library from Google, and I know that Testacular was specifically created for testing Angular apps.
I have read through both the Jasmine documentation and watched the Testacular setup video, but I can't get the most basic testing to work. Assume I have three files:
modules.js
controller.js
appSpec.js
modules.js has my module definition with a few .factory(...) services and a few .directive(...) custom directives. controller.js houses my controllers for wiring up the modules to the html view.
So far, so good. Next I have added appSpec.js. Let's say I want to use it to test a service in my module called, "Data" that has a method, "getData()" which returns a resource.
In testactular init I have told it to watch all three files. I run Testacular and it tells me it is watching the correct files. Super.
What I don't understand is how I get the Jasmine spec know how to look at the module and controller so that they can be tested. If I simply say:
describe('Data Service', function(){
it ('should retrieve two items from the database', function(){
data = Data.getData() //my angular service
expect(data.length).toBe(2);
});
});
Not surprisingly, it has no idea what Data.getData() is.
It seems obvious that somehow I am supposed to bring my module definition and controllers into the spec before I begin writing suites. It must be so obvious that I don't see in the documentation how people are doing it. Tutorials just seem to start writing specs in the spec.js file and assume all is well.
I have seen other posts here where similar questions are being asked, but admittedly they all have a foundation I seem to be lacking. For example, one post talks about not manually creating an instance of the controller, but rather inject dependencies. Why is he creating a new $rootScope object, how is his module being referenced, etc...
I understand that my question is probably just a lack of basic understanding of the Jasmine framework, but I can't seem to squeeze any more understanding from the Jasmine readme file. Can someone point me to a basic explanation of how this is supposed to work?
Thanks.
Try doing module('myModule') in the jasmine test.
Here are some open source angular projects that have great tests to look at:
angular-app
angular-ui
bootstrap
The way that you include your definitions for your tests is through the karma.config.js file
files = [
JASMINE,
JASMINE_ADAPTER,
'../app/lib/icg/object.js',
'../app/lib/icg/geometry.js',
'../app/lib/icg/ubiquity.js',
'../test/unit/icgUbiquitySpec.js',
'../test/unit/icgObjectSpec.js'
];
Here you define which files get loaded into your browser, the first files that don't include the word 'Spec' are the definitions and the ones that do include are my test files. You need to include your definitions BEFORE your tests so that they are defined before you run the tests, which is why I include all my spec files last.

Resources