Error with 'inject' angular and jasmine - javascript

I have been trying to find the problem but Im not capable, so
Eco:
Angular and Angular-mocks #1.4.3
Here my karma config file with correct order?
...
files: [
'../../www/lib/angular/angular.js',
'../../www/lib/angular-mocks/angular-mocks.js',
'../../www/js/core/app.js',
'../../www/js/core/**/*.js',
'../../www/js/feature/**/*.js'
],
...
My controller test
describe('HomeCtrl', function () {
beforeEach(function() {
module('app');
});
beforeEach(inject(function() {
}));
})
Error
/Users/rmas/src/node_modules/angular/angular.js:4386:53
forEach#/Users/rmas/src/node_modules/angular/angular.js:336:24
loadModules#/Users/rmas/src/node_modules/angular/angular.js:4346:12
createInjector#/Users/rmas/src/node_modules/angular/angular.js:4272:22
workFn#/Users/rmas/src/node_modules/angular-mocks/angular-mocks.js:2393:60
So I think the problem is angular-mocks ? I have tried with 1.5 version (angular and angular-mocks).
Module is 'app' is not a typing error.
Thanks for your help !

I had a similar problem, the issue was that I was not loading all needed modules, I missed the uiBootstrap module from loading and it was causing that issue as it was a dependency in my app.
Please verify if you have all required modules loaded in the Karma Configuration before trying to inject dependencies.

Related

error[$injector:unpr] Unknown provider: $translateMissingTranslationHandlerLogProvider <-

Getting following error in angularjs:~1.6.0 app while using angular-translate:^2.15.2, translate-loader-static-files:^2.15.2 and grunt-contrib-uglify:^0.7.0:
[$injector:unpr] Unknown provider:
$translateMissingTranslationHandlerLogProvider <-
$translateMissingTranslationHandlerLog
http://errors.angularjs.org/1.6.3/$injector/unpr?p0=%24translateMissingTranslationHandlerLogProvider%20%3C-%20%24translateMissingTranslationHandlerLog
After applying translate-cloak translation keys flicker is gone and app is working smoothly BUT It throws the same error mentioned above when run as grunt server:dist
Is it due to grunt uglyfying process? Any possible suggested fixes?
How It is used inside app.js:
function translateFn($translateProvider) {
$translateProvider
.useStaticFilesLoader({
prefix: 'translations/',
suffix: '.json'
})
.useMissingTranslationHandlerLog();
}
function runFn(SomeService, $translate) {
SomeService.getData()
.then(function () {
$translate.use(some_data.defaults.locale);
});
});
}
ng.module('myApp', [
'ui.router',
.......
'pascalprecht.translate',
.....
])
.config(configFn)
.config(translateFn)
.run(runFn);
Have you installed the angular-translate-handler-log dependency as stated on the docs?
You can use the inline array annotation with run to tell the dependency injector what to inject so that it does not matter if the function arguments get garbled up by a minifier
.run(["SomeService","$translate",runFn]);
bower install angular-translate-handler-log dependency -S

Error: [$injector:modulerr] Failed to instantiate module app due to: State 'frameworks'' is already defined registerState#http://localhost:3030 [duplicate]

I am developing an AngularJS application. To ship the code in production, I'm using this Grunt configuration/task:
grunt.registerTask( 'compile', [
'sass:compile', 'copy:compile_assets', 'ngAnnotate', 'concat:compile_js', 'uglify', 'index:compile'
]);
It's really hard to debug, and it's kind of a question to people who already ran into such problems and can point to some direction.
My main module is including those submodules:
angular
.module('controlcenter', [
'ui.router',
'ui.bootstrap',
'templates-app',
'templates-common',
'authentication',
'api',
'reports',
'interceptors',
'controlcenter.websites',
'controlcenter.users',
'controlcenter.campaigns',
'controlcenter.reports',
'controlcenter.login'
])
.run(run);
The error I get is following:
Uncaught Error: [$injector:modulerr] Failed to instantiate module controlcenter due to:
Error: [$injector:modulerr] Failed to instantiate module controlcenter.websites due to:
Error: State 'websites'' is already defined
If I remove the websites module, I get the same error for
controlcenter.users.
I am using the ui-router to handle routing inside the app.
After my build process (for integration testing), everything works just fine:
grunt.registerTask( 'build', [
'clean', 'html2js', 'jshint', 'sass:build',
'concat:build_css', 'copy:build_app_assets', 'copy:build_vendor_assets',
'copy:build_appjs', 'copy:build_vendorjs', 'copy:build_vendorcss', 'index:build', 'karmaconfig',
'karma:continuous'
]);
So maybe ngAnnotate or or concat/uglify are doing weird things here?
UPDATE 1:
It has something to do with my configuration of the modules. Here is the code:
angular
.module('controlcenter.websites',
[
'ui.router'
]
)
.config(config);
config.$inject = ['$stateProvider'];
function config($stateProvider) {
$stateProvider.state( 'websites', {
url: '/websites',
views: {
"main": {
controller: 'WebsitesController',
templateUrl: 'websites/websites.tpl.html'
}
}
});
}
When I change the name of the state to websites_2, I get an error
with 'websites_2 is already defined'.
When I remove the module completely, the next one hast the same problem inside the config file. So is the structure wrong?
Update 2:
The problem seems concat related.
It takes every JS file and adds it one after another to one, bigger file. All of my modules are at the end. The last module always has the problem with 'state already defined'. So it's not just the order of the modules appending to each other, it's something elsse...
Update 3:
I placed my code (I've excluded every Controller-Code and functions, just the scaffold) in a gist. This is the outcome after my compile process, without uglifying it.
Issue:
You have multiple files that contains a config function to configure your module, like this:
angular
.module('controlcenter.websites', [])
.config(config);
function config() {
// ...
}
The problem is that after you concatenate all files you end up with a big file with multiple declarations of config. Because of JavaScript's variable hoisting, all declarations are moved to the top and only the very last of them is evaluated, and this one is:
function config($stateProvider) {
$stateProvider.state( 'websites', {
url: '/websites',
views: {
"main": {
controller: 'WebsitesController',
templateUrl: 'websites/overview/websites.tpl.html'
}
},
data : {requiresLogin : true }
});
}
Hence, each time you .config(config) a module, you are telling Angular to configure your module with that particular configuration function, which means that it executes multiple times and tries to define the state websites more than once.
Solution:
Wrap each JavaScript file code with a closure. This way you will avoid declaring a variable/function more than once:
(function (angular) {
'use strict';
angular
.module('controlcenter.website.details', ['ui.router'])
.config(config);
config.$inject = ['$stateProvider'];
function config($stateProvider) {
$stateProvider
.state( 'websiteDetails', {
url: '/websiteDetails/:id',
views: {
"main": {
controller: 'WebsiteDetailsController',
templateUrl: 'websites/details/website.details.tpl.html'
}
},
data : {requiresLogin : true }
})
.state( 'websiteDetails.categories', {
url: '/categories',
views: {
"detailsContent": {
templateUrl: 'websites/details/website.details.categories.tpl.html'
}
},
data : {requiresLogin : true }
})
;
}
})(window.angular);
Edit:
I strongly recommend you wrap your files into closures. However, if you still don't want to do that, you can name your functions according to their respective modules. This way your configuration function for controlcenter.website.details would become controlcenterWebsiteDetailsConfig. Another option is to wrap your code during build phase with grunt-wrap.
window.angular and closures: This is a technique I like to use on my code when I'm going to uglify it. By wrapping your code into a closure and giving it a parameter called angular with the actual value of window.angular you are actually creating a variable that can be uglified. This code, for instance:
(function (angular) {
// You could also declare a variable, instead of a closure parameter:
// var angular = window.angular;
angular.module('app', ['controllers']);
angular.module('controllers', []);
// ...
})(window.angular);
Could be easily uglified to this (notice that every reference to angular is replaced by a):
!function(a){a.module("app",["controllers"]),a.module("controllers",[])}(window.angular);
On the other side, an unwrapped code snippet like this:
angular.module('app', ['controllers']);
angular.module('controllers', []);
Would become:
angular.module("app",["controllers"]),angular.module("controllers",[]);
For more on closures, check this post and this post.
If you check it in the concatenated file, do you have the states defined twice? Can it be that you are copying the files twice? Check the temporary folders from where you are taking the files (also in grunt config, what you are copying and what you are deleting...).
So I had the same problem but with the following setup:
yeoman angular-fullstack (using typescript)
Webstorm
With the angular-fullstack configuration, the closures were already implemented (as Danilo Valente suggests) so I struggled quite a bit until I found out that in Webstorm, I had the typescript compiler enabled which compiled all of my *.ts files to *.js. But since Webstorm is so 'smart', it does not show these compiled files in the working tree. Grunt however concatenated of course all files regardless if it is typescript of JS. That's why - in the end- all of my states were defined twice.
So the obvious fix: Disabled typescript compiler of webstorm and deleted all the generated *.js files and it works.

Angular, Jasmine mock whole module dependiences," is not available!" error

In my module i have some dependiences:
var app = angular.module('action', ['xeditable']);
Angular-xeditable is a bundle of AngularJS directives that allows you to create editable elements. more: http://vitalets.github.io/angular-xeditable/
End no i my Jasmine test i want to mock all this module.
I was trying like this:
var mocks;
beforeEach(function() {
mocks = jasmine.createSpyObj("mocks", ["xeditable"]);
module("action", function($provide){
$provide.value('xeditable', mocks.xeditable)
});
});
but i still get:
Error: [$injector:nomod] Module 'xeditable' is not available!
I know that there were a lot of questions about it but do not know how to deal, very please help :)
i solved it, just added another beforeEach before load module, like that:
beforeEach(function () {
//mock the xeditable lib:
angular.module("xeditable", []);
});
beforeEach(function() {
module("action");
});

Injector error using Angulartics with AngularJS

I have problem with adding Angulartics.
In my app.js I just added that two dependencies (Angulartics and the last one) you can see:
var smsApp = angular.module('smsApp', [
'ngRoute',
'smsControllers',
'smsFilters',
'google-maps',
'pascalprecht.translate',
'angulartics',
'angulartics.google.analytics',
]);
and then in my index.html I added: <script src="./js/angulartics.js">
<script src="./js/angulartics-ga.js"> ---- paths to these files are ok
but when I want to create that module with:
var injector = angular.injector(['smsApp', 'ng']);
I got this error:
Uncaught Error: [$injector:unpr] http://errors.angularjs.org/1.2.15/$injector/unpr?p0=%24rootElementProvider%20%3C-%20%24rootElement%20%3C-%20%24location
Without Angulartics it goes well! Please help me :) thanks
I'm following this tutorial.
Assuming you're reading the docs here: https://github.com/angulartics/angulartics
You need to install the angularitics.google.analytics plugin by running 'bower install angulartics-google-analytics --save'
Why are you using injector?
If you're using injector, you're not using the regular AngularJS bootstrapping code, so $rootElement is not defined.
You could mock the object:
<script src="/path/to/angular-mock.js">
...
var injector = angular.injector(['smsApp', 'ngMock', 'ng']);
Or define it in your app explicitely
smsApp.config(['$provide', function($provide) {
// Should match the element that contains your ng-app="smsApp" attribute
$provide.value('$rootElement', angular.element(document.body));
}]);

Using OpenLayers with RequireJS and AngularJS

I'm trying to get an app running that uses both AngularJS and RequireJS. I'm having problems getting my OpenLayers lib to work in this setup.
I set the main AMD-modules in the main.js:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
openLayers: 'vendor/openlayers-debug',
other modules.....
},
shim: {
angular: {
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
other modules....
}
}
);
require(['openLayers',
'angular',
'app',
'controllers/olMapController',
'directives/olMap',
other modules...
], function(OpenLayers) {
return OpenLayers;
}
);
Then in the angular controller I use for the initialisation of OpenLayers, I try to indicate that openlayers-debug.js is a dependency:
define(['openLayers'],
function(OpenLayers) {
controllers.controller('olMapController', ['$scope', function(scope) {
console.log('Loaded olMapController. OpenLayers version: ' + OpenLayers.VERSION_NUMBER);
}]);
}
);
Well, this doesn't work. SOMETIMES the olMapController function is executed, but mostly not. The console then just displays an error stating:
Error: [ng:areq] Argument 'olMapController' is not a function, got undefined
So, I think OpenLayers hasn't finished loading yet, but somehow require thinks it has and continues loading code that depends on OpenLayers, in this case the olMapController. It then can't find its dependency, whereupon Angular returns this error message. Or something like that...? Sometimes something happens that makes OpenLayers load fast enought for it to be present when it is loaded as a dependency. What that is, I can't tell.
I left out other libraries and modules require and define to keep the code readable. I hope the example is still understandable.
Any ideas on what I could do to get openlayers to load well? The error message disappears when I leave the ['openLayers'] dependency out of olMapController.
Thanks in advance for any help.
Best regards,
Martijn Senden
Well, just for reference my final solution. The comment by angabriel set me off in the right direction.
Like i said, I'm using the domReady module provided by RequireJS to bootstrap Angular. This is still being called to early, because OpenLayers isn't loaded yet when angular starts. RequireJS also provides a callback property in require.config. This is a function that is triggered when all the dependencies are loaded. So I used that function to require the angular bootstrap module. My config now looks like this:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
domReady: 'vendor/domReady',
openLayers: 'vendor/openlayers-debug',
etcetera....
},
shim: {
angular: {
deps: ['jquery'],
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
},
deps: ['angular',
'openLayers',
'app',
'domReady',
'controllers/rootController',
'controllers/olMapController',
'directives/olMap'
],
callback: function() {
require(['bootstrap']);
}
}
);
And the bootstrap module looks like this:
define(['angular', 'domReady', 'app'], function(angular, domReady) {
domReady(function() {
angular.bootstrap(document, ['GRVP']);
});
});
Thanks for the help. #angabriel: I upvoted your comment. It's not possible to accept a comment as an answer, is it? Your initial answer wasn't really the answer to my question, but the comment helped a lot...
Regards, Martijn
Sorry this answer will only contain text as your code is too big for a small example.
I would suggest to write a directive that utilizes head.js to load libraries you need at a specific context. One could also think of a directive that initializes openLayers this way.
I guess your error is a timing problem, because the require.js and angular.js module loading gets out of sync - more precisely there seems to be no sync at all between them.
update
To repeat my comment which lastly helped to lead the OP in the right direction:
You have to decide which framework gives the tone. If you go with requireJS, then require everything and bootstrap angular manually. (Remove ng-app="" from index.html) and do `angular.bootstrap()ยด when requirejs has completed. So the problem most likely is, that angular starts too early.

Categories

Resources