AngularJS Jasmine: mocking ngModule with dependencies - javascript

So in my project I'm using only one module everywhere.
Here is how it looks:
angular
.module('moduleToMock', [
'ngAnimate',
'ngAria',
'ngMessages',
'ngRoute',
'ngMaterial',
'md.data.table',
'textAngular',
'ui.utils.masks',
'mp.colorPicker',
'mdPickers',
'ngCookies',
'ngIdle',
'toastr',
'ui.bootstrap',
'ui.bootstrap.typeahead'
])
You see a bunch of services in require section.
Right now I'm going to start writing tests. The error I'm getting is Module 'ngAnimate' is not available. I already found the same question discussed
So as I see, I should go with something like this:
beforeEach(function(){
module('moduleToMock');
module(function ($provide) {
$provide.value('ngAnimate', module('ngAnimate', []));
$provide.value('ngAria', module('ngAria', []));
$provide.value('ngMessages', module('ngMessages', []));
$provide.value('ngRoute', module('ngRoute', []));
$provide.value('ngMaterial', module('ngMaterial', []));
...
});
});
And this piece of code I have to insert in the beginning of each test of each service, factory, controller and etc.? Is there a way to do not copy-paste it each time I'm writing tests? Most of dependencies I have is not being injected into controllers, just declared as ngModule requirenment.

Related

Getting Undefined dependecy on controller in Angular JS

I´m using loopback with angular JS. I have a Person model on loopback and generated the lb-services.js to get acces to the Person model.
I added the lb-services to the module:
(function() {
'use strict';
angular
.module('frontend', ['ngAnimate', 'ngCookies', 'ngTouch', 'ngSanitize', 'ngMessages', 'ngAria', 'ngResource', 'ngRoute', 'ui.bootstrap', 'toastr','lbServices']);
})();
However on my PersonsController when calling the createPerson() method I´m getting that Persons is undefined. I don´t understand why, since I have the dependecy on the controller.
This is my code:
angular.module('frontend').controller('PersonsController',['$scope','Person',function($scope){
$scope.person = {name:'guest',last_name:"none",age:55};
$scope.createPerson= function(){
console.log("CREATING PERSON...");
Person.create({name:$scope.person.name,last_name:$scope.person.last_name,age:$scope.person.age}).$promise
.then(function(){
console.log("Created person.")
});
};
}])
Can anyone help me out?
angular.module('frontend').controller('PersonsController',['$scope','Person',function($scope, Person){
just add Person as second parameter in function declaration and read the docs about DI in angular.

Why does an ngSanitize dependency break my app?

To whom it may concern,
In effort to bind some html, which, to note, will include angular directives, upon injecting an ngSanitize dependency, my app ceases to render. Any thoughts as to why this happens, and whether my code has any blatant issues?
TLDR: everything works fine until bring ngSanitize into the picture!
Working Controller:
angular.module('appName')
.controller('DecksCtrl', function ($scope, Auth, $http) {. . .
Broken Controller:
angular.module('appName', ['ngSanitize'])
.controller('DecksCtrl', function ($scope, Auth, $http) {. . .
Console Errors:
Uncaught Error: [$injector:modulerr] Failed to instantiate module appName due to: Error: [$injector:unpr] Unknown provider: $stateProvider
Thank you
Peter Ward
Your problem is misunderstanding the difference between a module declaration and a reference to an existing module.
To declare a module there are 2 arguments, the name and the dependency array
angular.module('appName', [/* all the dependencies for this module*/]);
Then when you add components you use the module reference getter that does not have second dependency argument. This getter returns the module object for chaining the component(s) to
angular.module('appName')
.controller('DecksCtrl', function ($scope, Auth, $http) {. . .
What you have done is try to inject a dependency into a module reference getter. this in turn over wrote the original declaration for that module
You want to inject it in your app.js . In that yeoman generator its - appName / client / app / app.js
angular.module('yourapp', [
//your injections here
'ngSanitize',
'other injection',
'another injection'
]).config(function ($routeProvider, $locationProvider, $httpProvider) {
You declare all of your apps dependancies here.

Angular controller not loading using OcLazyLoad and ngRoute

I have an app that which has a load of scripts loading initially and the list is growing as development goes on. I want to lazy load scripts which contain controllers as and when needed. I am using OcLazyLoad along with ngRoute for the routing option (i did try ui-route which actually had the same end result but was causing other app issues). The lazy load and routing is working fine, scripts and views are only loaded when needed, but the issue is the controller is not being loaded (Argument 'caseReviewController' is not) so it's as though the controller does not exist.
Here is a simple version of what I have in my app.js file...
var app = angular.module('dashboard', ['oc.lazyLoad', 'ngRoute', 'LocalStorageModule']);
app.config(function ($ocLazyLoadProvider, $routeProvider, localStorageServiceProvider) {
$ocLazyLoadProvider.config({
loadedModules: ['dashboard'], modules: [
{
name: 'caseReview',
files: ['js/controllers/case-review.js']
}
]
});
$routeProvider
//other routes here...
.when('/case-review', {
templateUrl: 'views/case-review.html',
controller: 'caseReviewController',
resolve: {
loadModule: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('caseReview');
}]
}
})
});
In the seperate case-review.js file I have a simple controller
app.controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
This controller is not being found or executed but the view and js file are being lazy loaded as expected. Any help would be great.
Thanks.
In your separate case-review.js, you must get the reference of app.
angular.module('dashboard').controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
As you've mentioned it's in separate file, it may not know about the app variable. It's better to get the reference of the angular module in the separate file.
This must solve your issue.

Module needs to be created twice in AngularJS

If the app.userModule.services module is created first (index.js) and then is instanced to create the factory (UserService.js), why do I get the following error?
Uncaught Error: [$injector:unpr] Unknown provider: $resourceProvider
<- $resource <- UserService
Only if I create the module in UserService (added [ 'ngResource' ]) the application works right.
angular.module('guotay.userModule.services', [ 'ngResource' ]).factory(...
The question: Why the content of user/services/index.js is ignored??
The project structure and some parts of the code:
index.html:
<script src="app/app.js"></script>
<script src="app/components/user/index.js"></script>
<script src="app/components/user/controllers/index.js"></script>
<script src="app/components/user/controllers/LoginCtrl.js"></script>
<script src="app/components/user/services/index.js"></script>
<script src="app/components/user/services/UserService.js"></script>
And the same with other modules
user/index.js
angular.module('app.userModule', [ 'app.userModule.controllers',
'app.userModule.services' ]).config(function config($routeProvider) {...});
user/services/index.js
angular.module('app.userModule.services', []);
user/services/UserService.js
var serviceId = 'UserService';
angular.module('app.userModule.services').factory(serviceId, [ '$resource',
serviceFunc ]);
function serviceFunc($resource) {...}
app.js
angular.module('app', ['ngRoute', 'ngCookies', 'app.userModule', 'app.newsEntryModule'])
.config(...)
.run(function($rootScope, $location, $cookieStore, UserService) {
UserService.get(function(user) {
$rootScope.user = user;
$location.path(originalPath);
});});
I have other services with the same implementation, and they work right with the creation of the module in the index.js, but they not appear in app.js.
Because angular.module('someName', ['list', 'of', 'dependencies']);
is the way you define a module and angular.module('someName') is the way you obtain an instance (retrieve) of an already defined module.
If you define the same module twice the second definition will overwrite the first one - you will loose everything you defined in the first one.
It's all in the docs.
Update:
The browser first loads app.js and only after it loads app/components/user/services/index.js
So any code in app.js depending on stuff from index.js will break.
This is the reason you cannot reference UserService in app.js. It's not yet declared.

AngularJS : get translate key in app.js

In my application, I use the AngularJS module Pascal Precht (translate module). I come to you because I can not get in my method myApp.Run of app.js a translation key.
I can do in a controller or a view. But impossible to get it at the initialization of the project. It shows me the key, not correspondence.
Do you have a solution?
Here is my code:
var myApp = angular.module('myApp', ['ngRoute', 'ngAnimate', 'myApp.filters', 'myApp.services', 'myApp.directives', 'pascalprecht.translate']);
// Declare routeProvider
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {templateUrl:'partials/connectView.html', controller:'ConnectController'});
$routeProvider.when('/homeView', {templateUrl:'partials/homeView.html', controller:'HomeController'});
}]);
// Declare translateProvider
myApp.config(['$translateProvider', function($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'res/localization/lang-',
suffix: '.json'
});
$translateProvider.preferredLanguage('fr_FR');
//$translateProvider.preferredLanguage('en_US');
}]);
// Declare Global variables
myApp.run(['$rootScope', '$filter', function($rootScope, $filter) {
$rootScope.list = false;
etc....
//I'm trying to get translate Key but it doesn't work
console.log($filter('translate')('MY_KEY'));
}]);
My AngularJS version is 1.2.16 (last stable version). Thx
Try injecting the $translate service in app.run().
angular-translate version 1.1.1 and below
myApp.run(['$rootScope', '$translate', '$log', function ($rootScope, $translate, $log) {
$log.debug($translate('MY_KEY'));
}]);
I'd also suggest you to upgrade to the latest version of Pascal Precht's angular-translate. There are some changes in the new version.
angular-translate version 2.0.0 and above
myApp.run(['$rootScope', '$translate', '$log', function ($rootScope, $translate, $log) {
// translate via promises (recommended way)
$translate(['MY_KEY', 'MY_OTHER_KEY'])
.then(function (translation) {
$log.debug(translation.MY_KEY);
});
// translate instantly from the internal state of loaded translation
$log.debug($translate.instant('MY_KEY'));
}]);
See this helpful migration guide.
Why don't you inject the $translate service in the run section
and then call it instead of using the filter?!
console.log($translate('MY_KEY'));
Well, Apparently I can't comment because of reputation issue, we came across something that might be what you are experiencing - since the locale file is downloaded only in the config part of angular, it might not be available (yet) when you call the translate.
We solved this by adding all the locale files upfront (we don't have many and they are small) and in the initialization we just choose the correct one, that way we avoid the problem.
(again this should probably be more of a comment then an answer, but I can't comment...)
This is not a solution for your issue, but if you try the following code in your 'run', you will get an idea, why the translation is not available at the initializing state.
myApp.run(['$rootScope', '$filter','$timeout', function($rootScope, $filter,$timeout) {
$timeout(function(){
alert($filter('translate')('MY_KEY'));
},5000)
}]);
Problem here is, by the time the translation is being loaded the 'run' will be executed. So it cannot be assured that you will get the translation loaded at that time.

Categories